This commit is contained in:
Joshua Bell 2019-01-06 20:26:58 -08:00
parent 42dc31e40e
commit ed1277cc4d

171
path.s
View File

@ -8,6 +8,8 @@
.org $2000
.include "apple2.inc"
.include "apple2.mac"
.include "prodos.inc"
;;; ============================================================
@ -20,7 +22,20 @@ INBUF := $200 ; GETLN input buffer
CROUT := $FD8E
COUT := $FDED
MOVE := $FE2C ; call with Y=0
MOVE_SRC := $3C
MOVE_END := $3E
MOVE_DST := $42
TOKEN_NAME_TABLE := $D0D0
CASE_MASK = $DF
;;; ============================================================
;;; Install the new command
;; TODO: Fail if Applesoft is not in ROM
;; Save previous external command address
lda EXTRNCMD+1
@ -28,34 +43,54 @@ COUT := $FDED
lda EXTRNCMD+2
sta next_command+1
;; Request a 1-page buffer
lda #1
;; Request a 2-page buffer
lda #2
jsr GETBUFR
bcc :+
lda #$C ; NO BUFFERS AVAILABLE
rts
:
;; A = MSB of new page - update absolute addresses
;; (aligned to page boundary so only MSB changes)
: sta new_page ; A = MSB of new page
;; Compute move delta in pages
lda #>handler
sec
sbc new_page
sta page_delta
;; Relocatable routine is aligned to page boundary so only MSB changes
ldx relocation_table
: ldy relocation_table+1,x
lda handler,y
clc
adc page_delta
sta handler,y
dex
bpl :-
;; Relocate
lda #<handler
sta MOVE_SRC
lda #>handler
sta MOVE_SRC+1
lda #<handler_end
sta MOVE_END
lda #>handler_end
sta MOVE_END+1
lda #0
sta MOVE_DST
lda new_page
sta MOVE_DST+1
ldy #0
jsr MOVE
;; Install new address in external command address
lda new_page
sta EXTRNCMD+2
lda #0
sta EXTRNCMD+1
;; Relocate
ldx #0
: lda handler,x
page_num3 := *+2
sta $2100,x ; self-modified
inx
bne :-
;; Complete
rts
@ -68,21 +103,19 @@ COUT := $FDED
.res $2100 - *, 0
.proc handler
ptr := $06
;; Check for this command, character by character.
ldx #0
nxtchr: lda INBUF,x
;; TODO: skip leading spaces
and #$7F ; Convert to ASCII
cmp #'a' ; Convert to upper-case
bcc :+
cmp #'z'+1
bcs :+
and #$DF
nxtchr: lda INBUF,x
page_num6 := *+2 ; address needing updating
jsr to_upper
page_num1 := *+2 ; address needing updating
: cmp command_string,x
bne not_path
cmp command_string,x
bne check_if_token
inx
cpx #command_length
bne nxtchr
@ -115,15 +148,75 @@ nxtchr: lda INBUF,x
;;; ============================================================
not_path:
check_if_token:
;; Ensure it's alpha
lda INBUF
page_num7 := *+2 ; address needing updating
jsr to_upper
cmp #'A'|$80
bcc not_ours
cmp #('Z'+1)|$80
bcs not_ours
;; Check if it's a BASIC token. Based on the AppleSoft BASIC source.
;; Point ptr at TOKEN_NAME_TABLE less one page (will advance below)
lda #<(TOKEN_NAME_TABLE-$100)
sta ptr
lda #>(TOKEN_NAME_TABLE-$100)
sta ptr+1
;; These start at "-1" and are immediately incremented
ldx #$FF ; X = position in input line
ldy #$FF ; (ptr),y offset TOKEN_NAME_TABLE
;; Match loop
mloop: iny ; Advance through token table
bne :+
inc ptr+1
: inx
;; Check for match
next_char:
lda INBUF,x ; Next character
page_num8 := *+2 ; address needing updating
jsr to_upper
;; NOTE: Does not skip over spaces, unlike BASIC tokenizer
sec ; Compare by subtraction..
sbc (ptr),Y
beq mloop
cmp #$80 ; If only difference was the high bit
beq not_ours ; then it's end-of-token -- and a match!
;; Otherwise, advance to next token
next_token:
ldx #0 ; Start next match at start of input line
;; TODO: skip leading spaces
@loop: lda (ptr),y ; Scan table looking for a high bit set
iny
bne :+
inc ptr+1
: asl
bcc @loop ; High bit clear, keep looking
lda (ptr),y ; End of table?
bne next_char ; Nope, check for a match
;; Not a keyword, so invoke
not_a_token:
;; TODO: Implement me!
;;; ============================================================
not_ours:
sec ; Signal failure...
next_command := *+1
jmp $ffff ; Execute next command in chain
;;; ============================================================
;;; ============================================================
execute:
@ -137,10 +230,10 @@ execute:
;; Show current path
ldx #0
page_num3 := *+2
page_num3 := *+2 ; address needing updating
: cpx path_buffer
beq done
page_num4 := *+2
page_num4 := *+2 ; address needing updating
lda path_buffer+1,x
ora #$80
jsr COUT
@ -154,7 +247,6 @@ done: clc
;;; --------------------------------------------------
;; Set path
set_path:
ptr := $06
lda VPATH1
sta ptr
ldx VPATH1+1
@ -164,27 +256,43 @@ set_path:
lda (ptr),y
tay
: lda (ptr),y
page_num5 := *+2
page_num5 := *+2 ; address needing updating
sta path_buffer,y
dey
bpl :-
clc
rts
;;; ============================================================
;;; Helpers
.proc to_upper
cmp #'a'|$80
bcc skip
and #CASE_MASK
skip: rts
.endproc
;;; ============================================================
;;; Data
command_string:
.byte "PATH" ; Command string
scrcode "PATH"
command_length = *-command_string
path_buffer:
.res 65, 0
.endproc
.assert .sizeof(handler) <= $100, error, "Must fit on one page"
.assert .sizeof(handler) <= $200, error, "Must fit on two pages"
handler_end := *-1
next_command := handler::next_command
new_page:
.byte 0
page_delta:
.byte 0
relocation_table:
.byte 5
.byte <handler::page_num1
@ -192,3 +300,6 @@ relocation_table:
.byte <handler::page_num3
.byte <handler::page_num4
.byte <handler::page_num5
.byte <handler::page_num6
.byte <handler::page_num7
.byte <handler::page_num8