EhBASIC LOAD and SAVE notes

The quickest and easiest way to save the program is to do this …

Type LIST but not the return ..
Set your terminal program to ASCII capture..
Hit return to start the LIST command..
Once the list is complete stop the ASCII capture.

To load the program back there are two possible, similar, ways.

If your hardware supports hardware handshake properly just select the listing and use ASCII send to transfer it (You’ll need to edit the ‘Ready’ prompt from the end of the listing).

If your hardware doesn’t support hardware handshaking then you’ll need to paste a number of SPACE characters at the start of each line to give the interpreter enough time to tokenise the previous line. The number of spaces depends on two things, how fast your processor is and how fast the serial link is. The faster the processor the fewer spaces, the faster the serial link the more spaces. Otherwise just do as above.

(Alternately edit the NULL command to insert $20’s instead of $00’s into the start of each line and do ..
NULL n
LIST
NULL 0
when you save the list)

If you want to save the program as binary you should save (Smeml) to (Svarl)-1.

If you want to save the program as ASCII you should redirect the character output vector to write to your filesystem and then call LIST. Doing this can also allow you to specify line numbers or ranges as with LIST. The output vector should be restored and the file closed when LIST returns or an error is encountered.

To load a binary program start loading it at (Smeml) and set (Svarl) to the last address + 1 then call LAB_1477 to clear the variables and reset the execution pointer. An easy way to do the first part is by copying (Smeml) to (Svarl) and using (Svarl) as a post incremented save pointer. If there is a chance that the program has been relocated it’s probably a good idea to rebuild the line pointer chain.

To load an ASCII program redirect the character input vector to read from your filesystem and return to the main interpreter loop. The input vector should be restored and the file closed when the file end is reached or an error is encountered.

I prefer ASCII format as it’s far more portable, easier to manipulate and can include direct commands and comment lines that aren’t saved to memory.

Is there an easy way to support a filename in the LOAD and save COMMANDs, and get access to that from my code? Right now I am prompting the user for it.

Call the evaluate following expression routine, LAB_EVEZ, and look for a string by testing if the data type flag, Dtypef, is negative. If it is the string descriptor is on the descriptor stack so don’t forget to pop it off there by calling LAB_22B6 once you’re done with it.

Look at Jeff Trantor’s implemention of LOAD and SAVE for the Apple 1 with a CFFA1 and for the OSI C1P via the serial line.

Daryl Rictor wrote a simple SAVE and LOAD program:

;******** LOAD & SAVE PATCH FOR ENHANCED BASIC ON 65C02 Simulator

psave    
    jsr  pscan
    ldy  #$00
    lda  itempl
    sta  (itempl),y
    iny
    lda  itemph
    sta  (itempl),y
    ldx  smeml
    lda  smemh
    jsr  print2byte
    jsr  print_cr
    sec
    lda  itempl
    sbc  smeml
    tax
    lda  itemph
    sbc  smemh
    jsr  print2byte
    jsr  print_cr
    rts

pload    
    jsr  pscan
    lda  itempl
    sta  svarl
    sta  sarryl
    sta  earryl
    lda  itemph
    sta  svarh
    sta  sarryh
    sta  earryh
    JMP   LAB_1319    
pscan
    lda  smeml
        sta  itempl
        lda  smemh
        sta  itemph
pscan1  ldy   #$00
    lda   (itempl),y
    bne   pscan2
    iny   
    lda   (itempl),y
    bne   pscan2
    clc
    lda   #$02
    adc   itempl
    sta  itempl
    lda  #$00
    adc  itemph
    sta  itemph
    rts
pscan2  ldy   #$00
    lda  (itempl),y
    tax
    iny
    lda  (itempl),y
    sta  itemph
    stx  itempl
    bra  pscan1

Another version of this:
;******** LOAD & SAVE PATCH FOR ENHANCED BASIC ON SBC-3
; Daryl Rictor, Feb 2009
;

.include dos.lbl      ; get DiskOS pointers
;input    ; sbc scanned input
;output    ; text output
;DiskOS    ; diskos entry
;SaveF    ; save program file from BASIC
;LoadF    ; load program file from BASIC

;ibuffs+1 ($420) contains the name, start addr, end address

psave    ldx  #$00
    lda  ibuffs+1
    stz  ibuffs+1  ; this fixes syntax error in ehbasic
    bne  psave15
    rts
psave1    lda  ibuffs+1,x
    stz  ibuffs+1,x  ; this fixes syntax error in ehbasic
    beq  psave3
psave15    cmp  #$b9
    bne  psave2
    lda  #"/"
psave2    sta  buffer+2,x
    inx
    cpx  #$46
    bne  psave1
    rts      ; entry too long, abort
psave3    lda  #","
    sta  buffer+2,x
    inx
    phx
    jsr  pscan    ; Find end of program
    plx
    lda  smemh
    jsr  ToHex
    lda  smeml
    jsr  ToHex
    lda  #","
    sta  buffer+2,x
    inx
    lda  itemph
    jsr  ToHex
    lda  itempl
    jsr  ToHex
    lda  #$00
    sta  buffer+2,x
    jsr  SaveF    ; save file to IDE (in DiskOS)
    rts

pload    ldx  #$00
    lda  ibuffs+1
    stz  ibuffs+1  ; this fixes syntax error in ehbasic
    bne  pload15
    rts
pload1    lda  ibuffs+1,x
    beq  pload3
pload15    cmp  #$b9
    bne  pload2
    lda  #"/"
pload2    sta  buffer+2,x
    inx
    cpx  #$47
    bne  pload1
    rts      ; entry too long, abort
pload3    lda  #$00
    sta  buffer+2,x
    jsr  Loadf    ; load file from IDE (in DiskOS)
    jsr  pscan
    lda  itempl
    sta  svarl
    sta  sarryl
    sta  earryl
    lda  itemph
    sta  svarh
    sta  sarryh
    sta  earryh
    JMP   LAB_1319    

pscan
    lda  smeml
          sta  itempl
          lda  smemh
          sta  itemph
pscan1    ldy   #$00
    lda   (itempl),y
    bne   pscan2
    iny   
    lda   (itempl),y
    bne   pscan2
    clc
    lda   #$02
    adc   itempl
    sta  itempl
    lda  #$00
    adc  itemph
    sta  itemph
    rts
pscan2    ldy   #$00
    lda  (itempl),y
    tax
    iny
    lda  (itempl),y
    sta  itemph
    stx  itempl
    bra  pscan1

SysJMP    JSR  Main_Loop  ; in DiskOS
    rts

ToHex    PHA                     ;  prints AA hex digits
    LSR                     ;  MOVE UPPER NIBBLE TO LOWER
    LSR                     ;
    LSR                     ;
    LSR                     ;
    JSR   SaveDig           ;
    PLA                     ;
SaveDig    AND   #$0F              ;
    CMP   #$0A              ;
    BCC   SaveDig1          ;
    ADC   #$66              ;
SaveDig1  EOR   #$30              ;
    sta   buffer+2,x        ;
    inx
    rts

And another approach:

There seems to be quite a lot of mixed information about how to deal with string arguments in LOAD and SAVE. I’d like to present the way I came up with:
At the beginning of either LOAD and SAVE, i call a subroutine that gets the string argument using LAB_EVEX and opens the file:

openfile:
                jsr LAB_EVEX
                lda Dtypef
                bne @go
                ; not a string, trigger syntax error
                ldx #$02
                jsr LAB_XERR
@go:
                ldy #$00
@l:
                lda (ssptr_l),y
                beq @open
                cmp #'"'
                beq @term
                iny
                bne @l
@term:
                lda #$00
                sta (ssptr_l),y
@open:
                lda ssptr_l
                ldx ssptr_h
                jsr krn_open
                bne     io_error
                rts
io_error:
                pha
                jsr     krn_primm
                .asciiz "io error: "
                pla
                jmp krn_hexout

As it seems, after calling LAB_EVEX, ssptr points to the string given as parameter including the closing “, which I overwrite with $00 to be compatible with my open routine, which expects the address of a null terminated string.
In another thread, it was suggested to pop the string from the descriptor stack using LAB_22B6, which in my case resulted in ut1_ph/l not pointing to the string, but anywhere in the area of $exxx, where my os resides. So I went for the above approach. It works, but it feels rather dirty due to the overwriting of the closing “. At this point, I am open for suggestions.