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.