6502_EhBASIC_V2.22/basic.asm
Klaus2m5 54117e62a6 redistribution
The original EhBASIC website is unavailable at this time. This
repository restores the availability of the original EhBASIC source and
documentation.
2013-10-26 17:04:12 +02:00

8692 lines
244 KiB
NASM

; Enhanced BASIC to assemble under 6502 simulator, $ver 2.22
; $E7E1 $E7CF $E7C6 $E7D3 $E7D1 $E7D5 $E7CF $E81E $E825
; 2.00 new revision numbers start here
; 2.01 fixed LCASE$() and UCASE$()
; 2.02 new get value routine done
; 2.03 changed RND() to galoise method
; 2.04 fixed SPC()
; 2.05 new get value routine fixed
; 2.06 changed USR() code
; 2.07 fixed STR$()
; 2.08 changed INPUT and READ to remove need for $00 start to input buffer
; 2.09 fixed RND()
; 2.10 integrated missed changes from an earlier version
; 2.20 added ELSE to IF .. THEN and fixed IF .. GOTO <statement> to cause error
; 2.21 fixed IF .. THEN RETURN to not cause error
; 2.22 fixed RND() breaking the get byte routine
; zero page use ..
LAB_WARM = $00 ; BASIC warm start entry point
Wrmjpl = LAB_WARM+1; BASIC warm start vector jump low byte
Wrmjph = LAB_WARM+2; BASIC warm start vector jump high byte
Usrjmp = $0A ; USR function JMP address
Usrjpl = Usrjmp+1 ; USR function JMP vector low byte
Usrjph = Usrjmp+2 ; USR function JMP vector high byte
Nullct = $0D ; nulls output after each line
TPos = $0E ; BASIC terminal position byte
TWidth = $0F ; BASIC terminal width byte
Iclim = $10 ; input column limit
Itempl = $11 ; temporary integer low byte
Itemph = Itempl+1 ; temporary integer high byte
nums_1 = Itempl ; number to bin/hex string convert MSB
nums_2 = nums_1+1 ; number to bin/hex string convert
nums_3 = nums_1+2 ; number to bin/hex string convert LSB
Srchc = $5B ; search character
Temp3 = Srchc ; temp byte used in number routines
Scnquo = $5C ; scan-between-quotes flag
Asrch = Scnquo ; alt search character
XOAw_l = Srchc ; eXclusive OR, OR and AND word low byte
XOAw_h = Scnquo ; eXclusive OR, OR and AND word high byte
Ibptr = $5D ; input buffer pointer
Dimcnt = Ibptr ; # of dimensions
Tindx = Ibptr ; token index
Defdim = $5E ; default DIM flag
Dtypef = $5F ; data type flag, $FF=string, $00=numeric
Oquote = $60 ; open quote flag (b7) (Flag: DATA scan; LIST quote; memory)
Gclctd = $60 ; garbage collected flag
Sufnxf = $61 ; subscript/FNX flag, 1xxx xxx = FN(0xxx xxx)
Imode = $62 ; input mode flag, $00=INPUT, $80=READ
Cflag = $63 ; comparison evaluation flag
TabSiz = $64 ; TAB step size (was input flag)
next_s = $65 ; next descriptor stack address
; these two bytes form a word pointer to the item
; currently on top of the descriptor stack
last_sl = $66 ; last descriptor stack address low byte
last_sh = $67 ; last descriptor stack address high byte (always $00)
des_sk = $68 ; descriptor stack start address (temp strings)
; = $70 ; End of descriptor stack
ut1_pl = $71 ; utility pointer 1 low byte
ut1_ph = ut1_pl+1 ; utility pointer 1 high byte
ut2_pl = $73 ; utility pointer 2 low byte
ut2_ph = ut2_pl+1 ; utility pointer 2 high byte
Temp_2 = ut1_pl ; temp byte for block move
FACt_1 = $75 ; FAC temp mantissa1
FACt_2 = FACt_1+1 ; FAC temp mantissa2
FACt_3 = FACt_2+1 ; FAC temp mantissa3
dims_l = FACt_2 ; array dimension size low byte
dims_h = FACt_3 ; array dimension size high byte
TempB = $78 ; temp page 0 byte
Smeml = $79 ; start of mem low byte (Start-of-Basic)
Smemh = Smeml+1 ; start of mem high byte (Start-of-Basic)
Svarl = $7B ; start of vars low byte (Start-of-Variables)
Svarh = Svarl+1 ; start of vars high byte (Start-of-Variables)
Sarryl = $7D ; var mem end low byte (Start-of-Arrays)
Sarryh = Sarryl+1 ; var mem end high byte (Start-of-Arrays)
Earryl = $7F ; array mem end low byte (End-of-Arrays)
Earryh = Earryl+1 ; array mem end high byte (End-of-Arrays)
Sstorl = $81 ; string storage low byte (String storage (moving down))
Sstorh = Sstorl+1 ; string storage high byte (String storage (moving down))
Sutill = $83 ; string utility ptr low byte
Sutilh = Sutill+1 ; string utility ptr high byte
Ememl = $85 ; end of mem low byte (Limit-of-memory)
Ememh = Ememl+1 ; end of mem high byte (Limit-of-memory)
Clinel = $87 ; current line low byte (Basic line number)
Clineh = Clinel+1 ; current line high byte (Basic line number)
Blinel = $89 ; break line low byte (Previous Basic line number)
Blineh = Blinel+1 ; break line high byte (Previous Basic line number)
Cpntrl = $8B ; continue pointer low byte
Cpntrh = Cpntrl+1 ; continue pointer high byte
Dlinel = $8D ; current DATA line low byte
Dlineh = Dlinel+1 ; current DATA line high byte
Dptrl = $8F ; DATA pointer low byte
Dptrh = Dptrl+1 ; DATA pointer high byte
Rdptrl = $91 ; read pointer low byte
Rdptrh = Rdptrl+1 ; read pointer high byte
Varnm1 = $93 ; current var name 1st byte
Varnm2 = Varnm1+1 ; current var name 2nd byte
Cvaral = $95 ; current var address low byte
Cvarah = Cvaral+1 ; current var address high byte
Frnxtl = $97 ; var pointer for FOR/NEXT low byte
Frnxth = Frnxtl+1 ; var pointer for FOR/NEXT high byte
Tidx1 = Frnxtl ; temp line index
Lvarpl = Frnxtl ; let var pointer low byte
Lvarph = Frnxth ; let var pointer high byte
prstk = $99 ; precedence stacked flag
comp_f = $9B ; compare function flag, bits 0,1 and 2 used
; bit 2 set if >
; bit 1 set if =
; bit 0 set if <
func_l = $9C ; function pointer low byte
func_h = func_l+1 ; function pointer high byte
garb_l = func_l ; garbage collection working pointer low byte
garb_h = func_h ; garbage collection working pointer high byte
des_2l = $9E ; string descriptor_2 pointer low byte
des_2h = des_2l+1 ; string descriptor_2 pointer high byte
g_step = $A0 ; garbage collect step size
Fnxjmp = $A1 ; jump vector for functions
Fnxjpl = Fnxjmp+1 ; functions jump vector low byte
Fnxjph = Fnxjmp+2 ; functions jump vector high byte
g_indx = Fnxjpl ; garbage collect temp index
FAC2_r = $A3 ; FAC2 rounding byte
Adatal = $A4 ; array data pointer low byte
Adatah = Adatal+1 ; array data pointer high byte
Nbendl = Adatal ; new block end pointer low byte
Nbendh = Adatah ; new block end pointer high byte
Obendl = $A6 ; old block end pointer low byte
Obendh = Obendl+1 ; old block end pointer high byte
numexp = $A8 ; string to float number exponent count
expcnt = $A9 ; string to float exponent count
numbit = numexp ; bit count for array element calculations
numdpf = $AA ; string to float decimal point flag
expneg = $AB ; string to float eval exponent -ve flag
Astrtl = numdpf ; array start pointer low byte
Astrth = expneg ; array start pointer high byte
Histrl = numdpf ; highest string low byte
Histrh = expneg ; highest string high byte
Baslnl = numdpf ; BASIC search line pointer low byte
Baslnh = expneg ; BASIC search line pointer high byte
Fvar_l = numdpf ; find/found variable pointer low byte
Fvar_h = expneg ; find/found variable pointer high byte
Ostrtl = numdpf ; old block start pointer low byte
Ostrth = expneg ; old block start pointer high byte
Vrschl = numdpf ; variable search pointer low byte
Vrschh = expneg ; variable search pointer high byte
FAC1_e = $AC ; FAC1 exponent
FAC1_1 = FAC1_e+1 ; FAC1 mantissa1
FAC1_2 = FAC1_e+2 ; FAC1 mantissa2
FAC1_3 = FAC1_e+3 ; FAC1 mantissa3
FAC1_s = FAC1_e+4 ; FAC1 sign (b7)
str_ln = FAC1_e ; string length
str_pl = FAC1_1 ; string pointer low byte
str_ph = FAC1_2 ; string pointer high byte
des_pl = FAC1_2 ; string descriptor pointer low byte
des_ph = FAC1_3 ; string descriptor pointer high byte
mids_l = FAC1_3 ; MID$ string temp length byte
negnum = $B1 ; string to float eval -ve flag
numcon = $B1 ; series evaluation constant count
FAC1_o = $B2 ; FAC1 overflow byte
FAC2_e = $B3 ; FAC2 exponent
FAC2_1 = FAC2_e+1 ; FAC2 mantissa1
FAC2_2 = FAC2_e+2 ; FAC2 mantissa2
FAC2_3 = FAC2_e+3 ; FAC2 mantissa3
FAC2_s = FAC2_e+4 ; FAC2 sign (b7)
FAC_sc = $B8 ; FAC sign comparison, Acc#1 vs #2
FAC1_r = $B9 ; FAC1 rounding byte
ssptr_l = FAC_sc ; string start pointer low byte
ssptr_h = FAC1_r ; string start pointer high byte
sdescr = FAC_sc ; string descriptor pointer
csidx = $BA ; line crunch save index
Asptl = csidx ; array size/pointer low byte
Aspth = $BB ; array size/pointer high byte
Btmpl = Asptl ; BASIC pointer temp low byte
Btmph = Aspth ; BASIC pointer temp low byte
Cptrl = Asptl ; BASIC pointer temp low byte
Cptrh = Aspth ; BASIC pointer temp low byte
Sendl = Asptl ; BASIC pointer temp low byte
Sendh = Aspth ; BASIC pointer temp low byte
LAB_IGBY = $BC ; get next BASIC byte subroutine
LAB_GBYT = $C2 ; get current BASIC byte subroutine
Bpntrl = $C3 ; BASIC execute (get byte) pointer low byte
Bpntrh = Bpntrl+1 ; BASIC execute (get byte) pointer high byte
; = $D7 ; end of get BASIC char subroutine
Rbyte4 = $D8 ; extra PRNG byte
Rbyte1 = Rbyte4+1 ; most significant PRNG byte
Rbyte2 = Rbyte4+2 ; middle PRNG byte
Rbyte3 = Rbyte4+3 ; least significant PRNG byte
NmiBase = $DC ; NMI handler enabled/setup/triggered flags
; bit function
; === ========
; 7 interrupt enabled
; 6 interrupt setup
; 5 interrupt happened
; = $DD ; NMI handler addr low byte
; = $DE ; NMI handler addr high byte
IrqBase = $DF ; IRQ handler enabled/setup/triggered flags
; = $E0 ; IRQ handler addr low byte
; = $E1 ; IRQ handler addr high byte
; = $DE ; unused
; = $DF ; unused
; = $E0 ; unused
; = $E1 ; unused
; = $E2 ; unused
; = $E3 ; unused
; = $E4 ; unused
; = $E5 ; unused
; = $E6 ; unused
; = $E7 ; unused
; = $E8 ; unused
; = $E9 ; unused
; = $EA ; unused
; = $EB ; unused
; = $EC ; unused
; = $ED ; unused
; = $EE ; unused
Decss = $EF ; number to decimal string start
Decssp1 = Decss+1 ; number to decimal string start
; = $FF ; decimal string end
; token values needed for BASIC
; primary command tokens (can start a statement)
TK_END = $80 ; END token
TK_FOR = TK_END+1 ; FOR token
TK_NEXT = TK_FOR+1 ; NEXT token
TK_DATA = TK_NEXT+1 ; DATA token
TK_INPUT = TK_DATA+1 ; INPUT token
TK_DIM = TK_INPUT+1 ; DIM token
TK_READ = TK_DIM+1 ; READ token
TK_LET = TK_READ+1 ; LET token
TK_DEC = TK_LET+1 ; DEC token
TK_GOTO = TK_DEC+1 ; GOTO token
TK_RUN = TK_GOTO+1 ; RUN token
TK_IF = TK_RUN+1 ; IF token
TK_RESTORE = TK_IF+1 ; RESTORE token
TK_GOSUB = TK_RESTORE+1 ; GOSUB token
TK_RETIRQ = TK_GOSUB+1 ; RETIRQ token
TK_RETNMI = TK_RETIRQ+1 ; RETNMI token
TK_RETURN = TK_RETNMI+1 ; RETURN token
TK_REM = TK_RETURN+1 ; REM token
TK_STOP = TK_REM+1 ; STOP token
TK_ON = TK_STOP+1 ; ON token
TK_NULL = TK_ON+1 ; NULL token
TK_INC = TK_NULL+1 ; INC token
TK_WAIT = TK_INC+1 ; WAIT token
TK_LOAD = TK_WAIT+1 ; LOAD token
TK_SAVE = TK_LOAD+1 ; SAVE token
TK_DEF = TK_SAVE+1 ; DEF token
TK_POKE = TK_DEF+1 ; POKE token
TK_DOKE = TK_POKE+1 ; DOKE token
TK_CALL = TK_DOKE+1 ; CALL token
TK_DO = TK_CALL+1 ; DO token
TK_LOOP = TK_DO+1 ; LOOP token
TK_PRINT = TK_LOOP+1 ; PRINT token
TK_CONT = TK_PRINT+1 ; CONT token
TK_LIST = TK_CONT+1 ; LIST token
TK_CLEAR = TK_LIST+1 ; CLEAR token
TK_NEW = TK_CLEAR+1 ; NEW token
TK_WIDTH = TK_NEW+1 ; WIDTH token
TK_GET = TK_WIDTH+1 ; GET token
TK_SWAP = TK_GET+1 ; SWAP token
TK_BITSET = TK_SWAP+1 ; BITSET token
TK_BITCLR = TK_BITSET+1 ; BITCLR token
TK_IRQ = TK_BITCLR+1 ; IRQ token
TK_NMI = TK_IRQ+1 ; NMI token
; secondary command tokens, can't start a statement
TK_TAB = TK_NMI+1 ; TAB token
TK_ELSE = TK_TAB+1 ; ELSE token
TK_TO = TK_ELSE+1 ; TO token
TK_FN = TK_TO+1 ; FN token
TK_SPC = TK_FN+1 ; SPC token
TK_THEN = TK_SPC+1 ; THEN token
TK_NOT = TK_THEN+1 ; NOT token
TK_STEP = TK_NOT+1 ; STEP token
TK_UNTIL = TK_STEP+1 ; UNTIL token
TK_WHILE = TK_UNTIL+1 ; WHILE token
TK_OFF = TK_WHILE+1 ; OFF token
; opperator tokens
TK_PLUS = TK_OFF+1 ; + token
TK_MINUS = TK_PLUS+1 ; - token
TK_MUL = TK_MINUS+1 ; * token
TK_DIV = TK_MUL+1 ; / token
TK_POWER = TK_DIV+1 ; ^ token
TK_AND = TK_POWER+1 ; AND token
TK_EOR = TK_AND+1 ; EOR token
TK_OR = TK_EOR+1 ; OR token
TK_RSHIFT = TK_OR+1 ; RSHIFT token
TK_LSHIFT = TK_RSHIFT+1 ; LSHIFT token
TK_GT = TK_LSHIFT+1 ; > token
TK_EQUAL = TK_GT+1 ; = token
TK_LT = TK_EQUAL+1 ; < token
; functions tokens
TK_SGN = TK_LT+1 ; SGN token
TK_INT = TK_SGN+1 ; INT token
TK_ABS = TK_INT+1 ; ABS token
TK_USR = TK_ABS+1 ; USR token
TK_FRE = TK_USR+1 ; FRE token
TK_POS = TK_FRE+1 ; POS token
TK_SQR = TK_POS+1 ; SQR token
TK_RND = TK_SQR+1 ; RND token
TK_LOG = TK_RND+1 ; LOG token
TK_EXP = TK_LOG+1 ; EXP token
TK_COS = TK_EXP+1 ; COS token
TK_SIN = TK_COS+1 ; SIN token
TK_TAN = TK_SIN+1 ; TAN token
TK_ATN = TK_TAN+1 ; ATN token
TK_PEEK = TK_ATN+1 ; PEEK token
TK_DEEK = TK_PEEK+1 ; DEEK token
TK_SADD = TK_DEEK+1 ; SADD token
TK_LEN = TK_SADD+1 ; LEN token
TK_STRS = TK_LEN+1 ; STR$ token
TK_VAL = TK_STRS+1 ; VAL token
TK_ASC = TK_VAL+1 ; ASC token
TK_UCASES = TK_ASC+1 ; UCASE$ token
TK_LCASES = TK_UCASES+1 ; LCASE$ token
TK_CHRS = TK_LCASES+1 ; CHR$ token
TK_HEXS = TK_CHRS+1 ; HEX$ token
TK_BINS = TK_HEXS+1 ; BIN$ token
TK_BITTST = TK_BINS+1 ; BITTST token
TK_MAX = TK_BITTST+1 ; MAX token
TK_MIN = TK_MAX+1 ; MIN token
TK_PI = TK_MIN+1 ; PI token
TK_TWOPI = TK_PI+1 ; TWOPI token
TK_VPTR = TK_TWOPI+1 ; VARPTR token
TK_LEFTS = TK_VPTR+1 ; LEFT$ token
TK_RIGHTS = TK_LEFTS+1 ; RIGHT$ token
TK_MIDS = TK_RIGHTS+1 ; MID$ token
; offsets from a base of X or Y
PLUS_0 = $00 ; X or Y plus 0
PLUS_1 = $01 ; X or Y plus 1
PLUS_2 = $02 ; X or Y plus 2
PLUS_3 = $03 ; X or Y plus 3
LAB_STAK = $0100 ; stack bottom, no offset
LAB_SKFE = LAB_STAK+$FE
; flushed stack address
LAB_SKFF = LAB_STAK+$FF
; flushed stack address
ccflag = $0200 ; BASIC CTRL-C flag, 00 = enabled, 01 = dis
ccbyte = ccflag+1 ; BASIC CTRL-C byte
ccnull = ccbyte+1 ; BASIC CTRL-C byte timeout
VEC_CC = ccnull+1 ; ctrl c check vector
VEC_IN = VEC_CC+2 ; input vector
VEC_OUT = VEC_IN+2 ; output vector
VEC_LD = VEC_OUT+2 ; load vector
VEC_SV = VEC_LD+2 ; save vector
; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80
Ibuffs = IRQ_vec+$14
; start of input buffer after IRQ/NMI code
Ibuffe = Ibuffs+$47; end of input buffer
Ram_base = $0300 ; start of user RAM (set as needed, should be page aligned)
Ram_top = $C000 ; end of user RAM+1 (set as needed, should be page aligned)
; This start can be changed to suit your system
*= $C000
; BASIC cold start entry point
; new page 2 initialisation, copy block to ccflag on
LAB_COLD
LDY #PG2_TABE-PG2_TABS-1
; byte count-1
LAB_2D13
LDA PG2_TABS,Y ; get byte
STA ccflag,Y ; store in page 2
DEY ; decrement count
BPL LAB_2D13 ; loop if not done
LDX #$FF ; set byte
STX Clineh ; set current line high byte (set immediate mode)
TXS ; reset stack pointer
LDA #$4C ; code for JMP
STA Fnxjmp ; save for jump vector for functions
; copy block from LAB_2CEE to $00BC - $00D3
LDX #StrTab-LAB_2CEE ; set byte count
LAB_2D4E
LDA LAB_2CEE-1,X ; get byte from table
STA LAB_IGBY-1,X ; save byte in page zero
DEX ; decrement count
BNE LAB_2D4E ; loop if not all done
; copy block from StrTab to $0000 - $0012
LAB_GMEM
LDX #EndTab-StrTab-1 ; set byte count-1
TabLoop
LDA StrTab,X ; get byte from table
STA PLUS_0,X ; save byte in page zero
DEX ; decrement count
BPL TabLoop ; loop if not all done
; set-up start values
LDA #$00 ; clear A
STA NmiBase ; clear NMI handler enabled flag
STA IrqBase ; clear IRQ handler enabled flag
STA FAC1_o ; clear FAC1 overflow byte
STA last_sh ; clear descriptor stack top item pointer high byte
LDA #$0E ; set default tab size
STA TabSiz ; save it
LDA #$03 ; set garbage collect step size for descriptor stack
STA g_step ; save it
LDX #des_sk ; descriptor stack start
STX next_s ; set descriptor stack pointer
JSR LAB_CRLF ; print CR/LF
LDA #<LAB_MSZM ; point to memory size message (low addr)
LDY #>LAB_MSZM ; point to memory size message (high addr)
JSR LAB_18C3 ; print null terminated string from memory
JSR LAB_INLN ; print "? " and get BASIC input
STX Bpntrl ; set BASIC execute pointer low byte
STY Bpntrh ; set BASIC execute pointer high byte
JSR LAB_GBYT ; get last byte back
BNE LAB_2DAA ; branch if not null (user typed something)
LDY #$00 ; else clear Y
; character was null so get memory size the hard way
; we get here with Y=0 and Itempl/h = Ram_base
LAB_2D93
INC Itempl ; increment temporary integer low byte
BNE LAB_2D99 ; branch if no overflow
INC Itemph ; increment temporary integer high byte
LDA Itemph ; get high byte
CMP #>Ram_top ; compare with top of RAM+1
BEQ LAB_2DB6 ; branch if match (end of user RAM)
LAB_2D99
LDA #$55 ; set test byte
STA (Itempl),Y ; save via temporary integer
CMP (Itempl),Y ; compare via temporary integer
BNE LAB_2DB6 ; branch if fail
ASL ; shift test byte left (now $AA)
STA (Itempl),Y ; save via temporary integer
CMP (Itempl),Y ; compare via temporary integer
BEQ LAB_2D93 ; if ok go do next byte
BNE LAB_2DB6 ; branch if fail
LAB_2DAA
JSR LAB_2887 ; get FAC1 from string
LDA FAC1_e ; get FAC1 exponent
CMP #$98 ; compare with exponent = 2^24
BCS LAB_GMEM ; if too large go try again
JSR LAB_F2FU ; save integer part of FAC1 in temporary integer
; (no range check)
LAB_2DB6
LDA Itempl ; get temporary integer low byte
LDY Itemph ; get temporary integer high byte
CPY #<Ram_base+1 ; compare with start of RAM+$100 high byte
BCC LAB_GMEM ; if too small go try again
; uncomment these lines if you want to check on the high limit of memory. Note if
; Ram_top is set too low then this will fail. default is ignore it and assume the
; users know what they're doing!
; CPY #>Ram_top ; compare with top of RAM high byte
; BCC MEM_OK ; branch if < RAM top
; BNE LAB_GMEM ; if too large go try again
; else was = so compare low bytes
; CMP #<Ram_top ; compare with top of RAM low byte
; BEQ MEM_OK ; branch if = RAM top
; BCS LAB_GMEM ; if too large go try again
;MEM_OK
STA Ememl ; set end of mem low byte
STY Ememh ; set end of mem high byte
STA Sstorl ; set bottom of string space low byte
STY Sstorh ; set bottom of string space high byte
LDY #<Ram_base ; set start addr low byte
LDX #>Ram_base ; set start addr high byte
STY Smeml ; save start of mem low byte
STX Smemh ; save start of mem high byte
; this line is only needed if Ram_base is not $xx00
; LDY #$00 ; clear Y
TYA ; clear A
STA (Smeml),Y ; clear first byte
INC Smeml ; increment start of mem low byte
; these two lines are only needed if Ram_base is $xxFF
; BNE LAB_2E05 ; branch if no rollover
; INC Smemh ; increment start of mem high byte
LAB_2E05
JSR LAB_CRLF ; print CR/LF
JSR LAB_1463 ; do "NEW" and "CLEAR"
LDA Ememl ; get end of mem low byte
SEC ; set carry for subtract
SBC Smeml ; subtract start of mem low byte
TAX ; copy to X
LDA Ememh ; get end of mem high byte
SBC Smemh ; subtract start of mem high byte
JSR LAB_295E ; print XA as unsigned integer (bytes free)
LDA #<LAB_SMSG ; point to sign-on message (low addr)
LDY #>LAB_SMSG ; point to sign-on message (high addr)
JSR LAB_18C3 ; print null terminated string from memory
LDA #<LAB_1274 ; warm start vector low byte
LDY #>LAB_1274 ; warm start vector high byte
STA Wrmjpl ; save warm start vector low byte
STY Wrmjph ; save warm start vector high byte
JMP (Wrmjpl) ; go do warm start
; open up space in memory
; move (Ostrtl)-(Obendl) to new block ending at (Nbendl)
; Nbendl,Nbendh - new block end address (A/Y)
; Obendl,Obendh - old block end address
; Ostrtl,Ostrth - old block start address
; returns with ..
; Nbendl,Nbendh - new block start address (high byte - $100)
; Obendl,Obendh - old block start address (high byte - $100)
; Ostrtl,Ostrth - old block start address (unchanged)
LAB_11CF
JSR LAB_121F ; check available memory, "Out of memory" error if no room
; addr to check is in AY (low/high)
STA Earryl ; save new array mem end low byte
STY Earryh ; save new array mem end high byte
; open up space in memory
; move (Ostrtl)-(Obendl) to new block ending at (Nbendl)
; don't set array end
LAB_11D6
SEC ; set carry for subtract
LDA Obendl ; get block end low byte
SBC Ostrtl ; subtract block start low byte
TAY ; copy MOD(block length/$100) byte to Y
LDA Obendh ; get block end high byte
SBC Ostrth ; subtract block start high byte
TAX ; copy block length high byte to X
INX ; +1 to allow for count=0 exit
TYA ; copy block length low byte to A
BEQ LAB_120A ; branch if length low byte=0
; block is (X-1)*256+Y bytes, do the Y bytes first
SEC ; set carry for add + 1, two's complement
EOR #$FF ; invert low byte for subtract
ADC Obendl ; add block end low byte
STA Obendl ; save corrected old block end low byte
BCS LAB_11F3 ; branch if no underflow
DEC Obendh ; else decrement block end high byte
SEC ; set carry for add + 1, two's complement
LAB_11F3
TYA ; get MOD(block length/$100) byte
EOR #$FF ; invert low byte for subtract
ADC Nbendl ; add destination end low byte
STA Nbendl ; save modified new block end low byte
BCS LAB_1203 ; branch if no underflow
DEC Nbendh ; else decrement block end high byte
BCC LAB_1203 ; branch always
LAB_11FF
LDA (Obendl),Y ; get byte from source
STA (Nbendl),Y ; copy byte to destination
LAB_1203
DEY ; decrement index
BNE LAB_11FF ; loop until Y=0
; now do Y=0 indexed byte
LDA (Obendl),Y ; get byte from source
STA (Nbendl),Y ; save byte to destination
LAB_120A
DEC Obendh ; decrement source pointer high byte
DEC Nbendh ; decrement destination pointer high byte
DEX ; decrement block count
BNE LAB_1203 ; loop until count = $0
RTS
; check room on stack for A bytes
; stack too deep? do OM error
LAB_1212
STA TempB ; save result in temp byte
TSX ; copy stack
CPX TempB ; compare new "limit" with stack
BCC LAB_OMER ; if stack < limit do "Out of memory" error then warm start
RTS
; check available memory, "Out of memory" error if no room
; addr to check is in AY (low/high)
LAB_121F
CPY Sstorh ; compare bottom of string mem high byte
BCC LAB_124B ; if less then exit (is ok)
BNE LAB_1229 ; skip next test if greater (tested <)
; high byte was =, now do low byte
CMP Sstorl ; compare with bottom of string mem low byte
BCC LAB_124B ; if less then exit (is ok)
; addr is > string storage ptr (oops!)
LAB_1229
PHA ; push addr low byte
LDX #$08 ; set index to save Adatal to expneg inclusive
TYA ; copy addr high byte (to push on stack)
; save misc numeric work area
LAB_122D
PHA ; push byte
LDA Adatal-1,X ; get byte from Adatal to expneg ( ,$00 not pushed)
DEX ; decrement index
BPL LAB_122D ; loop until all done
JSR LAB_GARB ; garbage collection routine
; restore misc numeric work area
LDX #$00 ; clear the index to restore bytes
LAB_1238
PLA ; pop byte
STA Adatal,X ; save byte to Adatal to expneg
INX ; increment index
CPX #$08 ; compare with end + 1
BMI LAB_1238 ; loop if more to do
PLA ; pop addr high byte
TAY ; copy back to Y
PLA ; pop addr low byte
CPY Sstorh ; compare bottom of string mem high byte
BCC LAB_124B ; if less then exit (is ok)
BNE LAB_OMER ; if greater do "Out of memory" error then warm start
; high byte was =, now do low byte
CMP Sstorl ; compare with bottom of string mem low byte
BCS LAB_OMER ; if >= do "Out of memory" error then warm start
; ok exit, carry clear
LAB_124B
RTS
; do "Out of memory" error then warm start
LAB_OMER
LDX #$0C ; error code $0C ("Out of memory" error)
; do error #X, then warm start
LAB_XERR
JSR LAB_CRLF ; print CR/LF
LDA LAB_BAER,X ; get error message pointer low byte
LDY LAB_BAER+1,X ; get error message pointer high byte
JSR LAB_18C3 ; print null terminated string from memory
JSR LAB_1491 ; flush stack and clear continue flag
LDA #<LAB_EMSG ; point to " Error" low addr
LDY #>LAB_EMSG ; point to " Error" high addr
LAB_1269
JSR LAB_18C3 ; print null terminated string from memory
LDY Clineh ; get current line high byte
INY ; increment it
BEQ LAB_1274 ; go do warm start (was immediate mode)
; else print line number
JSR LAB_2953 ; print " in line [LINE #]"
; BASIC warm start entry point
; wait for Basic command
LAB_1274
; clear ON IRQ/NMI bytes
LDA #$00 ; clear A
STA IrqBase ; clear enabled byte
STA NmiBase ; clear enabled byte
LDA #<LAB_RMSG ; point to "Ready" message low byte
LDY #>LAB_RMSG ; point to "Ready" message high byte
JSR LAB_18C3 ; go do print string
; wait for Basic command (no "Ready")
LAB_127D
JSR LAB_1357 ; call for BASIC input
LAB_1280
STX Bpntrl ; set BASIC execute pointer low byte
STY Bpntrh ; set BASIC execute pointer high byte
JSR LAB_GBYT ; scan memory
BEQ LAB_127D ; loop while null
; got to interpret input line now ..
LDX #$FF ; current line to null value
STX Clineh ; set current line high byte
BCC LAB_1295 ; branch if numeric character (handle new BASIC line)
; no line number .. immediate mode
JSR LAB_13A6 ; crunch keywords into Basic tokens
JMP LAB_15F6 ; go scan and interpret code
; handle new BASIC line
LAB_1295
JSR LAB_GFPN ; get fixed-point number into temp integer
JSR LAB_13A6 ; crunch keywords into Basic tokens
STY Ibptr ; save index pointer to end of crunched line
JSR LAB_SSLN ; search BASIC for temp integer line number
BCC LAB_12E6 ; branch if not found
; aroooogah! line # already exists! delete it
LDY #$01 ; set index to next line pointer high byte
LDA (Baslnl),Y ; get next line pointer high byte
STA ut1_ph ; save it
LDA Svarl ; get start of vars low byte
STA ut1_pl ; save it
LDA Baslnh ; get found line pointer high byte
STA ut2_ph ; save it
LDA Baslnl ; get found line pointer low byte
DEY ; decrement index
SBC (Baslnl),Y ; subtract next line pointer low byte
CLC ; clear carry for add
ADC Svarl ; add start of vars low byte
STA Svarl ; save new start of vars low byte
STA ut2_pl ; save destination pointer low byte
LDA Svarh ; get start of vars high byte
ADC #$FF ; -1 + carry
STA Svarh ; save start of vars high byte
SBC Baslnh ; subtract found line pointer high byte
TAX ; copy to block count
SEC ; set carry for subtract
LDA Baslnl ; get found line pointer low byte
SBC Svarl ; subtract start of vars low byte
TAY ; copy to bytes in first block count
BCS LAB_12D0 ; branch if overflow
INX ; increment block count (correct for =0 loop exit)
DEC ut2_ph ; decrement destination high byte
LAB_12D0
CLC ; clear carry for add
ADC ut1_pl ; add source pointer low byte
BCC LAB_12D8 ; branch if no overflow
DEC ut1_ph ; else decrement source pointer high byte
CLC ; clear carry
; close up memory to delete old line
LAB_12D8
LDA (ut1_pl),Y ; get byte from source
STA (ut2_pl),Y ; copy to destination
INY ; increment index
BNE LAB_12D8 ; while <> 0 do this block
INC ut1_ph ; increment source pointer high byte
INC ut2_ph ; increment destination pointer high byte
DEX ; decrement block count
BNE LAB_12D8 ; loop until all done
; got new line in buffer and no existing same #
LAB_12E6
LDA Ibuffs ; get byte from start of input buffer
BEQ LAB_1319 ; if null line just go flush stack/vars and exit
; got new line and it isn't empty line
LDA Ememl ; get end of mem low byte
LDY Ememh ; get end of mem high byte
STA Sstorl ; set bottom of string space low byte
STY Sstorh ; set bottom of string space high byte
LDA Svarl ; get start of vars low byte (end of BASIC)
STA Obendl ; save old block end low byte
LDY Svarh ; get start of vars high byte (end of BASIC)
STY Obendh ; save old block end high byte
ADC Ibptr ; add input buffer pointer (also buffer length)
BCC LAB_1301 ; branch if no overflow from add
INY ; else increment high byte
LAB_1301
STA Nbendl ; save new block end low byte (move to, low byte)
STY Nbendh ; save new block end high byte
JSR LAB_11CF ; open up space in memory
; old start pointer Ostrtl,Ostrth set by the find line call
LDA Earryl ; get array mem end low byte
LDY Earryh ; get array mem end high byte
STA Svarl ; save start of vars low byte
STY Svarh ; save start of vars high byte
LDY Ibptr ; get input buffer pointer (also buffer length)
DEY ; adjust for loop type
LAB_1311
LDA Ibuffs-4,Y ; get byte from crunched line
STA (Baslnl),Y ; save it to program memory
DEY ; decrement count
CPY #$03 ; compare with first byte-1
BNE LAB_1311 ; continue while count <> 3
LDA Itemph ; get line # high byte
STA (Baslnl),Y ; save it to program memory
DEY ; decrement count
LDA Itempl ; get line # low byte
STA (Baslnl),Y ; save it to program memory
DEY ; decrement count
LDA #$FF ; set byte to allow chain rebuild. if you didn't set this
; byte then a zero already here would stop the chain rebuild
; as it would think it was the [EOT] marker.
STA (Baslnl),Y ; save it to program memory
LAB_1319
JSR LAB_1477 ; reset execution to start, clear vars and flush stack
LDX Smeml ; get start of mem low byte
LDA Smemh ; get start of mem high byte
LDY #$01 ; index to high byte of next line pointer
LAB_1325
STX ut1_pl ; set line start pointer low byte
STA ut1_ph ; set line start pointer high byte
LDA (ut1_pl),Y ; get it
BEQ LAB_133E ; exit if end of program
; rebuild chaining of Basic lines
LDY #$04 ; point to first code byte of line
; there is always 1 byte + [EOL] as null entries are deleted
LAB_1330
INY ; next code byte
LDA (ut1_pl),Y ; get byte
BNE LAB_1330 ; loop if not [EOL]
SEC ; set carry for add + 1
TYA ; copy end index
ADC ut1_pl ; add to line start pointer low byte
TAX ; copy to X
LDY #$00 ; clear index, point to this line's next line pointer
STA (ut1_pl),Y ; set next line pointer low byte
TYA ; clear A
ADC ut1_ph ; add line start pointer high byte + carry
INY ; increment index to high byte
STA (ut1_pl),Y ; save next line pointer low byte
BCC LAB_1325 ; go do next line, branch always, carry clear
LAB_133E
JMP LAB_127D ; else we just wait for Basic command, no "Ready"
; print "? " and get BASIC input
LAB_INLN
JSR LAB_18E3 ; print "?" character
JSR LAB_18E0 ; print " "
BNE LAB_1357 ; call for BASIC input and return
; receive line from keyboard
; $08 as delete key (BACKSPACE on standard keyboard)
LAB_134B
JSR LAB_PRNA ; go print the character
DEX ; decrement the buffer counter (delete)
.byte $2C ; make LDX into BIT abs
; call for BASIC input (main entry point)
LAB_1357
LDX #$00 ; clear BASIC line buffer pointer
LAB_1359
JSR V_INPT ; call scan input device
BCC LAB_1359 ; loop if no byte
BEQ LAB_1359 ; loop until valid input (ignore NULLs)
CMP #$07 ; compare with [BELL]
BEQ LAB_1378 ; branch if [BELL]
CMP #$0D ; compare with [CR]
BEQ LAB_1384 ; do CR/LF exit if [CR]
CPX #$00 ; compare pointer with $00
BNE LAB_1374 ; branch if not empty
; next two lines ignore any non print character and [SPACE] if input buffer empty
CMP #$21 ; compare with [SP]+1
BCC LAB_1359 ; if < ignore character
LAB_1374
CMP #$08 ; compare with [BACKSPACE] (delete last character)
BEQ LAB_134B ; go delete last character
LAB_1378
CPX #Ibuffe-Ibuffs ; compare character count with max
BCS LAB_138E ; skip store and do [BELL] if buffer full
STA Ibuffs,X ; else store in buffer
INX ; increment pointer
LAB_137F
JSR LAB_PRNA ; go print the character
BNE LAB_1359 ; always loop for next character
LAB_1384
JMP LAB_1866 ; do CR/LF exit to BASIC
; announce buffer full
LAB_138E
LDA #$07 ; [BELL] character into A
BNE LAB_137F ; go print the [BELL] but ignore input character
; branch always
; crunch keywords into Basic tokens
; position independent buffer version ..
; faster, dictionary search version ....
LAB_13A6
LDY #$FF ; set save index (makes for easy math later)
SEC ; set carry for subtract
LDA Bpntrl ; get basic execute pointer low byte
SBC #<Ibuffs ; subtract input buffer start pointer
TAX ; copy result to X (index past line # if any)
STX Oquote ; clear open quote/DATA flag
LAB_13AC
LDA Ibuffs,X ; get byte from input buffer
BEQ LAB_13EC ; if null save byte then exit
CMP #'_' ; compare with "_"
BCS LAB_13EC ; if >= go save byte then continue crunching
CMP #'<' ; compare with "<"
BCS LAB_13CC ; if >= go crunch now
CMP #'0' ; compare with "0"
BCS LAB_13EC ; if >= go save byte then continue crunching
STA Scnquo ; save buffer byte as search character
CMP #$22 ; is it quote character?
BEQ LAB_1410 ; branch if so (copy quoted string)
CMP #'*' ; compare with "*"
BCC LAB_13EC ; if < go save byte then continue crunching
; else crunch now
LAB_13CC
BIT Oquote ; get open quote/DATA token flag
BVS LAB_13EC ; branch if b6 of Oquote set (was DATA)
; go save byte then continue crunching
STX TempB ; save buffer read index
STY csidx ; copy buffer save index
LDY #<TAB_1STC ; get keyword first character table low address
STY ut2_pl ; save pointer low byte
LDY #>TAB_1STC ; get keyword first character table high address
STY ut2_ph ; save pointer high byte
LDY #$00 ; clear table pointer
LAB_13D0
CMP (ut2_pl),Y ; compare with keyword first character table byte
BEQ LAB_13D1 ; go do word_table_chr if match
BCC LAB_13EA ; if < keyword first character table byte go restore
; Y and save to crunched
INY ; else increment pointer
BNE LAB_13D0 ; and loop (branch always)
; have matched first character of some keyword
LAB_13D1
TYA ; copy matching index
ASL ; *2 (bytes per pointer)
TAX ; copy to new index
LDA TAB_CHRT,X ; get keyword table pointer low byte
STA ut2_pl ; save pointer low byte
LDA TAB_CHRT+1,X ; get keyword table pointer high byte
STA ut2_ph ; save pointer high byte
LDY #$FF ; clear table pointer (make -1 for start)
LDX TempB ; restore buffer read index
LAB_13D6
INY ; next table byte
LDA (ut2_pl),Y ; get byte from table
LAB_13D8
BMI LAB_13EA ; all bytes matched so go save token
INX ; next buffer byte
CMP Ibuffs,X ; compare with byte from input buffer
BEQ LAB_13D6 ; go compare next if match
BNE LAB_1417 ; branch if >< (not found keyword)
LAB_13EA
LDY csidx ; restore save index
; save crunched to output
LAB_13EC
INX ; increment buffer index (to next input byte)
INY ; increment save index (to next output byte)
STA Ibuffs,Y ; save byte to output
CMP #$00 ; set the flags, set carry
BEQ LAB_142A ; do exit if was null [EOL]
; A holds token or byte here
SBC #':' ; subtract ":" (carry set by CMP #00)
BEQ LAB_13FF ; branch if it was ":" (is now $00)
; A now holds token-$3A
CMP #TK_DATA-$3A ; compare with DATA token - $3A
BNE LAB_1401 ; branch if not DATA
; token was : or DATA
LAB_13FF
STA Oquote ; save token-$3A (clear for ":", TK_DATA-$3A for DATA)
LAB_1401
EOR #TK_REM-$3A ; effectively subtract REM token offset
BNE LAB_13AC ; If wasn't REM then go crunch rest of line
STA Asrch ; else was REM so set search for [EOL]
; loop for REM, "..." etc.
LAB_1408
LDA Ibuffs,X ; get byte from input buffer
BEQ LAB_13EC ; branch if null [EOL]
CMP Asrch ; compare with stored character
BEQ LAB_13EC ; branch if match (end quote)
; entry for copy string in quotes, don't crunch
LAB_1410
INY ; increment buffer save index
STA Ibuffs,Y ; save byte to output
INX ; increment buffer read index
BNE LAB_1408 ; loop while <> 0 (should never be 0!)
; not found keyword this go
LAB_1417
LDX TempB ; compare has failed, restore buffer index (start byte!)
; now find the end of this word in the table
LAB_141B
LDA (ut2_pl),Y ; get table byte
PHP ; save status
INY ; increment table index
PLP ; restore byte status
BPL LAB_141B ; if not end of keyword go do next
LDA (ut2_pl),Y ; get byte from keyword table
BNE LAB_13D8 ; go test next word if not zero byte (end of table)
; reached end of table with no match
LDA Ibuffs,X ; restore byte from input buffer
BPL LAB_13EA ; branch always (all bytes in buffer are $00-$7F)
; go save byte in output and continue crunching
; reached [EOL]
LAB_142A
INY ; increment pointer
INY ; increment pointer (makes it next line pointer high byte)
STA Ibuffs,Y ; save [EOL] (marks [EOT] in immediate mode)
INY ; adjust for line copy
INY ; adjust for line copy
INY ; adjust for line copy
DEC Bpntrl ; allow for increment (change if buffer starts at $xxFF)
RTS
; search Basic for temp integer line number from start of mem
LAB_SSLN
LDA Smeml ; get start of mem low byte
LDX Smemh ; get start of mem high byte
; search Basic for temp integer line number from AX
; returns carry set if found
; returns Baslnl/Baslnh pointer to found or next higher (not found) line
; old 541 new 507
LAB_SHLN
LDY #$01 ; set index
STA Baslnl ; save low byte as current
STX Baslnh ; save high byte as current
LDA (Baslnl),Y ; get pointer high byte from addr
BEQ LAB_145F ; pointer was zero so we're done, do 'not found' exit
LDY #$03 ; set index to line # high byte
LDA (Baslnl),Y ; get line # high byte
DEY ; decrement index (point to low byte)
CMP Itemph ; compare with temporary integer high byte
BNE LAB_1455 ; if <> skip low byte check
LDA (Baslnl),Y ; get line # low byte
CMP Itempl ; compare with temporary integer low byte
LAB_1455
BCS LAB_145E ; else if temp < this line, exit (passed line#)
LAB_1456
DEY ; decrement index to next line ptr high byte
LDA (Baslnl),Y ; get next line pointer high byte
TAX ; copy to X
DEY ; decrement index to next line ptr low byte
LDA (Baslnl),Y ; get next line pointer low byte
BCC LAB_SHLN ; go search for line # in temp (Itempl/Itemph) from AX
; (carry always clear)
LAB_145E
BEQ LAB_1460 ; exit if temp = found line #, carry is set
LAB_145F
CLC ; clear found flag
LAB_1460
RTS
; perform NEW
LAB_NEW
BNE LAB_1460 ; exit if not end of statement (to do syntax error)
LAB_1463
LDA #$00 ; clear A
TAY ; clear Y
STA (Smeml),Y ; clear first line, next line pointer, low byte
INY ; increment index
STA (Smeml),Y ; clear first line, next line pointer, high byte
CLC ; clear carry
LDA Smeml ; get start of mem low byte
ADC #$02 ; calculate end of BASIC low byte
STA Svarl ; save start of vars low byte
LDA Smemh ; get start of mem high byte
ADC #$00 ; add any carry
STA Svarh ; save start of vars high byte
; reset execution to start, clear vars and flush stack
LAB_1477
CLC ; clear carry
LDA Smeml ; get start of mem low byte
ADC #$FF ; -1
STA Bpntrl ; save BASIC execute pointer low byte
LDA Smemh ; get start of mem high byte
ADC #$FF ; -1+carry
STA Bpntrh ; save BASIC execute pointer high byte
; "CLEAR" command gets here
LAB_147A
LDA Ememl ; get end of mem low byte
LDY Ememh ; get end of mem high byte
STA Sstorl ; set bottom of string space low byte
STY Sstorh ; set bottom of string space high byte
LDA Svarl ; get start of vars low byte
LDY Svarh ; get start of vars high byte
STA Sarryl ; save var mem end low byte
STY Sarryh ; save var mem end high byte
STA Earryl ; save array mem end low byte
STY Earryh ; save array mem end high byte
JSR LAB_161A ; perform RESTORE command
; flush stack and clear continue flag
LAB_1491
LDX #des_sk ; set descriptor stack pointer
STX next_s ; save descriptor stack pointer
PLA ; pull return address low byte
TAX ; copy return address low byte
PLA ; pull return address high byte
STX LAB_SKFE ; save to cleared stack
STA LAB_SKFF ; save to cleared stack
LDX #$FD ; new stack pointer
TXS ; reset stack
LDA #$00 ; clear byte
STA Cpntrh ; clear continue pointer high byte
STA Sufnxf ; clear subscript/FNX flag
LAB_14A6
RTS
; perform CLEAR
LAB_CLEAR
BEQ LAB_147A ; if no following token go do "CLEAR"
; else there was a following token (go do syntax error)
RTS
; perform LIST [n][-m]
; bigger, faster version (a _lot_ faster)
LAB_LIST
BCC LAB_14BD ; branch if next character numeric (LIST n..)
BEQ LAB_14BD ; branch if next character [NULL] (LIST)
CMP #TK_MINUS ; compare with token for -
BNE LAB_14A6 ; exit if not - (LIST -m)
; LIST [[n][-m]]
; this bit sets the n , if present, as the start and end
LAB_14BD
JSR LAB_GFPN ; get fixed-point number into temp integer
JSR LAB_SSLN ; search BASIC for temp integer line number
; (pointer in Baslnl/Baslnh)
JSR LAB_GBYT ; scan memory
BEQ LAB_14D4 ; branch if no more characters
; this bit checks the - is present
CMP #TK_MINUS ; compare with token for -
BNE LAB_1460 ; return if not "-" (will be Syntax error)
; LIST [n]-m
; the - was there so set m as the end value
JSR LAB_IGBY ; increment and scan memory
JSR LAB_GFPN ; get fixed-point number into temp integer
BNE LAB_1460 ; exit if not ok
LAB_14D4
LDA Itempl ; get temporary integer low byte
ORA Itemph ; OR temporary integer high byte
BNE LAB_14E2 ; branch if start set
LDA #$FF ; set for -1
STA Itempl ; set temporary integer low byte
STA Itemph ; set temporary integer high byte
LAB_14E2
LDY #$01 ; set index for line
STY Oquote ; clear open quote flag
JSR LAB_CRLF ; print CR/LF
LDA (Baslnl),Y ; get next line pointer high byte
; pointer initially set by search at LAB_14BD
BEQ LAB_152B ; if null all done so exit
JSR LAB_1629 ; do CRTL-C check vector
INY ; increment index for line
LDA (Baslnl),Y ; get line # low byte
TAX ; copy to X
INY ; increment index
LDA (Baslnl),Y ; get line # high byte
CMP Itemph ; compare with temporary integer high byte
BNE LAB_14FF ; branch if no high byte match
CPX Itempl ; compare with temporary integer low byte
BEQ LAB_1501 ; branch if = last line to do (< will pass next branch)
LAB_14FF ; else ..
BCS LAB_152B ; if greater all done so exit
LAB_1501
STY Tidx1 ; save index for line
JSR LAB_295E ; print XA as unsigned integer
LDA #$20 ; space is the next character
LAB_1508
LDY Tidx1 ; get index for line
AND #$7F ; mask top out bit of character
LAB_150C
JSR LAB_PRNA ; go print the character
CMP #$22 ; was it " character
BNE LAB_1519 ; branch if not
; we are either entering or leaving a pair of quotes
LDA Oquote ; get open quote flag
EOR #$FF ; toggle it
STA Oquote ; save it back
LAB_1519
INY ; increment index
LDA (Baslnl),Y ; get next byte
BNE LAB_152E ; branch if not [EOL] (go print character)
TAY ; else clear index
LDA (Baslnl),Y ; get next line pointer low byte
TAX ; copy to X
INY ; increment index
LDA (Baslnl),Y ; get next line pointer high byte
STX Baslnl ; set pointer to line low byte
STA Baslnh ; set pointer to line high byte
BNE LAB_14E2 ; go do next line if not [EOT]
; else ..
LAB_152B
RTS
LAB_152E
BPL LAB_150C ; just go print it if not token byte
; else was token byte so uncrunch it (maybe)
BIT Oquote ; test the open quote flag
BMI LAB_150C ; just go print character if open quote set
LDX #>LAB_KEYT ; get table address high byte
ASL ; *2
ASL ; *4
BCC LAB_152F ; branch if no carry
INX ; else increment high byte
CLC ; clear carry for add
LAB_152F
ADC #<LAB_KEYT ; add low byte
BCC LAB_1530 ; branch if no carry
INX ; else increment high byte
LAB_1530
STA ut2_pl ; save table pointer low byte
STX ut2_ph ; save table pointer high byte
STY Tidx1 ; save index for line
LDY #$00 ; clear index
LDA (ut2_pl),Y ; get length
TAX ; copy length
INY ; increment index
LDA (ut2_pl),Y ; get 1st character
DEX ; decrement length
BEQ LAB_1508 ; if no more characters exit and print
JSR LAB_PRNA ; go print the character
INY ; increment index
LDA (ut2_pl),Y ; get keyword address low byte
PHA ; save it for now
INY ; increment index
LDA (ut2_pl),Y ; get keyword address high byte
LDY #$00
STA ut2_ph ; save keyword pointer high byte
PLA ; pull low byte
STA ut2_pl ; save keyword pointer low byte
LAB_1540
LDA (ut2_pl),Y ; get character
DEX ; decrement character count
BEQ LAB_1508 ; if last character exit and print
JSR LAB_PRNA ; go print the character
INY ; increment index
BNE LAB_1540 ; loop for next character
; perform FOR
LAB_FOR
LDA #$80 ; set FNX
STA Sufnxf ; set subscript/FNX flag
JSR LAB_LET ; go do LET
PLA ; pull return address
PLA ; pull return address
LDA #$10 ; we need 16d bytes !
JSR LAB_1212 ; check room on stack for A bytes
JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL])
CLC ; clear carry for add
TYA ; copy index to A
ADC Bpntrl ; add BASIC execute pointer low byte
PHA ; push onto stack
LDA Bpntrh ; get BASIC execute pointer high byte
ADC #$00 ; add carry
PHA ; push onto stack
LDA Clineh ; get current line high byte
PHA ; push onto stack
LDA Clinel ; get current line low byte
PHA ; push onto stack
LDA #TK_TO ; get "TO" token
JSR LAB_SCCA ; scan for CHR$(A) , else do syntax error then warm start
JSR LAB_CTNM ; check if source is numeric, else do type mismatch
JSR LAB_EVNM ; evaluate expression and check is numeric,
; else do type mismatch
LDA FAC1_s ; get FAC1 sign (b7)
ORA #$7F ; set all non sign bits
AND FAC1_1 ; and FAC1 mantissa1
STA FAC1_1 ; save FAC1 mantissa1
LDA #<LAB_159F ; set return address low byte
LDY #>LAB_159F ; set return address high byte
STA ut1_pl ; save return address low byte
STY ut1_ph ; save return address high byte
JMP LAB_1B66 ; round FAC1 and put on stack (returns to next instruction)
LAB_159F
LDA #<LAB_259C ; set 1 pointer low addr (default step size)
LDY #>LAB_259C ; set 1 pointer high addr
JSR LAB_UFAC ; unpack memory (AY) into FAC1
JSR LAB_GBYT ; scan memory
CMP #TK_STEP ; compare with STEP token
BNE LAB_15B3 ; jump if not "STEP"
;.was step so ..
JSR LAB_IGBY ; increment and scan memory
JSR LAB_EVNM ; evaluate expression and check is numeric,
; else do type mismatch
LAB_15B3
JSR LAB_27CA ; return A=FF,C=1/-ve A=01,C=0/+ve
STA FAC1_s ; set FAC1 sign (b7)
; this is +1 for +ve step and -1 for -ve step, in NEXT we
; compare the FOR value and the TO value and return +1 if
; FOR > TO, 0 if FOR = TO and -1 if FOR < TO. the value
; here (+/-1) is then compared to that result and if they
; are the same (+ve and FOR > TO or -ve and FOR < TO) then
; the loop is done
JSR LAB_1B5B ; push sign, round FAC1 and put on stack
LDA Frnxth ; get var pointer for FOR/NEXT high byte
PHA ; push on stack
LDA Frnxtl ; get var pointer for FOR/NEXT low byte
PHA ; push on stack
LDA #TK_FOR ; get FOR token
PHA ; push on stack
; interpreter inner loop
LAB_15C2
JSR LAB_1629 ; do CRTL-C check vector
LDA Bpntrl ; get BASIC execute pointer low byte
LDY Bpntrh ; get BASIC execute pointer high byte
LDX Clineh ; continue line is $FFxx for immediate mode
; ($00xx for RUN from immediate mode)
INX ; increment it (now $00 if immediate mode)
BEQ LAB_15D1 ; branch if null (immediate mode)
STA Cpntrl ; save continue pointer low byte
STY Cpntrh ; save continue pointer high byte
LAB_15D1
LDY #$00 ; clear index
LDA (Bpntrl),Y ; get next byte
BEQ LAB_15DC ; branch if null [EOL]
CMP #':' ; compare with ":"
BEQ LAB_15F6 ; branch if = (statement separator)
LAB_15D9
JMP LAB_SNER ; else syntax error then warm start
; have reached [EOL]
LAB_15DC
LDY #$02 ; set index
LDA (Bpntrl),Y ; get next line pointer high byte
CLC ; clear carry for no "BREAK" message
BEQ LAB_1651 ; if null go to immediate mode (was immediate or [EOT]
; marker)
INY ; increment index
LDA (Bpntrl),Y ; get line # low byte
STA Clinel ; save current line low byte
INY ; increment index
LDA (Bpntrl),Y ; get line # high byte
STA Clineh ; save current line high byte
TYA ; A now = 4
ADC Bpntrl ; add BASIC execute pointer low byte
STA Bpntrl ; save BASIC execute pointer low byte
BCC LAB_15F6 ; branch if no overflow
INC Bpntrh ; else increment BASIC execute pointer high byte
LAB_15F6
JSR LAB_IGBY ; increment and scan memory
LAB_15F9
JSR LAB_15FF ; go interpret BASIC code from (Bpntrl)
LAB_15FC
JMP LAB_15C2 ; loop
; interpret BASIC code from (Bpntrl)
LAB_15FF
BEQ LAB_1628 ; exit if zero [EOL]
LAB_1602
ASL ; *2 bytes per vector and normalise token
BCS LAB_1609 ; branch if was token
JMP LAB_LET ; else go do implied LET
LAB_1609
CMP #[TK_TAB-$80]*2 ; compare normalised token * 2 with TAB
BCS LAB_15D9 ; branch if A>=TAB (do syntax error then warm start)
; only tokens before TAB can start a line
TAY ; copy to index
LDA LAB_CTBL+1,Y ; get vector high byte
PHA ; onto stack
LDA LAB_CTBL,Y ; get vector low byte
PHA ; onto stack
JMP LAB_IGBY ; jump to increment and scan memory
; then "return" to vector
; CTRL-C check jump. this is called as a subroutine but exits back via a jump if a
; key press is detected.
LAB_1629
JMP (VEC_CC) ; ctrl c check vector
; if there was a key press it gets back here ..
LAB_1636
CMP #$03 ; compare with CTRL-C
; perform STOP
LAB_STOP
BCS LAB_163B ; branch if token follows STOP
; else just END
; END
LAB_END
CLC ; clear the carry, indicate a normal program end
LAB_163B
BNE LAB_167A ; if wasn't CTRL-C or there is a following byte return
LDA Bpntrh ; get the BASIC execute pointer high byte
EOR #>Ibuffs ; compare with buffer address high byte (Cb unchanged)
BEQ LAB_164F ; branch if the BASIC pointer is in the input buffer
; (can't continue in immediate mode)
; else ..
EOR #>Ibuffs ; correct the bits
LDY Bpntrl ; get BASIC execute pointer low byte
STY Cpntrl ; save continue pointer low byte
STA Cpntrh ; save continue pointer high byte
LAB_1647
LDA Clinel ; get current line low byte
LDY Clineh ; get current line high byte
STA Blinel ; save break line low byte
STY Blineh ; save break line high byte
LAB_164F
PLA ; pull return address low
PLA ; pull return address high
LAB_1651
BCC LAB_165E ; if was program end just do warm start
; else ..
LDA #<LAB_BMSG ; point to "Break" low byte
LDY #>LAB_BMSG ; point to "Break" high byte
JMP LAB_1269 ; print "Break" and do warm start
LAB_165E
JMP LAB_1274 ; go do warm start
; perform RESTORE
LAB_RESTORE
BNE LAB_RESTOREn ; branch if next character not null (RESTORE n)
LAB_161A
SEC ; set carry for subtract
LDA Smeml ; get start of mem low byte
SBC #$01 ; -1
LDY Smemh ; get start of mem high byte
BCS LAB_1624 ; branch if no underflow
LAB_uflow
DEY ; else decrement high byte
LAB_1624
STA Dptrl ; save DATA pointer low byte
STY Dptrh ; save DATA pointer high byte
LAB_1628
RTS
; is RESTORE n
LAB_RESTOREn
JSR LAB_GFPN ; get fixed-point number into temp integer
JSR LAB_SNBL ; scan for next BASIC line
LDA Clineh ; get current line high byte
CMP Itemph ; compare with temporary integer high byte
BCS LAB_reset_search ; branch if >= (start search from beginning)
TYA ; else copy line index to A
SEC ; set carry (+1)
ADC Bpntrl ; add BASIC execute pointer low byte
LDX Bpntrh ; get BASIC execute pointer high byte
BCC LAB_go_search ; branch if no overflow to high byte
INX ; increment high byte
BCS LAB_go_search ; branch always (can never be carry clear)
; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml)
LAB_reset_search
LDA Smeml ; get start of mem low byte
LDX Smemh ; get start of mem high byte
; search for line # in temp (Itempl/Itemph) from (AX)
LAB_go_search
JSR LAB_SHLN ; search Basic for temp integer line number from AX
BCS LAB_line_found ; if carry set go set pointer
JMP LAB_16F7 ; else go do "Undefined statement" error
LAB_line_found
; carry already set for subtract
LDA Baslnl ; get pointer low byte
SBC #$01 ; -1
LDY Baslnh ; get pointer high byte
BCS LAB_1624 ; branch if no underflow (save DATA pointer and return)
BCC LAB_uflow ; else decrement high byte then save DATA pointer and
; return (branch always)
; perform NULL
LAB_NULL
JSR LAB_GTBY ; get byte parameter
STX Nullct ; save new NULL count
LAB_167A
RTS
; perform CONT
LAB_CONT
BNE LAB_167A ; if following byte exit to do syntax error
LDY Cpntrh ; get continue pointer high byte
BNE LAB_166C ; go do continue if we can
LDX #$1E ; error code $1E ("Can't continue" error)
JMP LAB_XERR ; do error #X, then warm start
; we can continue so ..
LAB_166C
LDA #TK_ON ; set token for ON
JSR LAB_IRQ ; set IRQ flags
LDA #TK_ON ; set token for ON
JSR LAB_NMI ; set NMI flags
STY Bpntrh ; save BASIC execute pointer high byte
LDA Cpntrl ; get continue pointer low byte
STA Bpntrl ; save BASIC execute pointer low byte
LDA Blinel ; get break line low byte
LDY Blineh ; get break line high byte
STA Clinel ; set current line low byte
STY Clineh ; set current line high byte
RTS
; perform RUN
LAB_RUN
BNE LAB_1696 ; branch if RUN n
JMP LAB_1477 ; reset execution to start, clear variables, flush stack and
; return
; does RUN n
LAB_1696
JSR LAB_147A ; go do "CLEAR"
BEQ LAB_16B0 ; get n and do GOTO n (branch always as CLEAR sets Z=1)
; perform DO
LAB_DO
LDA #$05 ; need 5 bytes for DO
JSR LAB_1212 ; check room on stack for A bytes
LDA Bpntrh ; get BASIC execute pointer high byte
PHA ; push on stack
LDA Bpntrl ; get BASIC execute pointer low byte
PHA ; push on stack
LDA Clineh ; get current line high byte
PHA ; push on stack
LDA Clinel ; get current line low byte
PHA ; push on stack
LDA #TK_DO ; token for DO
PHA ; push on stack
JSR LAB_GBYT ; scan memory
JMP LAB_15C2 ; go do interpreter inner loop
; perform GOSUB
LAB_GOSUB
LDA #$05 ; need 5 bytes for GOSUB
JSR LAB_1212 ; check room on stack for A bytes
LDA Bpntrh ; get BASIC execute pointer high byte
PHA ; push on stack
LDA Bpntrl ; get BASIC execute pointer low byte
PHA ; push on stack
LDA Clineh ; get current line high byte
PHA ; push on stack
LDA Clinel ; get current line low byte
PHA ; push on stack
LDA #TK_GOSUB ; token for GOSUB
PHA ; push on stack
LAB_16B0
JSR LAB_GBYT ; scan memory
JSR LAB_GOTO ; perform GOTO n
JMP LAB_15C2 ; go do interpreter inner loop
; (can't RTS, we used the stack!)
; perform GOTO
LAB_GOTO
JSR LAB_GFPN ; get fixed-point number into temp integer
JSR LAB_SNBL ; scan for next BASIC line
LDA Clineh ; get current line high byte
CMP Itemph ; compare with temporary integer high byte
BCS LAB_16D0 ; branch if >= (start search from beginning)
TYA ; else copy line index to A
SEC ; set carry (+1)
ADC Bpntrl ; add BASIC execute pointer low byte
LDX Bpntrh ; get BASIC execute pointer high byte
BCC LAB_16D4 ; branch if no overflow to high byte
INX ; increment high byte
BCS LAB_16D4 ; branch always (can never be carry)
; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml)
LAB_16D0
LDA Smeml ; get start of mem low byte
LDX Smemh ; get start of mem high byte
; search for line # in temp (Itempl/Itemph) from (AX)
LAB_16D4
JSR LAB_SHLN ; search Basic for temp integer line number from AX
BCC LAB_16F7 ; if carry clear go do "Undefined statement" error
; (unspecified statement)
; carry already set for subtract
LDA Baslnl ; get pointer low byte
SBC #$01 ; -1
STA Bpntrl ; save BASIC execute pointer low byte
LDA Baslnh ; get pointer high byte
SBC #$00 ; subtract carry
STA Bpntrh ; save BASIC execute pointer high byte
LAB_16E5
RTS
LAB_DONOK
LDX #$22 ; error code $22 ("LOOP without DO" error)
JMP LAB_XERR ; do error #X, then warm start
; perform LOOP
LAB_LOOP
TAY ; save following token
TSX ; copy stack pointer
LDA LAB_STAK+3,X ; get token byte from stack
CMP #TK_DO ; compare with DO token
BNE LAB_DONOK ; branch if no matching DO
INX ; dump calling routine return address
INX ; dump calling routine return address
TXS ; correct stack
TYA ; get saved following token back
BEQ LoopAlways ; if no following token loop forever
; (stack pointer in X)
CMP #':' ; could be ':'
BEQ LoopAlways ; if :... loop forever
SBC #TK_UNTIL ; subtract token for UNTIL, we know carry is set here
TAX ; copy to X (if it was UNTIL then Y will be correct)
BEQ DoRest ; branch if was UNTIL
DEX ; decrement result
BNE LAB_16FC ; if not WHILE go do syntax error and warm start
; only if the token was WHILE will this fail
DEX ; set invert result byte
DoRest
STX Frnxth ; save invert result byte
JSR LAB_IGBY ; increment and scan memory
JSR LAB_EVEX ; evaluate expression
LDA FAC1_e ; get FAC1 exponent
BEQ DoCmp ; if =0 go do straight compare
LDA #$FF ; else set all bits
DoCmp
TSX ; copy stack pointer
EOR Frnxth ; EOR with invert byte
BNE LoopDone ; if <> 0 clear stack and back to interpreter loop
; loop condition wasn't met so do it again
LoopAlways
LDA LAB_STAK+2,X ; get current line low byte
STA Clinel ; save current line low byte
LDA LAB_STAK+3,X ; get current line high byte
STA Clineh ; save current line high byte
LDA LAB_STAK+4,X ; get BASIC execute pointer low byte
STA Bpntrl ; save BASIC execute pointer low byte
LDA LAB_STAK+5,X ; get BASIC execute pointer high byte
STA Bpntrh ; save BASIC execute pointer high byte
JSR LAB_GBYT ; scan memory
JMP LAB_15C2 ; go do interpreter inner loop
; clear stack and back to interpreter loop
LoopDone
INX ; dump DO token
INX ; dump current line low byte
INX ; dump current line high byte
INX ; dump BASIC execute pointer low byte
INX ; dump BASIC execute pointer high byte
TXS ; correct stack
JMP LAB_DATA ; go perform DATA (find : or [EOL])
; do the return without gosub error
LAB_16F4
LDX #$04 ; error code $04 ("RETURN without GOSUB" error)
.byte $2C ; makes next line BIT LAB_0EA2
LAB_16F7 ; do undefined statement error
LDX #$0E ; error code $0E ("Undefined statement" error)
JMP LAB_XERR ; do error #X, then warm start
; perform RETURN
LAB_RETURN
BNE LAB_16E5 ; exit if following token (to allow syntax error)
LAB_16E8
PLA ; dump calling routine return address
PLA ; dump calling routine return address
PLA ; pull token
CMP #TK_GOSUB ; compare with GOSUB token
BNE LAB_16F4 ; branch if no matching GOSUB
LAB_16FF
PLA ; pull current line low byte
STA Clinel ; save current line low byte
PLA ; pull current line high byte
STA Clineh ; save current line high byte
PLA ; pull BASIC execute pointer low byte
STA Bpntrl ; save BASIC execute pointer low byte
PLA ; pull BASIC execute pointer high byte
STA Bpntrh ; save BASIC execute pointer high byte
; now do the DATA statement as we could be returning into
; the middle of an ON <var> GOSUB n,m,p,q line
; (the return address used by the DATA statement is the one
; pushed before the GOSUB was executed!)
; perform DATA
LAB_DATA
JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL])
; set BASIC execute pointer
LAB_170F
TYA ; copy index to A
CLC ; clear carry for add
ADC Bpntrl ; add BASIC execute pointer low byte
STA Bpntrl ; save BASIC execute pointer low byte
BCC LAB_1719 ; skip next if no carry
INC Bpntrh ; else increment BASIC execute pointer high byte
LAB_1719
RTS
LAB_16FC
JMP LAB_SNER ; do syntax error then warm start
; scan for next BASIC statement ([:] or [EOL])
; returns Y as index to [:] or [EOL]
LAB_SNBS
LDX #':' ; set look for character = ":"
.byte $2C ; makes next line BIT $00A2
; scan for next BASIC line
; returns Y as index to [EOL]
LAB_SNBL
LDX #$00 ; set alt search character = [EOL]
LDY #$00 ; set search character = [EOL]
STY Asrch ; store search character
LAB_1725
TXA ; get alt search character
EOR Asrch ; toggle search character, effectively swap with $00
STA Asrch ; save swapped search character
LAB_172D
LDA (Bpntrl),Y ; get next byte
BEQ LAB_1719 ; exit if null [EOL]
CMP Asrch ; compare with search character
BEQ LAB_1719 ; exit if found
INY ; increment index
CMP #$22 ; compare current character with open quote
BNE LAB_172D ; if not open quote go get next character
BEQ LAB_1725 ; if found go swap search character for alt search character
; perform IF
LAB_IF
JSR LAB_EVEX ; evaluate the expression
JSR LAB_GBYT ; scan memory
CMP #TK_THEN ; compare with THEN token
BEQ LAB_174B ; if it was THEN go do IF
; wasn't IF .. THEN so must be IF .. GOTO
CMP #TK_GOTO ; compare with GOTO token
BNE LAB_16FC ; if it wasn't GOTO go do syntax error
LDX Bpntrl ; save the basic pointer low byte
LDY Bpntrh ; save the basic pointer high byte
JSR LAB_IGBY ; increment and scan memory
BCS LAB_16FC ; if not numeric go do syntax error
STX Bpntrl ; restore the basic pointer low byte
STY Bpntrh ; restore the basic pointer high byte
LAB_174B
LDA FAC1_e ; get FAC1 exponent
BEQ LAB_174E ; if the result was zero go look for an ELSE
JSR LAB_IGBY ; else increment and scan memory
BCS LAB_174D ; if not numeric go do var or keyword
LAB_174C
JMP LAB_GOTO ; else was numeric so do GOTO n
; is var or keyword
LAB_174D
CMP #TK_RETURN ; compare the byte with the token for RETURN
BNE LAB_174G ; if it wasn't RETURN go interpret BASIC code from (Bpntrl)
; and return to this code to process any following code
JMP LAB_1602 ; else it was RETURN so interpret BASIC code from (Bpntrl)
; but don't return here
LAB_174G
JSR LAB_15FF ; interpret BASIC code from (Bpntrl)
; the IF was executed and there may be a following ELSE so the code needs to return
; here to check and ignore the ELSE if present
LDY #$00 ; clear the index
LDA (Bpntrl),Y ; get the next BASIC byte
CMP #TK_ELSE ; compare it with the token for ELSE
BEQ LAB_DATA ; if ELSE ignore the following statement
; there was no ELSE so continue execution of IF <expr> THEN <stat> [: <stat>]. any
; following ELSE will, correctly, cause a syntax error
RTS ; else return to the interpreter inner loop
; perform ELSE after IF
LAB_174E
LDY #$00 ; clear the BASIC byte index
LDX #$01 ; clear the nesting depth
LAB_1750
INY ; increment the BASIC byte index
LDA (Bpntrl),Y ; get the next BASIC byte
BEQ LAB_1753 ; if EOL go add the pointer and return
CMP #TK_IF ; compare the byte with the token for IF
BNE LAB_1752 ; if not IF token skip the depth increment
INX ; else increment the nesting depth ..
BNE LAB_1750 ; .. and continue looking
LAB_1752
CMP #TK_ELSE ; compare the byte with the token for ELSE
BNE LAB_1750 ; if not ELSE token continue looking
DEX ; was ELSE so decrement the nesting depth
BNE LAB_1750 ; loop if still nested
INY ; increment the BASIC byte index past the ELSE
; found the matching ELSE, now do <{n|statement}>
LAB_1753
TYA ; else copy line index to A
CLC ; clear carry for add
ADC Bpntrl ; add the BASIC execute pointer low byte
STA Bpntrl ; save the BASIC execute pointer low byte
BCC LAB_1754 ; branch if no overflow to high byte
INC Bpntrh ; else increment the BASIC execute pointer high byte
LAB_1754
JSR LAB_GBYT ; scan memory
BCC LAB_174C ; if numeric do GOTO n
; the code will return to the interpreter loop at the
; tail end of the GOTO <n>
JMP LAB_15FF ; interpret BASIC code from (Bpntrl)
; the code will return to the interpreter loop at the
; tail end of the <statement>
; perform REM, skip (rest of) line
LAB_REM
JSR LAB_SNBL ; scan for next BASIC line
JMP LAB_170F ; go set BASIC execute pointer and return, branch always
LAB_16FD
JMP LAB_SNER ; do syntax error then warm start
; perform ON
LAB_ON
CMP #TK_IRQ ; was it IRQ token ?
BNE LAB_NOIN ; if not go check NMI
JMP LAB_SIRQ ; else go set-up IRQ
LAB_NOIN
CMP #TK_NMI ; was it NMI token ?
BNE LAB_NONM ; if not go do normal ON command
JMP LAB_SNMI ; else go set-up NMI
LAB_NONM
JSR LAB_GTBY ; get byte parameter
PHA ; push GOTO/GOSUB token
CMP #TK_GOSUB ; compare with GOSUB token
BEQ LAB_176B ; branch if GOSUB
CMP #TK_GOTO ; compare with GOTO token
LAB_1767
BNE LAB_16FD ; if not GOTO do syntax error then warm start
; next character was GOTO or GOSUB
LAB_176B
DEC FAC1_3 ; decrement index (byte value)
BNE LAB_1773 ; branch if not zero
PLA ; pull GOTO/GOSUB token
JMP LAB_1602 ; go execute it
LAB_1773
JSR LAB_IGBY ; increment and scan memory
JSR LAB_GFPN ; get fixed-point number into temp integer (skip this n)
; (we could LDX #',' and JSR LAB_SNBL+2, then we
; just BNE LAB_176B for the loop. should be quicker ..
; no we can't, what if we meet a colon or [EOL]?)
CMP #$2C ; compare next character with ","
BEQ LAB_176B ; loop if ","
LAB_177E
PLA ; else pull keyword token (run out of options)
; also dump +/-1 pointer low byte and exit
LAB_177F
RTS
; takes n * 106 + 11 cycles where n is the number of digits
; get fixed-point number into temp integer
LAB_GFPN
LDX #$00 ; clear reg
STX Itempl ; clear temporary integer low byte
LAB_1785
STX Itemph ; save temporary integer high byte
BCS LAB_177F ; return if carry set, end of scan, character was
; not 0-9
CPX #$19 ; compare high byte with $19
TAY ; ensure Zb = 0 if the branch is taken
BCS LAB_1767 ; branch if >=, makes max line # 63999 because next
; bit does *$0A, = 64000, compare at target will fail
; and do syntax error
SBC #'0'-1 ; subtract "0", $2F + carry, from byte
TAY ; copy binary digit
LDA Itempl ; get temporary integer low byte
ASL ; *2 low byte
ROL Itemph ; *2 high byte
ASL ; *2 low byte
ROL Itemph ; *2 high byte, *4
ADC Itempl ; + low byte, *5
STA Itempl ; save it
TXA ; get high byte copy to A
ADC Itemph ; + high byte, *5
ASL Itempl ; *2 low byte, *10d
ROL ; *2 high byte, *10d
TAX ; copy high byte back to X
TYA ; get binary digit back
ADC Itempl ; add number low byte
STA Itempl ; save number low byte
BCC LAB_17B3 ; if no overflow to high byte get next character
INX ; else increment high byte
LAB_17B3
JSR LAB_IGBY ; increment and scan memory
JMP LAB_1785 ; loop for next character
; perform DEC
LAB_DEC
LDA #<LAB_2AFD ; set -1 pointer low byte
.byte $2C ; BIT abs to skip the LDA below
; perform INC
LAB_INC
LDA #<LAB_259C ; set 1 pointer low byte
LAB_17B5
PHA ; save +/-1 pointer low byte
LAB_17B7
JSR LAB_GVAR ; get var address
LDX Dtypef ; get data type flag, $FF=string, $00=numeric
BMI IncrErr ; exit if string
STA Lvarpl ; save var address low byte
STY Lvarph ; save var address high byte
JSR LAB_UFAC ; unpack memory (AY) into FAC1
PLA ; get +/-1 pointer low byte
PHA ; save +/-1 pointer low byte
LDY #>LAB_259C ; set +/-1 pointer high byte (both the same)
JSR LAB_246C ; add (AY) to FAC1
JSR LAB_PFAC ; pack FAC1 into variable (Lvarpl)
JSR LAB_GBYT ; scan memory
CMP #',' ; compare with ","
BNE LAB_177E ; exit if not "," (either end or error)
; was "," so another INCR variable to do
JSR LAB_IGBY ; increment and scan memory
JMP LAB_17B7 ; go do next var
IncrErr
JMP LAB_1ABC ; do "Type mismatch" error then warm start
; perform LET
LAB_LET
JSR LAB_GVAR ; get var address
STA Lvarpl ; save var address low byte
STY Lvarph ; save var address high byte
LDA #TK_EQUAL ; get = token
JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start
LDA Dtypef ; get data type flag, $FF=string, $00=numeric
PHA ; push data type flag
JSR LAB_EVEX ; evaluate expression
PLA ; pop data type flag
ROL ; set carry if type = string
JSR LAB_CKTM ; type match check, set C for string
BNE LAB_17D5 ; branch if string
JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return
; string LET
LAB_17D5
LDY #$02 ; set index to pointer high byte
LDA (des_pl),Y ; get string pointer high byte
CMP Sstorh ; compare bottom of string space high byte
BCC LAB_17F4 ; if less assign value and exit (was in program memory)
BNE LAB_17E6 ; branch if >
; else was equal so compare low bytes
DEY ; decrement index
LDA (des_pl),Y ; get pointer low byte
CMP Sstorl ; compare bottom of string space low byte
BCC LAB_17F4 ; if less assign value and exit (was in program memory)
; pointer was >= to bottom of string space pointer
LAB_17E6
LDY des_ph ; get descriptor pointer high byte
CPY Svarh ; compare start of vars high byte
BCC LAB_17F4 ; branch if less (descriptor is on stack)
BNE LAB_17FB ; branch if greater (descriptor is not on stack)
; else high bytes were equal so ..
LDA des_pl ; get descriptor pointer low byte
CMP Svarl ; compare start of vars low byte
BCS LAB_17FB ; branch if >= (descriptor is not on stack)
LAB_17F4
LDA des_pl ; get descriptor pointer low byte
LDY des_ph ; get descriptor pointer high byte
JMP LAB_1811 ; clean stack, copy descriptor to variable and return
; make space and copy string
LAB_17FB
LDY #$00 ; index to length
LDA (des_pl),Y ; get string length
JSR LAB_209C ; copy string
LDA des_2l ; get descriptor pointer low byte
LDY des_2h ; get descriptor pointer high byte
STA ssptr_l ; save descriptor pointer low byte
STY ssptr_h ; save descriptor pointer high byte
JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill)
LDA #<FAC1_e ; set descriptor pointer low byte
LDY #>FAC1_e ; get descriptor pointer high byte
; clean stack and assign value to string variable
LAB_1811
STA des_2l ; save descriptor_2 pointer low byte
STY des_2h ; save descriptor_2 pointer high byte
JSR LAB_22EB ; clean descriptor stack, YA = pointer
LDY #$00 ; index to length
LDA (des_2l),Y ; get string length
STA (Lvarpl),Y ; copy to let string variable
INY ; index to string pointer low byte
LDA (des_2l),Y ; get string pointer low byte
STA (Lvarpl),Y ; copy to let string variable
INY ; index to string pointer high byte
LDA (des_2l),Y ; get string pointer high byte
STA (Lvarpl),Y ; copy to let string variable
RTS
; perform GET
LAB_GET
JSR LAB_GVAR ; get var address
STA Lvarpl ; save var address low byte
STY Lvarph ; save var address high byte
JSR INGET ; get input byte
LDX Dtypef ; get data type flag, $FF=string, $00=numeric
BMI LAB_GETS ; go get string character
; was numeric get
TAY ; copy character to Y
JSR LAB_1FD0 ; convert Y to byte in FAC1
JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return
LAB_GETS
PHA ; save character
LDA #$01 ; string is single byte
BCS LAB_IsByte ; branch if byte received
PLA ; string is null
LAB_IsByte
JSR LAB_MSSP ; make string space A bytes long A=$AC=length,
; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte
BEQ LAB_NoSt ; skip store if null string
PLA ; get character back
LDY #$00 ; clear index
STA (str_pl),Y ; save byte in string (byte IS string!)
LAB_NoSt
JSR LAB_RTST ; check for space on descriptor stack then put address
; and length on descriptor stack and update stack pointers
JMP LAB_17D5 ; do string LET and return
; perform PRINT
LAB_1829
JSR LAB_18C6 ; print string from Sutill/Sutilh
LAB_182C
JSR LAB_GBYT ; scan memory
; PRINT
LAB_PRINT
BEQ LAB_CRLF ; if nothing following just print CR/LF
LAB_1831
CMP #TK_TAB ; compare with TAB( token
BEQ LAB_18A2 ; go do TAB/SPC
CMP #TK_SPC ; compare with SPC( token
BEQ LAB_18A2 ; go do TAB/SPC
CMP #',' ; compare with ","
BEQ LAB_188B ; go do move to next TAB mark
CMP #';' ; compare with ";"
BEQ LAB_18BD ; if ";" continue with PRINT processing
JSR LAB_EVEX ; evaluate expression
BIT Dtypef ; test data type flag, $FF=string, $00=numeric
BMI LAB_1829 ; branch if string
JSR LAB_296E ; convert FAC1 to string
JSR LAB_20AE ; print " terminated string to Sutill/Sutilh
LDY #$00 ; clear index
; don't check fit if terminal width byte is zero
LDA TWidth ; get terminal width byte
BEQ LAB_185E ; skip check if zero
SEC ; set carry for subtract
SBC TPos ; subtract terminal position
SBC (des_pl),Y ; subtract string length
BCS LAB_185E ; branch if less than terminal width
JSR LAB_CRLF ; else print CR/LF
LAB_185E
JSR LAB_18C6 ; print string from Sutill/Sutilh
BEQ LAB_182C ; always go continue processing line
; CR/LF return to BASIC from BASIC input handler
LAB_1866
LDA #$00 ; clear byte
STA Ibuffs,X ; null terminate input
LDX #<Ibuffs ; set X to buffer start-1 low byte
LDY #>Ibuffs ; set Y to buffer start-1 high byte
; print CR/LF
LAB_CRLF
LDA #$0D ; load [CR]
JSR LAB_PRNA ; go print the character
LDA #$0A ; load [LF]
BNE LAB_PRNA ; go print the character and return, branch always
LAB_188B
LDA TPos ; get terminal position
CMP Iclim ; compare with input column limit
BCC LAB_1897 ; branch if less
JSR LAB_CRLF ; else print CR/LF (next line)
BNE LAB_18BD ; continue with PRINT processing (branch always)
LAB_1897
SEC ; set carry for subtract
LAB_1898
SBC TabSiz ; subtract TAB size
BCS LAB_1898 ; loop if result was +ve
EOR #$FF ; complement it
ADC #$01 ; +1 (twos complement)
BNE LAB_18B6 ; always print A spaces (result is never $00)
; do TAB/SPC
LAB_18A2
PHA ; save token
JSR LAB_SGBY ; scan and get byte parameter
CMP #$29 ; is next character )
BNE LAB_1910 ; if not do syntax error then warm start
PLA ; get token back
CMP #TK_TAB ; was it TAB ?
BNE LAB_18B7 ; if not go do SPC
; calculate TAB offset
TXA ; copy integer value to A
SBC TPos ; subtract terminal position
BCC LAB_18BD ; branch if result was < 0 (can't TAB backwards)
; print A spaces
LAB_18B6
TAX ; copy result to X
LAB_18B7
TXA ; set flags on size for SPC
BEQ LAB_18BD ; branch if result was = $0, already here
; print X spaces
LAB_18BA
JSR LAB_18E0 ; print " "
DEX ; decrement count
BNE LAB_18BA ; loop if not all done
; continue with PRINT processing
LAB_18BD
JSR LAB_IGBY ; increment and scan memory
BNE LAB_1831 ; if more to print go do it
RTS
; print null terminated string from memory
LAB_18C3
JSR LAB_20AE ; print " terminated string to Sutill/Sutilh
; print string from Sutill/Sutilh
LAB_18C6
JSR LAB_22B6 ; pop string off descriptor stack, or from top of string
; space returns with A = length, X=$71=pointer low byte,
; Y=$72=pointer high byte
LDY #$00 ; reset index
TAX ; copy length to X
BEQ LAB_188C ; exit (RTS) if null string
LAB_18CD
LDA (ut1_pl),Y ; get next byte
JSR LAB_PRNA ; go print the character
INY ; increment index
DEX ; decrement count
BNE LAB_18CD ; loop if not done yet
RTS
; Print single format character
; print " "
LAB_18E0
LDA #$20 ; load " "
.byte $2C ; change next line to BIT LAB_3FA9
; print "?" character
LAB_18E3
LDA #$3F ; load "?" character
; print character in A
; now includes the null handler
; also includes infinite line length code
; note! some routines expect this one to exit with Zb=0
LAB_PRNA
CMP #' ' ; compare with " "
BCC LAB_18F9 ; branch if less (non printing)
; else printable character
PHA ; save the character
; don't check fit if terminal width byte is zero
LDA TWidth ; get terminal width
BNE LAB_18F0 ; branch if not zero (not infinite length)
; is "infinite line" so check TAB position
LDA TPos ; get position
SBC TabSiz ; subtract TAB size, carry set by CMP #$20 above
BNE LAB_18F7 ; skip reset if different
STA TPos ; else reset position
BEQ LAB_18F7 ; go print character
LAB_18F0
CMP TPos ; compare with terminal character position
BNE LAB_18F7 ; branch if not at end of line
JSR LAB_CRLF ; else print CR/LF
LAB_18F7
INC TPos ; increment terminal position
PLA ; get character back
LAB_18F9
JSR V_OUTP ; output byte via output vector
CMP #$0D ; compare with [CR]
BNE LAB_188A ; branch if not [CR]
; else print nullct nulls after the [CR]
STX TempB ; save buffer index
LDX Nullct ; get null count
BEQ LAB_1886 ; branch if no nulls
LDA #$00 ; load [NULL]
LAB_1880
JSR LAB_PRNA ; go print the character
DEX ; decrement count
BNE LAB_1880 ; loop if not all done
LDA #$0D ; restore the character (and set the flags)
LAB_1886
STX TPos ; clear terminal position (X always = zero when we get here)
LDX TempB ; restore buffer index
LAB_188A
AND #$FF ; set the flags
LAB_188C
RTS
; handle bad input data
LAB_1904
LDA Imode ; get input mode flag, $00=INPUT, $00=READ
BPL LAB_1913 ; branch if INPUT (go do redo)
LDA Dlinel ; get current DATA line low byte
LDY Dlineh ; get current DATA line high byte
STA Clinel ; save current line low byte
STY Clineh ; save current line high byte
LAB_1910
JMP LAB_SNER ; do syntax error then warm start
; mode was INPUT
LAB_1913
LDA #<LAB_REDO ; point to redo message (low addr)
LDY #>LAB_REDO ; point to redo message (high addr)
JSR LAB_18C3 ; print null terminated string from memory
LDA Cpntrl ; get continue pointer low byte
LDY Cpntrh ; get continue pointer high byte
STA Bpntrl ; save BASIC execute pointer low byte
STY Bpntrh ; save BASIC execute pointer high byte
RTS
; perform INPUT
LAB_INPUT
CMP #$22 ; compare next byte with open quote
BNE LAB_1934 ; branch if no prompt string
JSR LAB_1BC1 ; print "..." string
LDA #$3B ; load A with ";"
JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start
JSR LAB_18C6 ; print string from Sutill/Sutilh
; done with prompt, now get data
LAB_1934
JSR LAB_CKRN ; check not Direct, back here if ok
JSR LAB_INLN ; print "? " and get BASIC input
LDA #$00 ; set mode = INPUT
CMP Ibuffs ; test first byte in buffer
BNE LAB_1953 ; branch if not null input
CLC ; was null input so clear carry to exit program
JMP LAB_1647 ; go do BREAK exit
; perform READ
LAB_READ
LDX Dptrl ; get DATA pointer low byte
LDY Dptrh ; get DATA pointer high byte
LDA #$80 ; set mode = READ
LAB_1953
STA Imode ; set input mode flag, $00=INPUT, $80=READ
STX Rdptrl ; save READ pointer low byte
STY Rdptrh ; save READ pointer high byte
; READ or INPUT next variable from list
LAB_195B
JSR LAB_GVAR ; get (var) address
STA Lvarpl ; save address low byte
STY Lvarph ; save address high byte
LDA Bpntrl ; get BASIC execute pointer low byte
LDY Bpntrh ; get BASIC execute pointer high byte
STA Itempl ; save as temporary integer low byte
STY Itemph ; save as temporary integer high byte
LDX Rdptrl ; get READ pointer low byte
LDY Rdptrh ; get READ pointer high byte
STX Bpntrl ; set BASIC execute pointer low byte
STY Bpntrh ; set BASIC execute pointer high byte
JSR LAB_GBYT ; scan memory
BNE LAB_1988 ; branch if not null
; pointer was to null entry
BIT Imode ; test input mode flag, $00=INPUT, $80=READ
BMI LAB_19DD ; branch if READ
; mode was INPUT
JSR LAB_18E3 ; print "?" character (double ? for extended input)
JSR LAB_INLN ; print "? " and get BASIC input
STX Bpntrl ; set BASIC execute pointer low byte
STY Bpntrh ; set BASIC execute pointer high byte
LAB_1985
JSR LAB_GBYT ; scan memory
LAB_1988
BIT Dtypef ; test data type flag, $FF=string, $00=numeric
BPL LAB_19B0 ; branch if numeric
; else get string
STA Srchc ; save search character
CMP #$22 ; was it " ?
BEQ LAB_1999 ; branch if so
LDA #':' ; else search character is ":"
STA Srchc ; set new search character
LDA #',' ; other search character is ","
CLC ; clear carry for add
LAB_1999
STA Asrch ; set second search character
LDA Bpntrl ; get BASIC execute pointer low byte
LDY Bpntrh ; get BASIC execute pointer high byte
ADC #$00 ; c is =1 if we came via the BEQ LAB_1999, else =0
BCC LAB_19A4 ; branch if no execute pointer low byte rollover
INY ; else increment high byte
LAB_19A4
JSR LAB_20B4 ; print Srchc or Asrch terminated string to Sutill/Sutilh
JSR LAB_23F3 ; restore BASIC execute pointer from temp (Btmpl/Btmph)
JSR LAB_17D5 ; go do string LET
JMP LAB_19B6 ; go check string terminator
; get numeric INPUT
LAB_19B0
JSR LAB_2887 ; get FAC1 from string
JSR LAB_PFAC ; pack FAC1 into (Lvarpl)
LAB_19B6
JSR LAB_GBYT ; scan memory
BEQ LAB_19C5 ; branch if null (last entry)
CMP #',' ; else compare with ","
BEQ LAB_19C2 ; branch if ","
JMP LAB_1904 ; else go handle bad input data
; got good input data
LAB_19C2
JSR LAB_IGBY ; increment and scan memory
LAB_19C5
LDA Bpntrl ; get BASIC execute pointer low byte (temp READ/INPUT ptr)
LDY Bpntrh ; get BASIC execute pointer high byte (temp READ/INPUT ptr)
STA Rdptrl ; save for now
STY Rdptrh ; save for now
LDA Itempl ; get temporary integer low byte (temp BASIC execute ptr)
LDY Itemph ; get temporary integer high byte (temp BASIC execute ptr)
STA Bpntrl ; set BASIC execute pointer low byte
STY Bpntrh ; set BASIC execute pointer high byte
JSR LAB_GBYT ; scan memory
BEQ LAB_1A03 ; if null go do extra ignored message
JSR LAB_1C01 ; else scan for "," , else do syntax error then warm start
JMP LAB_195B ; go INPUT next variable from list
; find next DATA statement or do "Out of DATA" error
LAB_19DD
JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL])
INY ; increment index
TAX ; copy character ([:] or [EOL])
BNE LAB_19F6 ; branch if [:]
LDX #$06 ; set for "Out of DATA" error
INY ; increment index, now points to next line pointer high byte
LDA (Bpntrl),Y ; get next line pointer high byte
BEQ LAB_1A54 ; branch if end (eventually does error X)
INY ; increment index
LDA (Bpntrl),Y ; get next line # low byte
STA Dlinel ; save current DATA line low byte
INY ; increment index
LDA (Bpntrl),Y ; get next line # high byte
INY ; increment index
STA Dlineh ; save current DATA line high byte
LAB_19F6
LDA (Bpntrl),Y ; get byte
INY ; increment index
TAX ; copy to X
JSR LAB_170F ; set BASIC execute pointer
CPX #TK_DATA ; compare with "DATA" token
BEQ LAB_1985 ; was "DATA" so go do next READ
BNE LAB_19DD ; go find next statement if not "DATA"
; end of INPUT/READ routine
LAB_1A03
LDA Rdptrl ; get temp READ pointer low byte
LDY Rdptrh ; get temp READ pointer high byte
LDX Imode ; get input mode flag, $00=INPUT, $80=READ
BPL LAB_1A0E ; branch if INPUT
JMP LAB_1624 ; save AY as DATA pointer and return
; we were getting INPUT
LAB_1A0E
LDY #$00 ; clear index
LDA (Rdptrl),Y ; get next byte
BNE LAB_1A1B ; error if not end of INPUT
RTS
; user typed too much
LAB_1A1B
LDA #<LAB_IMSG ; point to extra ignored message (low addr)
LDY #>LAB_IMSG ; point to extra ignored message (high addr)
JMP LAB_18C3 ; print null terminated string from memory and return
; search the stack for FOR activity
; exit with z=1 if FOR else exit with z=0
LAB_11A1
TSX ; copy stack pointer
INX ; +1 pass return address
INX ; +2 pass return address
INX ; +3 pass calling routine return address
INX ; +4 pass calling routine return address
LAB_11A6
LDA LAB_STAK+1,X ; get token byte from stack
CMP #TK_FOR ; is it FOR token
BNE LAB_11CE ; exit if not FOR token
; was FOR token
LDA Frnxth ; get var pointer for FOR/NEXT high byte
BNE LAB_11BB ; branch if not null
LDA LAB_STAK+2,X ; get FOR variable pointer low byte
STA Frnxtl ; save var pointer for FOR/NEXT low byte
LDA LAB_STAK+3,X ; get FOR variable pointer high byte
STA Frnxth ; save var pointer for FOR/NEXT high byte
LAB_11BB
CMP LAB_STAK+3,X ; compare var pointer with stacked var pointer (high byte)
BNE LAB_11C7 ; branch if no match
LDA Frnxtl ; get var pointer for FOR/NEXT low byte
CMP LAB_STAK+2,X ; compare var pointer with stacked var pointer (low byte)
BEQ LAB_11CE ; exit if match found
LAB_11C7
TXA ; copy index
CLC ; clear carry for add
ADC #$10 ; add FOR stack use size
TAX ; copy back to index
BNE LAB_11A6 ; loop if not at start of stack
LAB_11CE
RTS
; perform NEXT
LAB_NEXT
BNE LAB_1A46 ; branch if NEXT var
LDY #$00 ; else clear Y
BEQ LAB_1A49 ; branch always (no variable to search for)
; NEXT var
LAB_1A46
JSR LAB_GVAR ; get variable address
LAB_1A49
STA Frnxtl ; store variable pointer low byte
STY Frnxth ; store variable pointer high byte
; (both cleared if no variable defined)
JSR LAB_11A1 ; search the stack for FOR activity
BEQ LAB_1A56 ; branch if found
LDX #$00 ; else set error $00 ("NEXT without FOR" error)
LAB_1A54
BEQ LAB_1ABE ; do error #X, then warm start
LAB_1A56
TXS ; set stack pointer, X set by search, dumps return addresses
TXA ; copy stack pointer
SEC ; set carry for subtract
SBC #$F7 ; point to TO var
STA ut2_pl ; save pointer to TO var for compare
ADC #$FB ; point to STEP var
LDY #>LAB_STAK ; point to stack page high byte
JSR LAB_UFAC ; unpack memory (STEP value) into FAC1
TSX ; get stack pointer back
LDA LAB_STAK+8,X ; get step sign
STA FAC1_s ; save FAC1 sign (b7)
LDA Frnxtl ; get FOR variable pointer low byte
LDY Frnxth ; get FOR variable pointer high byte
JSR LAB_246C ; add (FOR variable) to FAC1
JSR LAB_PFAC ; pack FAC1 into (FOR variable)
LDY #>LAB_STAK ; point to stack page high byte
JSR LAB_27FA ; compare FAC1 with (Y,ut2_pl) (TO value)
TSX ; get stack pointer back
CMP LAB_STAK+8,X ; compare step sign
BEQ LAB_1A9B ; branch if = (loop complete)
; loop back and do it all again
LDA LAB_STAK+$0D,X ; get FOR line low byte
STA Clinel ; save current line low byte
LDA LAB_STAK+$0E,X ; get FOR line high byte
STA Clineh ; save current line high byte
LDA LAB_STAK+$10,X ; get BASIC execute pointer low byte
STA Bpntrl ; save BASIC execute pointer low byte
LDA LAB_STAK+$0F,X ; get BASIC execute pointer high byte
STA Bpntrh ; save BASIC execute pointer high byte
LAB_1A98
JMP LAB_15C2 ; go do interpreter inner loop
; loop complete so carry on
LAB_1A9B
TXA ; stack copy to A
ADC #$0F ; add $10 ($0F+carry) to dump FOR structure
TAX ; copy back to index
TXS ; copy to stack pointer
JSR LAB_GBYT ; scan memory
CMP #',' ; compare with ","
BNE LAB_1A98 ; branch if not "," (go do interpreter inner loop)
; was "," so another NEXT variable to do
JSR LAB_IGBY ; else increment and scan memory
JSR LAB_1A46 ; do NEXT (var)
; evaluate expression and check is numeric, else do type mismatch
LAB_EVNM
JSR LAB_EVEX ; evaluate expression
; check if source is numeric, else do type mismatch
LAB_CTNM
CLC ; destination is numeric
.byte $24 ; makes next line BIT $38
; check if source is string, else do type mismatch
LAB_CTST
SEC ; required type is string
; type match check, set C for string, clear C for numeric
LAB_CKTM
BIT Dtypef ; test data type flag, $FF=string, $00=numeric
BMI LAB_1ABA ; branch if data type is string
; else data type was numeric
BCS LAB_1ABC ; if required type is string do type mismatch error
LAB_1AB9
RTS
; data type was string, now check required type
LAB_1ABA
BCS LAB_1AB9 ; exit if required type is string
; else do type mismatch error
LAB_1ABC
LDX #$18 ; error code $18 ("Type mismatch" error)
LAB_1ABE
JMP LAB_XERR ; do error #X, then warm start
; evaluate expression
LAB_EVEX
LDX Bpntrl ; get BASIC execute pointer low byte
BNE LAB_1AC7 ; skip next if not zero
DEC Bpntrh ; else decrement BASIC execute pointer high byte
LAB_1AC7
DEC Bpntrl ; decrement BASIC execute pointer low byte
LAB_EVEZ
LDA #$00 ; set null precedence (flag done)
LAB_1ACC
PHA ; push precedence byte
LDA #$02 ; 2 bytes
JSR LAB_1212 ; check room on stack for A bytes
JSR LAB_GVAL ; get value from line
LDA #$00 ; clear A
STA comp_f ; clear compare function flag
LAB_1ADB
JSR LAB_GBYT ; scan memory
LAB_1ADE
SEC ; set carry for subtract
SBC #TK_GT ; subtract token for > (lowest comparison function)
BCC LAB_1AFA ; branch if < TK_GT
CMP #$03 ; compare with ">" to "<" tokens
BCS LAB_1AFA ; branch if >= TK_SGN (highest evaluation function +1)
; was token for > = or < (A = 0, 1 or 2)
CMP #$01 ; compare with token for =
ROL ; *2, b0 = carry (=1 if token was = or <)
; (A = 0, 3 or 5)
EOR #$01 ; toggle b0
; (A = 1, 2 or 4. 1 if >, 2 if =, 4 if <)
EOR comp_f ; EOR with compare function flag bits
CMP comp_f ; compare with compare function flag
BCC LAB_1B53 ; if <(comp_f) do syntax error then warm start
; was more than one <, = or >)
STA comp_f ; save new compare function flag
JSR LAB_IGBY ; increment and scan memory
JMP LAB_1ADE ; go do next character
; token is < ">" or > "<" tokens
LAB_1AFA
LDX comp_f ; get compare function flag
BNE LAB_1B2A ; branch if compare function
BCS LAB_1B78 ; go do functions
; else was < TK_GT so is operator or lower
ADC #TK_GT-TK_PLUS ; add # of operators (+, -, *, /, ^, AND, OR or EOR)
BCC LAB_1B78 ; branch if < + operator
; carry was set so token was +, -, *, /, ^, AND, OR or EOR
BNE LAB_1B0B ; branch if not + token
BIT Dtypef ; test data type flag, $FF=string, $00=numeric
BPL LAB_1B0B ; branch if not string
; will only be $00 if type is string and token was +
JMP LAB_224D ; add strings, string 1 is in descriptor des_pl, string 2
; is in line, and return
LAB_1B0B
STA ut1_pl ; save it
ASL ; *2
ADC ut1_pl ; *3
TAY ; copy to index
LAB_1B13
PLA ; pull previous precedence
CMP LAB_OPPT,Y ; compare with precedence byte
BCS LAB_1B7D ; branch if A >=
JSR LAB_CTNM ; check if source is numeric, else do type mismatch
LAB_1B1C
PHA ; save precedence
LAB_1B1D
JSR LAB_1B43 ; get vector, execute function then continue evaluation
PLA ; restore precedence
LDY prstk ; get precedence stacked flag
BPL LAB_1B3C ; branch if stacked values
TAX ; copy precedence (set flags)
BEQ LAB_1B9D ; exit if done
BNE LAB_1B86 ; else pop FAC2 and return, branch always
LAB_1B2A
ROL Dtypef ; shift data type flag into Cb
TXA ; copy compare function flag
STA Dtypef ; clear data type flag, X is 0xxx xxxx
ROL ; shift data type into compare function byte b0
LDX Bpntrl ; get BASIC execute pointer low byte
BNE LAB_1B34 ; branch if no underflow
DEC Bpntrh ; else decrement BASIC execute pointer high byte
LAB_1B34
DEC Bpntrl ; decrement BASIC execute pointer low byte
TK_LT_PLUS = TK_LT-TK_PLUS
LDY #TK_LT_PLUS*3 ; set offset to last operator entry
STA comp_f ; save new compare function flag
BNE LAB_1B13 ; branch always
LAB_1B3C
CMP LAB_OPPT,Y ;.compare with stacked function precedence
BCS LAB_1B86 ; branch if A >=, pop FAC2 and return
BCC LAB_1B1C ; branch always
;.get vector, execute function then continue evaluation
LAB_1B43
LDA LAB_OPPT+2,Y ; get function vector high byte
PHA ; onto stack
LDA LAB_OPPT+1,Y ; get function vector low byte
PHA ; onto stack
; now push sign, round FAC1 and put on stack
JSR LAB_1B5B ; function will return here, then the next RTS will call
; the function
LDA comp_f ; get compare function flag
PHA ; push compare evaluation byte
LDA LAB_OPPT,Y ; get precedence byte
JMP LAB_1ACC ; continue evaluating expression
LAB_1B53
JMP LAB_SNER ; do syntax error then warm start
; push sign, round FAC1 and put on stack
LAB_1B5B
PLA ; get return addr low byte
STA ut1_pl ; save it
INC ut1_pl ; increment it (was ret-1 pushed? yes!)
; note! no check is made on the high byte! if the calling
; routine assembles to a page edge then this all goes
; horribly wrong !!!
PLA ; get return addr high byte
STA ut1_ph ; save it
LDA FAC1_s ; get FAC1 sign (b7)
PHA ; push sign
; round FAC1 and put on stack
LAB_1B66
JSR LAB_27BA ; round FAC1
LDA FAC1_3 ; get FAC1 mantissa3
PHA ; push on stack
LDA FAC1_2 ; get FAC1 mantissa2
PHA ; push on stack
LDA FAC1_1 ; get FAC1 mantissa1
PHA ; push on stack
LDA FAC1_e ; get FAC1 exponent
PHA ; push on stack
JMP (ut1_pl) ; return, sort of
; do functions
LAB_1B78
LDY #$FF ; flag function
PLA ; pull precedence byte
LAB_1B7B
BEQ LAB_1B9D ; exit if done
LAB_1B7D
CMP #$64 ; compare previous precedence with $64
BEQ LAB_1B84 ; branch if was $64 (< function)
JSR LAB_CTNM ; check if source is numeric, else do type mismatch
LAB_1B84
STY prstk ; save precedence stacked flag
; pop FAC2 and return
LAB_1B86
PLA ; pop byte
LSR ; shift out comparison evaluation lowest bit
STA Cflag ; save comparison evaluation flag
PLA ; pop exponent
STA FAC2_e ; save FAC2 exponent
PLA ; pop mantissa1
STA FAC2_1 ; save FAC2 mantissa1
PLA ; pop mantissa2
STA FAC2_2 ; save FAC2 mantissa2
PLA ; pop mantissa3
STA FAC2_3 ; save FAC2 mantissa3
PLA ; pop sign
STA FAC2_s ; save FAC2 sign (b7)
EOR FAC1_s ; EOR FAC1 sign (b7)
STA FAC_sc ; save sign compare (FAC1 EOR FAC2)
LAB_1B9D
LDA FAC1_e ; get FAC1 exponent
RTS
; print "..." string to string util area
LAB_1BC1
LDA Bpntrl ; get BASIC execute pointer low byte
LDY Bpntrh ; get BASIC execute pointer high byte
ADC #$00 ; add carry to low byte
BCC LAB_1BCA ; branch if no overflow
INY ; increment high byte
LAB_1BCA
JSR LAB_20AE ; print " terminated string to Sutill/Sutilh
JMP LAB_23F3 ; restore BASIC execute pointer from temp and return
; get value from line
LAB_GVAL
JSR LAB_IGBY ; increment and scan memory
BCS LAB_1BAC ; branch if not numeric character
; else numeric string found (e.g. 123)
LAB_1BA9
JMP LAB_2887 ; get FAC1 from string and return
; get value from line .. continued
; wasn't a number so ..
LAB_1BAC
TAX ; set the flags
BMI LAB_1BD0 ; if -ve go test token values
; else it is either a string, number, variable or (<expr>)
CMP #'$' ; compare with "$"
BEQ LAB_1BA9 ; branch if "$", hex number
CMP #'%' ; else compare with "%"
BEQ LAB_1BA9 ; branch if "%", binary number
CMP #'.' ; compare with "."
BEQ LAB_1BA9 ; if so get FAC1 from string and return (e.g. was .123)
; it wasn't any sort of number so ..
CMP #$22 ; compare with "
BEQ LAB_1BC1 ; branch if open quote
; wasn't any sort of number so ..
; evaluate expression within parentheses
CMP #'(' ; compare with "("
BNE LAB_1C18 ; if not "(" get (var), return value in FAC1 and $ flag
LAB_1BF7
JSR LAB_EVEZ ; evaluate expression, no decrement
; all the 'scan for' routines return the character after the sought character
; scan for ")" , else do syntax error then warm start
LAB_1BFB
LDA #$29 ; load A with ")"
; scan for CHR$(A) , else do syntax error then warm start
LAB_SCCA
LDY #$00 ; clear index
CMP (Bpntrl),Y ; check next byte is = A
BNE LAB_SNER ; if not do syntax error then warm start
JMP LAB_IGBY ; increment and scan memory then return
; scan for "(" , else do syntax error then warm start
LAB_1BFE
LDA #$28 ; load A with "("
BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start
; (branch always)
; scan for "," , else do syntax error then warm start
LAB_1C01
LDA #$2C ; load A with ","
BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start
; (branch always)
; syntax error then warm start
LAB_SNER
LDX #$02 ; error code $02 ("Syntax" error)
JMP LAB_XERR ; do error #X, then warm start
; get value from line .. continued
; do tokens
LAB_1BD0
CMP #TK_MINUS ; compare with token for -
BEQ LAB_1C11 ; branch if - token (do set-up for functions)
; wasn't -n so ..
CMP #TK_PLUS ; compare with token for +
BEQ LAB_GVAL ; branch if + token (+n = n so ignore leading +)
CMP #TK_NOT ; compare with token for NOT
BNE LAB_1BE7 ; branch if not token for NOT
; was NOT token
TK_EQUAL_PLUS = TK_EQUAL-TK_PLUS
LDY #TK_EQUAL_PLUS*3 ; offset to NOT function
BNE LAB_1C13 ; do set-up for function then execute (branch always)
; do = compare
LAB_EQUAL
JSR LAB_EVIR ; evaluate integer expression (no sign check)
LDA FAC1_3 ; get FAC1 mantissa3
EOR #$FF ; invert it
TAY ; copy it
LDA FAC1_2 ; get FAC1 mantissa2
EOR #$FF ; invert it
JMP LAB_AYFC ; save and convert integer AY to FAC1 and return
; get value from line .. continued
; wasn't +, -, or NOT so ..
LAB_1BE7
CMP #TK_FN ; compare with token for FN
BNE LAB_1BEE ; branch if not token for FN
JMP LAB_201E ; go evaluate FNx
; get value from line .. continued
; wasn't +, -, NOT or FN so ..
LAB_1BEE
SBC #TK_SGN ; subtract with token for SGN
BCS LAB_1C27 ; if a function token go do it
JMP LAB_SNER ; else do syntax error
; set-up for functions
LAB_1C11
TK_GT_PLUS = TK_GT-TK_PLUS
LDY #TK_GT_PLUS*3 ; set offset from base to > operator
LAB_1C13
PLA ; dump return address low byte
PLA ; dump return address high byte
JMP LAB_1B1D ; execute function then continue evaluation
; variable name set-up
; get (var), return value in FAC_1 and $ flag
LAB_1C18
JSR LAB_GVAR ; get (var) address
STA FAC1_2 ; save address low byte in FAC1 mantissa2
STY FAC1_3 ; save address high byte in FAC1 mantissa3
LDX Dtypef ; get data type flag, $FF=string, $00=numeric
BMI LAB_1C25 ; if string then return (does RTS)
LAB_1C24
JMP LAB_UFAC ; unpack memory (AY) into FAC1
LAB_1C25
RTS
; get value from line .. continued
; only functions left so ..
; set up function references
; new for V2.0+ this replaces a lot of IF .. THEN .. ELSEIF .. THEN .. that was needed
; to process function calls. now the function vector is computed and pushed on the stack
; and the preprocess offset is read. if the preprocess offset is non zero then the vector
; is calculated and the routine called, if not this routine just does RTS. whichever
; happens the RTS at the end of this routine, or the end of the preprocess routine, calls
; the function code
; this also removes some less than elegant code that was used to bypass type checking
; for functions that returned strings
LAB_1C27
ASL ; *2 (2 bytes per function address)
TAY ; copy to index
LDA LAB_FTBM,Y ; get function jump vector high byte
PHA ; push functions jump vector high byte
LDA LAB_FTBL,Y ; get function jump vector low byte
PHA ; push functions jump vector low byte
LDA LAB_FTPM,Y ; get function pre process vector high byte
BEQ LAB_1C56 ; skip pre process if null vector
PHA ; push functions pre process vector high byte
LDA LAB_FTPL,Y ; get function pre process vector low byte
PHA ; push functions pre process vector low byte
LAB_1C56
RTS ; do function, or pre process, call
; process string expression in parenthesis
LAB_PPFS
JSR LAB_1BF7 ; process expression in parenthesis
JMP LAB_CTST ; check if source is string then do function,
; else do type mismatch
; process numeric expression in parenthesis
LAB_PPFN
JSR LAB_1BF7 ; process expression in parenthesis
JMP LAB_CTNM ; check if source is numeric then do function,
; else do type mismatch
; set numeric data type and increment BASIC execute pointer
LAB_PPBI
LSR Dtypef ; clear data type flag, $FF=string, $00=numeric
JMP LAB_IGBY ; increment and scan memory then do function