320 lines
9.8 KiB
ArmAsm
320 lines
9.8 KiB
ArmAsm
.segment "CODE"
|
|
|
|
LOADSAVE_LFN = $FF
|
|
|
|
; ============================================================================
|
|
; COPY STRING EXPRESSION TO FILE_NAME_BUFFER
|
|
;
|
|
; Entry:
|
|
; TXTPTR points at string expression
|
|
;
|
|
; Exit:
|
|
; FILE_NAME_BUFFER contains NUL-terminated filename
|
|
;
|
|
; Clobbers:
|
|
; A,X,Y,INDEX,STRNG2
|
|
; ============================================================================
|
|
PARSE_LOADSAVE_FILENAME:
|
|
jsr FRMEVL
|
|
jsr CHKSTR
|
|
jsr FREFAC
|
|
; FREFAC:
|
|
; A = length
|
|
; INDEX = string address
|
|
sta STRNG2
|
|
ldy #$00
|
|
@copy:
|
|
cpy STRNG2
|
|
beq @done
|
|
lda (INDEX),y
|
|
sta FILE_NAME_BUFFER,y
|
|
iny
|
|
bne @copy
|
|
@done:
|
|
lda #$00
|
|
sta FILE_NAME_BUFFER,y
|
|
rts
|
|
|
|
; ============================================================================
|
|
; SET UP THE COMMON FILE ARGUMENTS
|
|
; ============================================================================
|
|
LOADSAVE_SET_FILE:
|
|
lda #LOADSAVE_LFN
|
|
sta IO_FILE_DESCRIPTOR
|
|
lda #<FILE_NAME_BUFFER
|
|
sta IO_FILE_DATA
|
|
lda #>FILE_NAME_BUFFER
|
|
sta IO_FILE_DATA+1
|
|
rts
|
|
|
|
; ============================================================================
|
|
; WAIT FOR FILE COMMAND COMPLETION
|
|
;
|
|
; Jumps to IQERR on host-side failure.
|
|
; ============================================================================
|
|
LOADSAVE_WAIT:
|
|
lda IO_FILE_STATUS
|
|
and #FILE_STATUS_READY
|
|
beq LOADSAVE_WAIT
|
|
lda IO_FILE_STATUS
|
|
and #FILE_STATUS_ERROR
|
|
beq @ok
|
|
jmp IQERR
|
|
@ok:
|
|
rts
|
|
|
|
|
|
; ============================================================================
|
|
; OPEN FOR READING
|
|
; ============================================================================
|
|
LOADSAVE_OPEN_R:
|
|
jsr LOADSAVE_SET_FILE
|
|
lda #IO_COMMAND_OPEN_R
|
|
sta IO_FILE_COMMAND
|
|
jmp LOADSAVE_WAIT
|
|
|
|
; ============================================================================
|
|
; OPEN FOR WRITING / TRUNCATE
|
|
; ============================================================================
|
|
LOADSAVE_OPEN_W:
|
|
jsr LOADSAVE_SET_FILE
|
|
lda #IO_COMMAND_OPEN_W
|
|
sta IO_FILE_COMMAND
|
|
jmp LOADSAVE_WAIT
|
|
|
|
; ============================================================================
|
|
; CLOSE INTERNAL LOAD/SAVE FILE
|
|
; ============================================================================
|
|
LOADSAVE_CLOSE:
|
|
lda #LOADSAVE_LFN
|
|
sta IO_FILE_DESCRIPTOR
|
|
lda #IO_COMMAND_CLOSE
|
|
sta IO_FILE_COMMAND
|
|
jsr LOADSAVE_WAIT
|
|
jsr CLRCH
|
|
rts
|
|
|
|
; ============================================================================
|
|
; SAVE "filename"
|
|
;
|
|
; Saves plain ASCII BASIC source, equivalent to LIST output.
|
|
; ============================================================================
|
|
SAVE:
|
|
jsr PARSE_LOADSAVE_FILENAME
|
|
jsr LOADSAVE_OPEN_W
|
|
; Route OUTDO/CHROUT to our internal file.
|
|
ldx #LOADSAVE_LFN
|
|
jsr CHKOUT
|
|
stx CURDVC
|
|
; Start with first BASIC line.
|
|
lda TXTTAB
|
|
sta LOWTRX
|
|
lda TXTTAB+1
|
|
sta LOWTRX+1
|
|
SAVE_NEXT_LINE:
|
|
; The high byte of the forward link is zero at end of program.
|
|
ldy #$01
|
|
lda (LOWTRX),y
|
|
beq SAVE_DONE
|
|
; ------------------------------------------------------------
|
|
; Print line number.
|
|
;
|
|
; record:
|
|
; +0/+1 = next line
|
|
; +2/+3 = line number
|
|
; +4... = tokenized body
|
|
; ------------------------------------------------------------
|
|
iny ; Y=2
|
|
lda (LOWTRX),y
|
|
tax
|
|
iny ; Y=3
|
|
lda (LOWTRX),y
|
|
jsr LINPRT
|
|
lda #' '
|
|
jsr OUTDO
|
|
; DATAFLG follows LIST's quoting/token rules.
|
|
lda #$01
|
|
sta DATAFLG
|
|
ldy #$04
|
|
SAVE_LINE_CHAR:
|
|
lda (LOWTRX),y
|
|
beq SAVE_LINE_DONE
|
|
; Test whether it's plain ASCII/token BEFORE doing CMPs
|
|
bpl SAVE_PLAIN_CHAR
|
|
cmp #$FF
|
|
beq SAVE_PLAIN_CHAR
|
|
bit DATAFLG
|
|
bmi SAVE_PLAIN_CHAR
|
|
; Token
|
|
sec
|
|
sbc #$7F
|
|
tax
|
|
sty FORPNT
|
|
ldy #$FF
|
|
SAVE_FIND_TOKEN:
|
|
dex
|
|
beq SAVE_TOKEN_FOUND
|
|
SAVE_SKIP_TOKEN:
|
|
iny
|
|
lda TOKEN_NAME_TABLE,y
|
|
bpl SAVE_SKIP_TOKEN
|
|
bmi SAVE_FIND_TOKEN
|
|
SAVE_TOKEN_FOUND:
|
|
iny
|
|
lda TOKEN_NAME_TABLE,y
|
|
bmi SAVE_TOKEN_LAST
|
|
jsr OUTDO
|
|
bne SAVE_TOKEN_FOUND
|
|
SAVE_TOKEN_LAST:
|
|
and #$7F
|
|
jsr OUTDO
|
|
ldy FORPNT
|
|
iny
|
|
jmp SAVE_LINE_CHAR
|
|
SAVE_PLAIN_CHAR:
|
|
and #$7F
|
|
jsr OUTDO
|
|
; Quote state must be updated AFTER output/test.
|
|
cmp #$22
|
|
bne SAVE_PLAIN_DONE
|
|
lda DATAFLG
|
|
eor #$FF
|
|
sta DATAFLG
|
|
SAVE_PLAIN_DONE:
|
|
iny
|
|
jmp SAVE_LINE_CHAR
|
|
SAVE_LINE_DONE:
|
|
; Every saved source line ends in LF.
|
|
jsr LFDO
|
|
; Follow next-line pointer.
|
|
ldy #$00
|
|
lda (LOWTRX),y
|
|
tax
|
|
iny
|
|
lda (LOWTRX),y
|
|
stx LOWTRX
|
|
sta LOWTRX+1
|
|
jmp SAVE_NEXT_LINE
|
|
SAVE_DONE:
|
|
jsr LOADSAVE_CLOSE
|
|
rts
|
|
|
|
; ============================================================================
|
|
; LOAD "filename"
|
|
;
|
|
; Replaces current program.
|
|
; Reads ASCII source one line at a time, tokenizes through the normal
|
|
; BASIC parser, and inserts using NUMBERED_LINE.
|
|
;
|
|
; IMPORTANT:
|
|
; NUMBERED_LINE eventually reaches FIX_LINKS -> SETPTRS -> STKINI, which
|
|
; resets the hardware stack. Therefore LOAD cannot expect NUMBERED_LINE to
|
|
; return with RTS. FIX_LINKS jumps back to LOAD_NEXT_LINE while LOAD_ACTIVE
|
|
; is set.
|
|
; ============================================================================
|
|
|
|
LOAD:
|
|
; Copy the filename before SCRTCH destroys temporary strings.
|
|
jsr PARSE_LOADSAVE_FILENAME
|
|
jsr LOADSAVE_OPEN_R
|
|
; Delete current program.
|
|
jsr SCRTCH
|
|
; Route CHRIN to the file.
|
|
ldx #LOADSAVE_LFN
|
|
jsr CHKIN
|
|
stx CURDVC
|
|
; Tell FIX_LINKS that program insertion belongs to LOAD.
|
|
lda #$01
|
|
sta LOAD_ACTIVE
|
|
; ----------------------------------------------------------------------------
|
|
; Entry point used both initially and by FIX_LINKS after inserting each line.
|
|
; Must be a globally visible label if FIX_LINKS lives in another source file.
|
|
; ----------------------------------------------------------------------------
|
|
LOAD_NEXT_LINE:
|
|
ldx #$00
|
|
; ----------------------------------------------------------------------------
|
|
; Read one physical source line into INPUTBUFFER.
|
|
;
|
|
; "10 PRINT 1\n" -> normal line
|
|
; "10 PRINT 1"<EOF> -> final line still accepted
|
|
; EOF with X=0 -> done loading
|
|
; ----------------------------------------------------------------------------
|
|
@read_char:
|
|
jsr CHRIN
|
|
; If host says EOF, A is not considered valid data.
|
|
pha
|
|
lda IO_FILE_STATUS
|
|
and #FILE_STATUS_EOF
|
|
bne @eof
|
|
pla
|
|
; LF terminates a source line.
|
|
cmp #LF
|
|
beq @line_complete
|
|
; Accept CRLF files too.
|
|
cmp #$0D
|
|
beq @read_char
|
|
; Same practical line limit as interactive INLIN.
|
|
cpx #$47
|
|
bcs @line_too_long
|
|
sta INPUTBUFFER,x
|
|
inx
|
|
jmp @read_char
|
|
@eof:
|
|
pla
|
|
; EOF with no accumulated characters means real end of file.
|
|
cpx #$00
|
|
beq @load_done
|
|
; Otherwise process the unterminated final line.
|
|
@line_complete:
|
|
lda #$00
|
|
sta INPUTBUFFER,x
|
|
; Point CHRGET at INPUTBUFFER-1, exactly like INLIN returns.
|
|
lda #<(INPUTBUFFER-1)
|
|
sta TXTPTR
|
|
lda #>(INPUTBUFFER-1)
|
|
sta TXTPTR+1
|
|
jsr CHRGET
|
|
; Ignore empty physical lines.
|
|
beq LOAD_NEXT_LINE
|
|
; A source file must consist of numbered program lines.
|
|
;
|
|
; CHRGET leaves carry clear for a leading decimal digit,
|
|
; exactly like the normal RESTART path.
|
|
bcc @numbered
|
|
jmp @syntax_error
|
|
@numbered:
|
|
; NUMBERED_LINE performs:
|
|
;
|
|
; LINGET
|
|
; PARSE_INPUT_LINE
|
|
; FNDLIN
|
|
; PUT_NEW_LINE
|
|
; FIX_LINKS
|
|
;
|
|
; DO NOT JSR here.
|
|
;
|
|
; FIX_LINKS eventually calls SETPTRS/STKINI, which resets the
|
|
; hardware stack. FIX_LINKS will detect LOAD_ACTIVE and jump back
|
|
; to LOAD_NEXT_LINE.
|
|
jmp NUMBERED_LINE
|
|
@line_too_long:
|
|
@syntax_error:
|
|
lda #$00
|
|
sta LOAD_ACTIVE
|
|
|
|
jsr CLRCH
|
|
jsr LOADSAVE_CLOSE
|
|
jmp SYNERR
|
|
@load_done:
|
|
lda #$00
|
|
sta LOAD_ACTIVE
|
|
jsr CLRCH
|
|
jsr LOADSAVE_CLOSE
|
|
; Do NOT JSR SETPTRS here.
|
|
;
|
|
; Every successfully inserted line already passed through
|
|
; FIX_LINKS -> SETPTRS -> LE33D.
|
|
;
|
|
; Also do not RTS: SETPTRS/STKINI during loading may have destroyed
|
|
; the original LOAD command's return frame.
|
|
jmp RESTART |