The disassembled code here is from
Commodore 64 ROM.
The comments and intermediate labels
are mine.
Together they are useful.
Placing this here as is for reference.
I found this exercise necessary when
implementing my hires extensions for C64
including a patch of this routine.
; C64 crunch is A57C-A612
; C64 tokens are A09E-A19D
crunch ; from C64 ROM
; INPUT: PETASCII of entered line is at buffer $0200, ending with #$00 null character
; OUTPUT: tokenizes in place entire line, ending line with #$00 null character
; HINT: because of tokens, result is smaller than original so can modify in place
LDX $7A ; source buffer index
LDY #$04 ; storage index starts at 4 (4+$1FB+1 = $200)
STY $0F ; set not DATA flag (4=NOT, 0=DATA)
.go LDA $0200,X ; retrieve next character from input buffer
BPL .lowch ; branch if 00-7F
CMP #$FF ; PI?
BEQ .store ; branch if PI, already tokenized
INX ; advance source index
BNE .go ; always skip initial character 80-FE, as X shouldn't ever wrap to 0
.lowch CMP #$20 ; compare to ASCII space
BEQ .store ; branch if space, store literal
STA $08 ; no, store character, non-zero = not REMark
CMP #$22 ; compare to ASCII quote
BEQ .literal ; branch if string, store literal characters instead of matchng tokens
BIT $0F ; test if in DATA statement
BVS .store ; branch if in DATA statement, store literal characters instead of matching tokens
CMP #$3F ; compare to ASCII question mark
BNE .chkzero ; no, skip next part
LDA #$99 ; replace question mark with token PRINT
BNE .store ; unconditional branch, store token
.chkzero CMP #$30 ; compare to ASCII zero digit
BCC .scantbl ; branch if less
CMP #$3C ; compare to ASCII less than
BCC .store ; branch if less, so branch if numeric or colon or semi-colon, store literal character
.scantbl STY $71 ; save storage offset index
LDY #$00 ; initialize token table byte index to zero
STY $0B ; initialize token number to zero
DEY ; cancel out the next increment for loop beginning with decrement
STX $7A ; save source index
DEX ; cancel out the next increment for loop beginning with decrement
.advance INY ; advance token table index
INX ; advance source index
.scanch LDA $0200,X ; retrieve character from buffer
SEC ; prepare for subtraction
SBC $A09E,Y ; compare to Commodore token table
BEQ .advance ; branch if character match, look for more matches
CMP #$80 ; end of token?
BNE .scannxt ; branch if not end of token, mismatch, so get ready to check next token
ORA $0B ; match! combine zero based token number with $80 high bit set for storage
.storaty LDY $71 ; retrive storage offset index
.store INX ; advance input index
INY ; advance output index
STA $01FB,Y ; store token or character
LDA $01FB,Y ; set Z flag if end of line
BEQ .endline ; branch if end of line, finish up
SEC ; prepare for subtraction
SBC #$3A ; subtract ASCII colon
BEQ .setf ; branch if colon
CMP #$49 ; DATA?
BNE .skipset ; skip setting flag if not DATA
.setf STA $0F ; $49 if DATA, or $00 if colon
.skipset SEC ; prepare for subtraction
SBC #$55 ; REM?
BNE .go ; branch if not REM to get next character
STA $08 ; store flag zero = REM
.litloop LDA $0200,X ; retrieve next character from input
BEQ .store ; branch if end of line
CMP $08 ; compare to token that got us in this loop (e.g. 0x22 quote), or 0x00 (REM)
BEQ .store ; branch if REMark end of line
.literal INY ; advance destination index
STA $01FB,Y ; store in buffer
INX ; advance source index
BNE .litloop ; repeat getting next character
.scannxt LDX $7A ; retrieve source index
INC $0B ; advance token number
.endtok INY ; advance destination index
LDA $A09D,Y ; retrieve character from token table
BPL .endtok ; loop until find end of token
LDA $A09E,Y ; retrieve next character from token table
BNE .scanch ; branch if not end of token table
LDA $0200,X ; re-retrieve character from input buffer
BPL .storaty ; branch if character 00-7F, should be if got here, no token match
.endline STA $01FD,Y ; store end of line nul character $00
DEC $7B ; update TXTPTR
LDA #$FF ; to point to
STA $7A ; $01FF
crunch_finish:
RTS ; done
No comments:
Post a Comment