URL
                    https://opencores.org/ocsvn/rtf65002/rtf65002/trunk
                
            Subversion Repositories rtf65002
[/] [rtf65002/] [trunk/] [software/] [asm/] [basic.asm] - Rev 40
Compare with Previous | Blame | View Log
; 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 routinemacro nat.byte $42xcecpu RTF65002endmmacro emmsecxceendmmacro emm816clcxcecpu W65C816SendmDisplayChar = $FFFF8000KeybdCheckForKeyDirect = $FFFF8004KeybdGetCharDirect = $FFFF8008KeybdGetChar = $FFFF800CKeybdCheckForChar = $FFFF8010RequestIOFocus = $FFFF8014ReleaseIOFocus = $FFFF8018ClearScreen = $FFFF801CHomeCursor = $FFFF8020ExitTask = $FFFF8024SetKeyboardEcho = $FFFF8028Sleep = $FFFF802CLoadFile = $FFFF8030SaveFile = $FFFF8034ICacheInvalidateAll = $FFFF8038ICacheInvalidateLine = $FFFF803CLEDS =$FFDC0600OUTNDX EQU 0x778INPNDX EQU 0x779FILENAME EQU 0x6C0FILEBUF EQU 0x05F60000; zero page use ..LAB_WARM = $00 ; BASIC warm start entry pointWrmjpl = LAB_WARM+1; BASIC warm start vector jump low byteWrmjph = LAB_WARM+2; BASIC warm start vector jump high byteUsrjmp = $0A ; USR function JMP addressUsrjpl = Usrjmp+1 ; USR function JMP vector low byteUsrjph = Usrjmp+2 ; USR function JMP vector high byteNullct = $0D ; nulls output after each lineTPos = $0E ; BASIC terminal position byteTWidth = $0F ; BASIC terminal width byteIclim = $10 ; input column limitItempl = $11 ; temporary integer low byteItemph = Itempl+1 ; temporary integer high bytenums_1 = Itempl ; number to bin/hex string convert MSBnums_2 = nums_1+1 ; number to bin/hex string convertnums_3 = nums_1+2 ; number to bin/hex string convert LSBSrchc = $5B ; search characterTemp3 = Srchc ; temp byte used in number routinesScnquo = $5C ; scan-between-quotes flagAsrch = Scnquo ; alt search characterXOAw_l = Srchc ; eXclusive OR, OR and AND word low byteXOAw_h = Scnquo ; eXclusive OR, OR and AND word high byteIbptr = $5D ; input buffer pointerDimcnt = Ibptr ; # of dimensionsTindx = Ibptr ; token indexDefdim = $5E ; default DIM flagDtypef = $5F ; data type flag, $FF=string, $00=numericOquote = $60 ; open quote flag (b7) (Flag: DATA scan; LIST quote; memory)Gclctd = $60 ; garbage collected flagSufnxf = $61 ; subscript/FNX flag, 1xxx xxx = FN(0xxx xxx)Imode = $62 ; input mode flag, $00=INPUT, $80=READCflag = $63 ; comparison evaluation flagTabSiz = $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 stacklast_sl = $66 ; last descriptor stack address low bytelast_sh = $67 ; last descriptor stack address high byte (always $00)des_sk = $68 ; descriptor stack start address (temp strings); = $70 ; End of descriptor stackut1_pl = $71 ; utility pointer 1 low byteut1_ph = ut1_pl+1 ; utility pointer 1 high byteut2_pl = $73 ; utility pointer 2 low byteut2_ph = ut2_pl+1 ; utility pointer 2 high byteTemp_2 = ut1_pl ; temp byte for block moveFACt_1 = $75 ; FAC temp mantissa1FACt_2 = FACt_1+1 ; FAC temp mantissa2FACt_3 = FACt_2+1 ; FAC temp mantissa3dims_l = FACt_2 ; array dimension size low bytedims_h = FACt_3 ; array dimension size high byteTempB = $78 ; temp page 0 byteSmeml = $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 byteSutilh = Sutill+1 ; string utility ptr high byteEmeml = $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 byteCpntrh = Cpntrl+1 ; continue pointer high byteDlinel = $8D ; current DATA line low byteDlineh = Dlinel+1 ; current DATA line high byteDptrl = $8F ; DATA pointer low byteDptrh = Dptrl+1 ; DATA pointer high byteRdptrl = $91 ; read pointer low byteRdptrh = Rdptrl+1 ; read pointer high byteVarnm1 = $93 ; current var name 1st byteVarnm2 = Varnm1+1 ; current var name 2nd byteCvaral = $95 ; current var address low byteCvarah = Cvaral+1 ; current var address high byteFrnxtl = $97 ; var pointer for FOR/NEXT low byteFrnxth = Frnxtl+1 ; var pointer for FOR/NEXT high byteTidx1 = Frnxtl ; temp line indexLvarpl = Frnxtl ; let var pointer low byteLvarph = Frnxth ; let var pointer high byteprstk = $99 ; precedence stacked flagcomp_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 bytefunc_h = func_l+1 ; function pointer high bytegarb_l = func_l ; garbage collection working pointer low bytegarb_h = func_h ; garbage collection working pointer high bytedes_2l = $9E ; string descriptor_2 pointer low bytedes_2h = des_2l+1 ; string descriptor_2 pointer high byteg_step = $A0 ; garbage collect step sizeFnxjmp = $A1 ; jump vector for functionsFnxjpl = Fnxjmp+1 ; functions jump vector low byteFnxjph = Fnxjmp+2 ; functions jump vector high byteg_indx = Fnxjpl ; garbage collect temp indexFAC2_r = $A3 ; FAC2 rounding byteAdatal = $A4 ; array data pointer low byteAdatah = Adatal+1 ; array data pointer high byteNbendl = Adatal ; new block end pointer low byteNbendh = Adatah ; new block end pointer high byteObendl = $A6 ; old block end pointer low byteObendh = Obendl+1 ; old block end pointer high bytenumexp = $A8 ; string to float number exponent countexpcnt = $A9 ; string to float exponent countnumbit = numexp ; bit count for array element calculationsnumdpf = $AA ; string to float decimal point flagexpneg = $AB ; string to float eval exponent -ve flagAstrtl = numdpf ; array start pointer low byteAstrth = expneg ; array start pointer high byteHistrl = numdpf ; highest string low byteHistrh = expneg ; highest string high byteBaslnl = numdpf ; BASIC search line pointer low byteBaslnh = expneg ; BASIC search line pointer high byteFvar_l = numdpf ; find/found variable pointer low byteFvar_h = expneg ; find/found variable pointer high byteOstrtl = numdpf ; old block start pointer low byteOstrth = expneg ; old block start pointer high byteVrschl = numdpf ; variable search pointer low byteVrschh = expneg ; variable search pointer high byteFAC1_e = $AC ; FAC1 exponentFAC1_1 = FAC1_e+1 ; FAC1 mantissa1FAC1_2 = FAC1_e+2 ; FAC1 mantissa2FAC1_3 = FAC1_e+3 ; FAC1 mantissa3FAC1_s = FAC1_e+4 ; FAC1 sign (b7)str_ln = FAC1_e ; string lengthstr_pl = FAC1_1 ; string pointer low bytestr_ph = FAC1_2 ; string pointer high bytedes_pl = FAC1_2 ; string descriptor pointer low bytedes_ph = FAC1_3 ; string descriptor pointer high bytemids_l = FAC1_3 ; MID$ string temp length bytenegnum = $B1 ; string to float eval -ve flagnumcon = $B1 ; series evaluation constant countFAC1_o = $B2 ; FAC1 overflow byteFAC2_e = $B3 ; FAC2 exponentFAC2_1 = FAC2_e+1 ; FAC2 mantissa1FAC2_2 = FAC2_e+2 ; FAC2 mantissa2FAC2_3 = FAC2_e+3 ; FAC2 mantissa3FAC2_s = FAC2_e+4 ; FAC2 sign (b7)FAC_sc = $B8 ; FAC sign comparison, Acc#1 vs #2FAC1_r = $B9 ; FAC1 rounding bytessptr_l = FAC_sc ; string start pointer low bytessptr_h = FAC1_r ; string start pointer high bytesdescr = FAC_sc ; string descriptor pointercsidx = $BA ; line crunch save indexAsptl = csidx ; array size/pointer low byteAspth = $BB ; array size/pointer high byteBtmpl = Asptl ; BASIC pointer temp low byteBtmph = Aspth ; BASIC pointer temp low byteCptrl = Asptl ; BASIC pointer temp low byteCptrh = Aspth ; BASIC pointer temp low byteSendl = Asptl ; BASIC pointer temp low byteSendh = Aspth ; BASIC pointer temp low byteLAB_IGBY = $BC ; get next BASIC byte subroutineLAB_GBYT = $C2 ; get current BASIC byte subroutineBpntrl = $C3 ; BASIC execute (get byte) pointer low byteBpntrh = Bpntrl+1 ; BASIC execute (get byte) pointer high byte; = $D7 ; end of get BASIC char subroutineRbyte4 = $D8 ; extra PRNG byteRbyte1 = Rbyte4+1 ; most significant PRNG byteRbyte2 = Rbyte4+2 ; middle PRNG byteRbyte3 = Rbyte4+3 ; least significant PRNG byteNmiBase = $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 byteIrqBase = $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 ; unusedDecss = $EF ; number to decimal string startDecssp1 = 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 tokenTK_FOR = TK_END+1 ; FOR tokenTK_NEXT = TK_FOR+1 ; NEXT tokenTK_DATA = TK_NEXT+1 ; DATA tokenTK_INPUT = TK_DATA+1 ; INPUT tokenTK_DIM = TK_INPUT+1 ; DIM tokenTK_READ = TK_DIM+1 ; READ tokenTK_LET = TK_READ+1 ; LET tokenTK_DEC = TK_LET+1 ; DEC tokenTK_GOTO = TK_DEC+1 ; GOTO tokenTK_RUN = TK_GOTO+1 ; RUN tokenTK_IF = TK_RUN+1 ; IF tokenTK_RESTORE = TK_IF+1 ; RESTORE tokenTK_GOSUB = TK_RESTORE+1 ; GOSUB tokenTK_RETIRQ = TK_GOSUB+1 ; RETIRQ tokenTK_RETNMI = TK_RETIRQ+1 ; RETNMI tokenTK_RETURN = TK_RETNMI+1 ; RETURN tokenTK_REM = TK_RETURN+1 ; REM tokenTK_STOP = TK_REM+1 ; STOP tokenTK_ON = TK_STOP+1 ; ON tokenTK_NULL = TK_ON+1 ; NULL tokenTK_INC = TK_NULL+1 ; INC tokenTK_WAIT = TK_INC+1 ; WAIT tokenTK_LOAD = TK_WAIT+1 ; LOAD tokenTK_SAVE = TK_LOAD+1 ; SAVE tokenTK_DEF = TK_SAVE+1 ; DEF tokenTK_POKE = TK_DEF+1 ; POKE tokenTK_DOKE = TK_POKE+1 ; DOKE tokenTK_CALL = TK_DOKE+1 ; CALL tokenTK_DO = TK_CALL+1 ; DO tokenTK_LOOP = TK_DO+1 ; LOOP tokenTK_PRINT = TK_LOOP+1 ; PRINT tokenTK_CONT = TK_PRINT+1 ; CONT tokenTK_LIST = TK_CONT+1 ; LIST tokenTK_CLEAR = TK_LIST+1 ; CLEAR tokenTK_NEW = TK_CLEAR+1 ; NEW tokenTK_WIDTH = TK_NEW+1 ; WIDTH tokenTK_GET = TK_WIDTH+1 ; GET tokenTK_SWAP = TK_GET+1 ; SWAP tokenTK_BITSET = TK_SWAP+1 ; BITSET tokenTK_BITCLR = TK_BITSET+1 ; BITCLR tokenTK_IRQ = TK_BITCLR+1 ; IRQ tokenTK_NMI = TK_IRQ+1 ; NMI tokenTK_BYE = TK_NMI+1; secondary command tokens, can't start a statementTK_TAB = TK_BYE+1 ; TAB tokenTK_ELSE = TK_TAB+1 ; ELSE tokenTK_TO = TK_ELSE+1 ; TO tokenTK_FN = TK_TO+1 ; FN tokenTK_SPC = TK_FN+1 ; SPC tokenTK_THEN = TK_SPC+1 ; THEN tokenTK_NOT = TK_THEN+1 ; NOT tokenTK_STEP = TK_NOT+1 ; STEP tokenTK_UNTIL = TK_STEP+1 ; UNTIL tokenTK_WHILE = TK_UNTIL+1 ; WHILE tokenTK_OFF = TK_WHILE+1 ; OFF token; opperator tokensTK_PLUS = TK_OFF+1 ; + tokenTK_MINUS = TK_PLUS+1 ; - tokenTK_MUL = TK_MINUS+1 ; * tokenTK_DIV = TK_MUL+1 ; / tokenTK_POWER = TK_DIV+1 ; ^ tokenTK_AND = TK_POWER+1 ; AND tokenTK_EOR = TK_AND+1 ; EOR tokenTK_OR = TK_EOR+1 ; OR tokenTK_RSHIFT = TK_OR+1 ; RSHIFT tokenTK_LSHIFT = TK_RSHIFT+1 ; LSHIFT tokenTK_GT = TK_LSHIFT+1 ; > tokenTK_EQUAL = TK_GT+1 ; = tokenTK_LT = TK_EQUAL+1 ; < token; functions tokensTK_SGN = TK_LT+1 ; SGN tokenTK_INT = TK_SGN+1 ; INT tokenTK_ABS = TK_INT+1 ; ABS tokenTK_USR = TK_ABS+1 ; USR tokenTK_FRE = TK_USR+1 ; FRE tokenTK_POS = TK_FRE+1 ; POS tokenTK_SQR = TK_POS+1 ; SQR tokenTK_RND = TK_SQR+1 ; RND tokenTK_LOG = TK_RND+1 ; LOG tokenTK_EXP = TK_LOG+1 ; EXP tokenTK_COS = TK_EXP+1 ; COS tokenTK_SIN = TK_COS+1 ; SIN tokenTK_TAN = TK_SIN+1 ; TAN tokenTK_ATN = TK_TAN+1 ; ATN tokenTK_PEEK = TK_ATN+1 ; PEEK tokenTK_DEEK = TK_PEEK+1 ; DEEK tokenTK_SADD = TK_DEEK+1 ; SADD tokenTK_LEN = TK_SADD+1 ; LEN tokenTK_STRS = TK_LEN+1 ; STR$ tokenTK_VAL = TK_STRS+1 ; VAL tokenTK_ASC = TK_VAL+1 ; ASC tokenTK_UCASES = TK_ASC+1 ; UCASE$ tokenTK_LCASES = TK_UCASES+1 ; LCASE$ tokenTK_CHRS = TK_LCASES+1 ; CHR$ tokenTK_HEXS = TK_CHRS+1 ; HEX$ tokenTK_BINS = TK_HEXS+1 ; BIN$ tokenTK_BITTST = TK_BINS+1 ; BITTST tokenTK_MAX = TK_BITTST+1 ; MAX tokenTK_MIN = TK_MAX+1 ; MIN tokenTK_PI = TK_MIN+1 ; PI tokenTK_TWOPI = TK_PI+1 ; TWOPI tokenTK_VPTR = TK_TWOPI+1 ; VARPTR tokenTK_LEFTS = TK_VPTR+1 ; LEFT$ tokenTK_RIGHTS = TK_LEFTS+1 ; RIGHT$ tokenTK_MIDS = TK_RIGHTS+1 ; MID$ token; offsets from a base of X or YPLUS_0 = $00 ; X or Y plus 0PLUS_1 = $01 ; X or Y plus 1PLUS_2 = $02 ; X or Y plus 2PLUS_3 = $03 ; X or Y plus 3LAB_STAK = $0100 ; stack bottom, no offsetLAB_SKFE = LAB_STAK+$FE; flushed stack addressLAB_SKFF = LAB_STAK+$FF; flushed stack addressccflag = $0200 ; BASIC CTRL-C flag, 00 = enabled, 01 = disccbyte = ccflag+1 ; BASIC CTRL-C byteccnull = ccbyte+1 ; BASIC CTRL-C byte timeoutVEC_CC = ccnull+1 ; ctrl c check vectorVEC_IN = VEC_CC+2 ; input vectorVEC_OUT = VEC_IN+2 ; output vectorVEC_LD = VEC_OUT+2 ; load vectorVEC_SV = VEC_LD+2 ; save vector; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80;Ibuffs = IRQ_vec+$14Ibuffs = VEC_SV+$14; start of input buffer after IRQ/NMI codeIbuffe = Ibuffs+$47; end of input bufferRam_base = $0400 ; start of user RAM (set as needed, should be page aligned)Ram_top = $1800 ; end of user RAM+1 (set as needed, should be page aligned)include "supermon816.asm"; This start can be changed to suit your system; *= $C000cpu W65C02org $C000; BASIC cold start entry point; new page 2 initialisation, copy block to ccflag onmessage "LAB_COLD"LAB_COLDLDY #PG2_TABE-PG2_TABS-1; byte count-1LAB_2D13LDA PG2_TABS,Y ; get byteSTA ccflag,Y ; store in page 2DEY ; decrement countBPL LAB_2D13 ; loop if not doneLDX #$FF ; set byteSTX Ibuffs-1 ; *** Added by Daryl Rictor for SBC-2 compatibilitySTX Clineh ; set current line high byte (set immediate mode)TXS ; reset stack pointerLDA #$4C ; code for JMPSTA Fnxjmp ; save for jump vector for functions; copy block from LAB_2CEE to $00BC - $00D3LDX #StrTab-LAB_2CEE ; set byte countLAB_2D4ELDA LAB_2CEE-1,X ; get byte from tableSTA LAB_IGBY-1,X ; save byte in page zeroDEX ; decrement countBNE LAB_2D4E ; loop if not all done; copy block from StrTab to $0000 - $0012LAB_GMEMLDX #EndTab-StrTab-1 ; set byte count-1TabLoopLDA StrTab,X ; get byte from tableSTA PLUS_0,X ; save byte in page zeroDEX ; decrement countBPL TabLoop ; loop if not all done; set-up start valuesLDA #$00 ; clear ASTA NmiBase ; clear NMI handler enabled flagSTA IrqBase ; clear IRQ handler enabled flagSTA FAC1_o ; clear FAC1 overflow byteSTA last_sh ; clear descriptor stack top item pointer high byteLDA #$0E ; set default tab sizeSTA TabSiz ; save itLDA #$03 ; set garbage collect step size for descriptor stackSTA g_step ; save itLDX #des_sk ; descriptor stack startSTX next_s ; set descriptor stack pointerJSR LAB_CRLF ; print CR/LFLDA #<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 memoryJSR LAB_INLN ; print "? " and get BASIC inputSTX Bpntrl ; set BASIC execute pointer low byteSTY Bpntrh ; set BASIC execute pointer high byteJSR LAB_GBYT ; get last byte backBNE 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_baseLAB_2D93INC Itempl ; increment temporary integer low byteBNE LAB_2D99 ; branch if no overflowINC Itemph ; increment temporary integer high byteLDA Itemph ; get high byteCMP #>Ram_top ; compare with top of RAM+1BEQ LAB_2DB6 ; branch if match (end of user RAM)LAB_2D99LDA #$55 ; set test byteSTA (Itempl),Y ; save via temporary integerCMP (Itempl),Y ; compare via temporary integerBNE LAB_2DB6 ; branch if failASL ; shift test byte left (now $AA)STA (Itempl),Y ; save via temporary integerCMP (Itempl),Y ; compare via temporary integerBEQ LAB_2D93 ; if ok go do next byteBNE LAB_2DB6 ; branch if failLAB_2DAAJSR LAB_2887 ; get FAC1 from stringLDA FAC1_e ; get FAC1 exponentCMP #$98 ; compare with exponent = 2^24BCS LAB_GMEM ; if too large go try againJSR LAB_F2FU ; save integer part of FAC1 in temporary integer; (no range check)LAB_2DB6LDA Itempl ; get temporary integer low byteLDY Itemph ; get temporary integer high byteCPY #<Ram_base+1 ; compare with start of RAM+$100 high byteBCC 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_OKSTA Ememl ; set end of mem low byteSTY Ememh ; set end of mem high byteSTA Sstorl ; set bottom of string space low byteSTY Sstorh ; set bottom of string space high byteLDY #<Ram_base ; set start addr low byteLDX #>Ram_base ; set start addr high byteSTY Smeml ; save start of mem low byteSTX Smemh ; save start of mem high byte; this line is only needed if Ram_base is not $xx00; LDY #$00 ; clear YTYA ; clear ASTA (Smeml),Y ; clear first byteINC 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 byteLAB_2E05JSR LAB_CRLF ; print CR/LFJSR LAB_1463 ; do "NEW" and "CLEAR"LDA Ememl ; get end of mem low byteSEC ; set carry for subtractSBC Smeml ; subtract start of mem low byteTAX ; copy to XLDA Ememh ; get end of mem high byteSBC Smemh ; subtract start of mem high byteJSR 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 memoryLDA #<LAB_1274 ; warm start vector low byteLDY #>LAB_1274 ; warm start vector high byteSTA Wrmjpl ; save warm start vector low byteSTY Wrmjph ; save warm start vector high byteJMP (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_11CFJSR 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 byteSTY 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 endLAB_11D6SEC ; set carry for subtractLDA Obendl ; get block end low byteSBC Ostrtl ; subtract block start low byteTAY ; copy MOD(block length/$100) byte to YLDA Obendh ; get block end high byteSBC Ostrth ; subtract block start high byteTAX ; copy block length high byte to XINX ; +1 to allow for count=0 exitTYA ; copy block length low byte to ABEQ LAB_120A ; branch if length low byte=0; block is (X-1)*256+Y bytes, do the Y bytes firstSEC ; set carry for add + 1, two's complementEOR #$FF ; invert low byte for subtractADC Obendl ; add block end low byteSTA Obendl ; save corrected old block end low byteBCS LAB_11F3 ; branch if no underflowDEC Obendh ; else decrement block end high byteSEC ; set carry for add + 1, two's complementLAB_11F3TYA ; get MOD(block length/$100) byteEOR #$FF ; invert low byte for subtractADC Nbendl ; add destination end low byteSTA Nbendl ; save modified new block end low byteBCS LAB_1203 ; branch if no underflowDEC Nbendh ; else decrement block end high byteBCC LAB_1203 ; branch alwaysLAB_11FFLDA (Obendl),Y ; get byte from sourceSTA (Nbendl),Y ; copy byte to destinationLAB_1203DEY ; decrement indexBNE LAB_11FF ; loop until Y=0; now do Y=0 indexed byteLDA (Obendl),Y ; get byte from sourceSTA (Nbendl),Y ; save byte to destinationLAB_120ADEC Obendh ; decrement source pointer high byteDEC Nbendh ; decrement destination pointer high byteDEX ; decrement block countBNE LAB_1203 ; loop until count = $0RTS; check room on stack for A bytes; stack too deep? do OM errorLAB_1212STA TempB ; save result in temp byteTSX ; copy stackCPX TempB ; compare new "limit" with stackBCC LAB_OMER ; if stack < limit do "Out of memory" error then warm startRTS; check available memory, "Out of memory" error if no room; addr to check is in AY (low/high)LAB_121FCPY Sstorh ; compare bottom of string mem high byteBCC LAB_124B ; if less then exit (is ok)BNE LAB_1229 ; skip next test if greater (tested <); high byte was =, now do low byteCMP Sstorl ; compare with bottom of string mem low byteBCC LAB_124B ; if less then exit (is ok); addr is > string storage ptr (oops!)LAB_1229PHA ; push addr low byteLDX #$08 ; set index to save Adatal to expneg inclusiveTYA ; copy addr high byte (to push on stack); save misc numeric work areaLAB_122DPHA ; push byteLDA Adatal-1,X ; get byte from Adatal to expneg ( ,$00 not pushed)DEX ; decrement indexBPL LAB_122D ; loop until all doneJSR LAB_GARB ; garbage collection routine; restore misc numeric work areaLDX #$00 ; clear the index to restore bytesLAB_1238PLA ; pop byteSTA Adatal,X ; save byte to Adatal to expnegINX ; increment indexCPX #$08 ; compare with end + 1BMI LAB_1238 ; loop if more to doPLA ; pop addr high byteTAY ; copy back to YPLA ; pop addr low byteCPY Sstorh ; compare bottom of string mem high byteBCC 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 byteCMP Sstorl ; compare with bottom of string mem low byteBCS LAB_OMER ; if >= do "Out of memory" error then warm start; ok exit, carry clearLAB_124BRTS; do "Out of memory" error then warm startLAB_OMERLDX #$0C ; error code $0C ("Out of memory" error); do error #X, then warm startLAB_XERRJSR LAB_CRLF ; print CR/LFLDA LAB_BAER,X ; get error message pointer low byteLDY LAB_BAER+1,X ; get error message pointer high byteJSR LAB_18C3 ; print null terminated string from memoryJSR LAB_1491 ; flush stack and clear continue flagLDA #<LAB_EMSG ; point to " Error" low addrLDY #>LAB_EMSG ; point to " Error" high addrLAB_1269JSR LAB_18C3 ; print null terminated string from memoryLDY Clineh ; get current line high byteINY ; increment itBEQ LAB_1274 ; go do warm start (was immediate mode); else print line numberJSR LAB_2953 ; print " in line [LINE #]"; BASIC warm start entry point; wait for Basic commandLAB_1274; clear ON IRQ/NMI bytesLDA #$00 ; clear ASTA IrqBase ; clear enabled byteSTA NmiBase ; clear enabled byteLDA #<LAB_RMSG ; point to "Ready" message low byteLDY #>LAB_RMSG ; point to "Ready" message high byteJSR LAB_18C3 ; go do print string; wait for Basic command (no "Ready")LAB_127DJSR LAB_1357 ; call for BASIC inputLAB_1280STX Bpntrl ; set BASIC execute pointer low byteSTY Bpntrh ; set BASIC execute pointer high byteJSR LAB_GBYT ; scan memoryBEQ LAB_127D ; loop while null; got to interpret input line now ..LDX #$FF ; current line to null valueSTX Clineh ; set current line high byteBCC LAB_1295 ; branch if numeric character (handle new BASIC line); no line number .. immediate modeJSR LAB_13A6 ; crunch keywords into Basic tokensJMP LAB_15F6 ; go scan and interpret code; handle new BASIC lineLAB_1295JSR LAB_GFPN ; get fixed-point number into temp integerJSR LAB_13A6 ; crunch keywords into Basic tokensSTY Ibptr ; save index pointer to end of crunched lineJSR LAB_SSLN ; search BASIC for temp integer line numberBCC LAB_12E6 ; branch if not found; aroooogah! line # already exists! delete itLDY #$01 ; set index to next line pointer high byteLDA (Baslnl),Y ; get next line pointer high byteSTA ut1_ph ; save itLDA Svarl ; get start of vars low byteSTA ut1_pl ; save itLDA Baslnh ; get found line pointer high byteSTA ut2_ph ; save itLDA Baslnl ; get found line pointer low byteDEY ; decrement indexSBC (Baslnl),Y ; subtract next line pointer low byteCLC ; clear carry for addADC Svarl ; add start of vars low byteSTA Svarl ; save new start of vars low byteSTA ut2_pl ; save destination pointer low byteLDA Svarh ; get start of vars high byteADC #$FF ; -1 + carrySTA Svarh ; save start of vars high byteSBC Baslnh ; subtract found line pointer high byteTAX ; copy to block countSEC ; set carry for subtractLDA Baslnl ; get found line pointer low byteSBC Svarl ; subtract start of vars low byteTAY ; copy to bytes in first block countBCS LAB_12D0 ; branch if overflowINX ; increment block count (correct for =0 loop exit)DEC ut2_ph ; decrement destination high byteLAB_12D0CLC ; clear carry for addADC ut1_pl ; add source pointer low byteBCC LAB_12D8 ; branch if no overflowDEC ut1_ph ; else decrement source pointer high byteCLC ; clear carry; close up memory to delete old lineLAB_12D8LDA (ut1_pl),Y ; get byte from sourceSTA (ut2_pl),Y ; copy to destinationINY ; increment indexBNE LAB_12D8 ; while <> 0 do this blockINC ut1_ph ; increment source pointer high byteINC ut2_ph ; increment destination pointer high byteDEX ; decrement block countBNE LAB_12D8 ; loop until all done; got new line in buffer and no existing same #LAB_12E6LDA Ibuffs ; get byte from start of input bufferBEQ LAB_1319 ; if null line just go flush stack/vars and exit; got new line and it isn't empty lineLDA Ememl ; get end of mem low byteLDY Ememh ; get end of mem high byteSTA Sstorl ; set bottom of string space low byteSTY Sstorh ; set bottom of string space high byteLDA Svarl ; get start of vars low byte (end of BASIC)STA Obendl ; save old block end low byteLDY Svarh ; get start of vars high byte (end of BASIC)STY Obendh ; save old block end high byteADC Ibptr ; add input buffer pointer (also buffer length)BCC LAB_1301 ; branch if no overflow from addINY ; else increment high byteLAB_1301STA Nbendl ; save new block end low byte (move to, low byte)STY Nbendh ; save new block end high byteJSR LAB_11CF ; open up space in memory; old start pointer Ostrtl,Ostrth set by the find line callLDA Earryl ; get array mem end low byteLDY Earryh ; get array mem end high byteSTA Svarl ; save start of vars low byteSTY Svarh ; save start of vars high byteLDY Ibptr ; get input buffer pointer (also buffer length)DEY ; adjust for loop typeLAB_1311LDA Ibuffs-4,Y ; get byte from crunched lineSTA (Baslnl),Y ; save it to program memoryDEY ; decrement countCPY #$03 ; compare with first byte-1BNE LAB_1311 ; continue while count <> 3LDA Itemph ; get line # high byteSTA (Baslnl),Y ; save it to program memoryDEY ; decrement countLDA Itempl ; get line # low byteSTA (Baslnl),Y ; save it to program memoryDEY ; decrement countLDA #$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 memoryLAB_1319JSR LAB_1477 ; reset execution to start, clear vars and flush stackLDX Smeml ; get start of mem low byteLDA Smemh ; get start of mem high byteLDY #$01 ; index to high byte of next line pointerLAB_1325STX ut1_pl ; set line start pointer low byteSTA ut1_ph ; set line start pointer high byteLDA (ut1_pl),Y ; get itBEQ LAB_133E ; exit if end of program; rebuild chaining of Basic linesLDY #$04 ; point to first code byte of line; there is always 1 byte + [EOL] as null entries are deletedLAB_1330INY ; next code byteLDA (ut1_pl),Y ; get byteBNE LAB_1330 ; loop if not [EOL]SEC ; set carry for add + 1TYA ; copy end indexADC ut1_pl ; add to line start pointer low byteTAX ; copy to XLDY #$00 ; clear index, point to this line's next line pointerSTA (ut1_pl),Y ; set next line pointer low byteTYA ; clear AADC ut1_ph ; add line start pointer high byte + carryINY ; increment index to high byteSTA (ut1_pl),Y ; save next line pointer low byteBCC LAB_1325 ; go do next line, branch always, carry clearLAB_133EJMP LAB_127D ; else we just wait for Basic command, no "Ready"; print "? " and get BASIC inputLAB_INLNJSR LAB_18E3 ; print "?" characterJSR 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_134BJSR LAB_PRNA ; go print the characterDEX ; decrement the buffer counter (delete).byte $2C ; make LDX into BIT abs; call for BASIC input (main entry point)LAB_1357LDX #$00 ; clear BASIC line buffer pointerLAB_1359JSR V_INPT ; call scan input deviceBCC LAB_1359 ; loop if no byteBEQ 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 $00BNE LAB_1374 ; branch if not empty; next two lines ignore any non print character and [SPACE] if input buffer emptyCMP #$21 ; compare with [SP]+1BCC LAB_1359 ; if < ignore characterLAB_1374CMP #$08 ; compare with [BACKSPACE] (delete last character)BEQ LAB_134B ; go delete last characterLAB_1378CPX #Ibuffe-Ibuffs ; compare character count with maxBCS LAB_138E ; skip store and do [BELL] if buffer fullSTA Ibuffs,X ; else store in bufferINX ; increment pointerLAB_137FJSR LAB_PRNA ; go print the characterBNE LAB_1359 ; always loop for next characterLAB_1384JMP LAB_1866 ; do CR/LF exit to BASICmessage "LAB_138E"; announce buffer fullLAB_138ELDA #$07 ; [BELL] character into ABNE 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_13A6LDY #$FF ; set save index (makes for easy math later)SEC ; set carry for subtractLDA Bpntrl ; get basic execute pointer low byteSBC #<Ibuffs ; subtract input buffer start pointerTAX ; copy result to X (index past line # if any)STX Oquote ; clear open quote/DATA flagLAB_13ACLDA Ibuffs,X ; get byte from input bufferBEQ LAB_13EC ; if null save byte then exitCMP #'_' ; compare with "_"BCS LAB_13EC ; if >= go save byte then continue crunchingCMP #'<' ; compare with "<"BCS LAB_13CC ; if >= go crunch nowCMP #'0' ; compare with "0"BCS LAB_13EC ; if >= go save byte then continue crunchingSTA Scnquo ; save buffer byte as search characterCMP #$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 nowLAB_13CCBIT Oquote ; get open quote/DATA token flagBVS LAB_13EC ; branch if b6 of Oquote set (was DATA); go save byte then continue crunchingSTX TempB ; save buffer read indexSTY csidx ; copy buffer save indexLDY #<TAB_1STC ; get keyword first character table low addressSTY ut2_pl ; save pointer low byteLDY #>TAB_1STC ; get keyword first character table high addressSTY ut2_ph ; save pointer high byteLDY #$00 ; clear table pointerLAB_13D0CMP (ut2_pl),Y ; compare with keyword first character table byteBEQ LAB_13D1 ; go do word_table_chr if matchBCC LAB_13EA ; if < keyword first character table byte go restore; Y and save to crunchedINY ; else increment pointerBNE LAB_13D0 ; and loop (branch always); have matched first character of some keywordLAB_13D1TYA ; copy matching indexASL ; *2 (bytes per pointer)TAX ; copy to new indexLDA TAB_CHRT,X ; get keyword table pointer low byteSTA ut2_pl ; save pointer low byteLDA TAB_CHRT+1,X ; get keyword table pointer high byteSTA ut2_ph ; save pointer high byteLDY #$FF ; clear table pointer (make -1 for start)LDX TempB ; restore buffer read indexLAB_13D6INY ; next table byteLDA (ut2_pl),Y ; get byte from tableLAB_13D8BMI LAB_13EA ; all bytes matched so go save tokenINX ; next buffer byteCMP Ibuffs,X ; compare with byte from input bufferBEQ LAB_13D6 ; go compare next if matchBNE LAB_1417 ; branch if >< (not found keyword)LAB_13EALDY csidx ; restore save index; save crunched to outputLAB_13ECINX ; increment buffer index (to next input byte)INY ; increment save index (to next output byte)STA Ibuffs,Y ; save byte to outputCMP #$00 ; set the flags, set carryBEQ LAB_142A ; do exit if was null [EOL]; A holds token or byte hereSBC #':' ; subtract ":" (carry set by CMP #00)BEQ LAB_13FF ; branch if it was ":" (is now $00); A now holds token-$3ACMP #TK_DATA-$3A ; compare with DATA token - $3ABNE LAB_1401 ; branch if not DATA; token was : or DATALAB_13FFSTA Oquote ; save token-$3A (clear for ":", TK_DATA-$3A for DATA)LAB_1401EOR #TK_REM-$3A ; effectively subtract REM token offsetBNE LAB_13AC ; If wasn't REM then go crunch rest of lineSTA Asrch ; else was REM so set search for [EOL]; loop for REM, "..." etc.LAB_1408LDA Ibuffs,X ; get byte from input bufferBEQ LAB_13EC ; branch if null [EOL]CMP Asrch ; compare with stored characterBEQ LAB_13EC ; branch if match (end quote); entry for copy string in quotes, don't crunchLAB_1410INY ; increment buffer save indexSTA Ibuffs,Y ; save byte to outputINX ; increment buffer read indexBNE LAB_1408 ; loop while <> 0 (should never be 0!); not found keyword this goLAB_1417LDX TempB ; compare has failed, restore buffer index (start byte!); now find the end of this word in the tableLAB_141BLDA (ut2_pl),Y ; get table bytePHP ; save statusINY ; increment table indexPLP ; restore byte statusBPL LAB_141B ; if not end of keyword go do nextLDA (ut2_pl),Y ; get byte from keyword tableBNE LAB_13D8 ; go test next word if not zero byte (end of table); reached end of table with no matchLDA Ibuffs,X ; restore byte from input bufferBPL LAB_13EA ; branch always (all bytes in buffer are $00-$7F); go save byte in output and continue crunching; reached [EOL]LAB_142AINY ; increment pointerINY ; increment pointer (makes it next line pointer high byte)STA Ibuffs,Y ; save [EOL] (marks [EOT] in immediate mode)INY ; adjust for line copyINY ; adjust for line copyINY ; adjust for line copyDEC Bpntrl ; allow for increment (change if buffer starts at $xxFF)RTS; search Basic for temp integer line number from start of memLAB_SSLNLDA Smeml ; get start of mem low byteLDX 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 507LAB_SHLNLDY #$01 ; set indexSTA Baslnl ; save low byte as currentSTX Baslnh ; save high byte as currentLDA (Baslnl),Y ; get pointer high byte from addrBEQ LAB_145F ; pointer was zero so we're done, do 'not found' exitLDY #$03 ; set index to line # high byteLDA (Baslnl),Y ; get line # high byteDEY ; decrement index (point to low byte)CMP Itemph ; compare with temporary integer high byteBNE LAB_1455 ; if <> skip low byte checkLDA (Baslnl),Y ; get line # low byteCMP Itempl ; compare with temporary integer low byteLAB_1455BCS LAB_145E ; else if temp < this line, exit (passed line#)LAB_1456DEY ; decrement index to next line ptr high byteLDA (Baslnl),Y ; get next line pointer high byteTAX ; copy to XDEY ; decrement index to next line ptr low byteLDA (Baslnl),Y ; get next line pointer low byteBCC LAB_SHLN ; go search for line # in temp (Itempl/Itemph) from AX; (carry always clear)LAB_145EBEQ LAB_1460 ; exit if temp = found line #, carry is setLAB_145FCLC ; clear found flagLAB_1460RTS; perform NEWLAB_NEWBNE LAB_1460 ; exit if not end of statement (to do syntax error)LAB_1463LDA #$00 ; clear ATAY ; clear YSTA (Smeml),Y ; clear first line, next line pointer, low byteINY ; increment indexSTA (Smeml),Y ; clear first line, next line pointer, high byteCLC ; clear carryLDA Smeml ; get start of mem low byteADC #$02 ; calculate end of BASIC low byteSTA Svarl ; save start of vars low byteLDA Smemh ; get start of mem high byteADC #$00 ; add any carrySTA Svarh ; save start of vars high byte; reset execution to start, clear vars and flush stackLAB_1477CLC ; clear carryLDA Smeml ; get start of mem low byteADC #$FF ; -1STA Bpntrl ; save BASIC execute pointer low byteLDA Smemh ; get start of mem high byteADC #$FF ; -1+carrySTA Bpntrh ; save BASIC execute pointer high byte; "CLEAR" command gets hereLAB_147ALDA Ememl ; get end of mem low byteLDY Ememh ; get end of mem high byteSTA Sstorl ; set bottom of string space low byteSTY Sstorh ; set bottom of string space high byteLDA Svarl ; get start of vars low byteLDY Svarh ; get start of vars high byteSTA Sarryl ; save var mem end low byteSTY Sarryh ; save var mem end high byteSTA Earryl ; save array mem end low byteSTY Earryh ; save array mem end high byteJSR LAB_161A ; perform RESTORE command; flush stack and clear continue flagLAB_1491LDX #des_sk ; set descriptor stack pointerSTX next_s ; save descriptor stack pointerPLA ; pull return address low byteTAX ; copy return address low bytePLA ; pull return address high byteSTX LAB_SKFE ; save to cleared stackSTA LAB_SKFF ; save to cleared stackLDX #$FD ; new stack pointerTXS ; reset stackLDA #$00 ; clear byteSTA Cpntrh ; clear continue pointer high byteSTA Sufnxf ; clear subscript/FNX flagLAB_14A6RTS; perform CLEARLAB_CLEARBEQ 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_LISTBCC 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 endLAB_14BDJSR LAB_GFPN ; get fixed-point number into temp integerJSR LAB_SSLN ; search BASIC for temp integer line number; (pointer in Baslnl/Baslnh)JSR LAB_GBYT ; scan memoryBEQ LAB_14D4 ; branch if no more characters; this bit checks the - is presentCMP #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 valueJSR LAB_IGBY ; increment and scan memoryJSR LAB_GFPN ; get fixed-point number into temp integerBNE LAB_1460 ; exit if not okLAB_14D4LDA Itempl ; get temporary integer low byteORA Itemph ; OR temporary integer high byteBNE LAB_14E2 ; branch if start setLDA #$FF ; set for -1STA Itempl ; set temporary integer low byteSTA Itemph ; set temporary integer high byteLAB_14E2LDY #$01 ; set index for lineSTY Oquote ; clear open quote flagJSR LAB_CRLF ; print CR/LFLDA (Baslnl),Y ; get next line pointer high byte; pointer initially set by search at LAB_14BDBEQ LAB_152B ; if null all done so exitJSR LAB_1629 ; do CRTL-C check vectorINY ; increment index for lineLDA (Baslnl),Y ; get line # low byteTAX ; copy to XINY ; increment indexLDA (Baslnl),Y ; get line # high byteCMP Itemph ; compare with temporary integer high byteBNE LAB_14FF ; branch if no high byte matchCPX Itempl ; compare with temporary integer low byteBEQ LAB_1501 ; branch if = last line to do (< will pass next branch)LAB_14FF ; else ..BCS LAB_152B ; if greater all done so exitLAB_1501STY Tidx1 ; save index for lineJSR LAB_295E ; print XA as unsigned integerLDA #$20 ; space is the next characterLAB_1508LDY Tidx1 ; get index for lineAND #$7F ; mask top out bit of characterLAB_150CJSR LAB_PRNA ; go print the characterCMP #$22 ; was it " characterBNE LAB_1519 ; branch if not; we are either entering or leaving a pair of quotesLDA Oquote ; get open quote flagEOR #$FF ; toggle itSTA Oquote ; save it backLAB_1519INY ; increment indexLDA (Baslnl),Y ; get next byteBNE LAB_152E ; branch if not [EOL] (go print character)TAY ; else clear indexLDA (Baslnl),Y ; get next line pointer low byteTAX ; copy to XINY ; increment indexLDA (Baslnl),Y ; get next line pointer high byteSTX Baslnl ; set pointer to line low byteSTA Baslnh ; set pointer to line high byteBNE LAB_14E2 ; go do next line if not [EOT]; else ..LAB_152BRTSLAB_152EBPL LAB_150C ; just go print it if not token byte; else was token byte so uncrunch it (maybe)BIT Oquote ; test the open quote flagBMI LAB_150C ; just go print character if open quote setLDX #>LAB_KEYT ; get table address high byteASL ; *2ASL ; *4BCC LAB_152F ; branch if no carryINX ; else increment high byteCLC ; clear carry for addLAB_152FADC #<LAB_KEYT ; add low byteBCC LAB_1530 ; branch if no carryINX ; else increment high byteLAB_1530STA ut2_pl ; save table pointer low byteSTX ut2_ph ; save table pointer high byteSTY Tidx1 ; save index for lineLDY #$00 ; clear indexLDA (ut2_pl),Y ; get lengthTAX ; copy lengthINY ; increment indexLDA (ut2_pl),Y ; get 1st characterDEX ; decrement lengthBEQ LAB_1508 ; if no more characters exit and printJSR LAB_PRNA ; go print the characterINY ; increment indexLDA (ut2_pl),Y ; get keyword address low bytePHA ; save it for nowINY ; increment indexLDA (ut2_pl),Y ; get keyword address high byteLDY #$00STA ut2_ph ; save keyword pointer high bytePLA ; pull low byteSTA ut2_pl ; save keyword pointer low byteLAB_1540LDA (ut2_pl),Y ; get characterDEX ; decrement character countBEQ LAB_1508 ; if last character exit and printJSR LAB_PRNA ; go print the characterINY ; increment indexBNE LAB_1540 ; loop for next character; perform FORLAB_FORLDA #$80 ; set FNXSTA Sufnxf ; set subscript/FNX flagJSR LAB_LET ; go do LETPLA ; pull return addressPLA ; pull return addressLDA #$10 ; we need 16d bytes !JSR LAB_1212 ; check room on stack for A bytesJSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL])CLC ; clear carry for addTYA ; copy index to AADC Bpntrl ; add BASIC execute pointer low bytePHA ; push onto stackLDA Bpntrh ; get BASIC execute pointer high byteADC #$00 ; add carryPHA ; push onto stackLDA Clineh ; get current line high bytePHA ; push onto stackLDA Clinel ; get current line low bytePHA ; push onto stackLDA #TK_TO ; get "TO" tokenJSR LAB_SCCA ; scan for CHR$(A) , else do syntax error then warm startJSR LAB_CTNM ; check if source is numeric, else do type mismatchJSR LAB_EVNM ; evaluate expression and check is numeric,; else do type mismatchLDA FAC1_s ; get FAC1 sign (b7)ORA #$7F ; set all non sign bitsAND FAC1_1 ; and FAC1 mantissa1STA FAC1_1 ; save FAC1 mantissa1LDA #<LAB_159F ; set return address low byteLDY #>LAB_159F ; set return address high byteSTA ut1_pl ; save return address low byteSTY ut1_ph ; save return address high byteJMP LAB_1B66 ; round FAC1 and put on stack (returns to next instruction)LAB_159FLDA #<LAB_259C ; set 1 pointer low addr (default step size)LDY #>LAB_259C ; set 1 pointer high addrJSR LAB_UFAC ; unpack memory (AY) into FAC1JSR LAB_GBYT ; scan memoryCMP #TK_STEP ; compare with STEP tokenBNE LAB_15B3 ; jump if not "STEP";.was step so ..JSR LAB_IGBY ; increment and scan memoryJSR LAB_EVNM ; evaluate expression and check is numeric,; else do type mismatchLAB_15B3JSR LAB_27CA ; return A=FF,C=1/-ve A=01,C=0/+veSTA 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 doneJSR LAB_1B5B ; push sign, round FAC1 and put on stackLDA Frnxth ; get var pointer for FOR/NEXT high bytePHA ; push on stackLDA Frnxtl ; get var pointer for FOR/NEXT low bytePHA ; push on stackLDA #TK_FOR ; get FOR tokenPHA ; push on stack; interpreter inner loopmessage "LAB_15C2"LAB_15C2JSR LAB_1629 ; do CRTL-C check vectorLDA Bpntrl ; get BASIC execute pointer low byteLDY Bpntrh ; get BASIC execute pointer high byteLDX 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 byteSTY Cpntrh ; save continue pointer high byteLAB_15D1LDY #$00 ; clear indexLDA (Bpntrl),Y ; get next byteBEQ LAB_15DC ; branch if null [EOL]CMP #':' ; compare with ":"BEQ LAB_15F6 ; branch if = (statement separator)LAB_15D9JMP LAB_SNER ; else syntax error then warm start; have reached [EOL]LAB_15DCLDY #$02 ; set indexLDA (Bpntrl),Y ; get next line pointer high byteCLC ; clear carry for no "BREAK" messageBEQ LAB_1651 ; if null go to immediate mode (was immediate or [EOT]; marker)INY ; increment indexLDA (Bpntrl),Y ; get line # low byteSTA Clinel ; save current line low byteINY ; increment indexLDA (Bpntrl),Y ; get line # high byteSTA Clineh ; save current line high byteTYA ; A now = 4ADC Bpntrl ; add BASIC execute pointer low byteSTA Bpntrl ; save BASIC execute pointer low byteBCC LAB_15F6 ; branch if no overflowINC Bpntrh ; else increment BASIC execute pointer high byteLAB_15F6JSR LAB_IGBY ; increment and scan memoryLAB_15F9JSR LAB_15FF ; go interpret BASIC code from (Bpntrl)LAB_15FCJMP LAB_15C2 ; loop; interpret BASIC code from (Bpntrl)LAB_15FFBEQ LAB_1628 ; exit if zero [EOL]LAB_1602ASL ; *2 bytes per vector and normalise tokenBCS LAB_1609 ; branch if was tokenJMP LAB_LET ; else go do implied LETmessage "LAB_1609"LAB_1609CMP #[TK_TAB-$80]*2 ; compare normalised token * 2 with TABBCS LAB_15D9 ; branch if A>=TAB (do syntax error then warm start); only tokens before TAB can start a lineTAY ; copy to indexLDA LAB_CTBL+1,Y ; get vector high bytePHA ; onto stackLDA LAB_CTBL,Y ; get vector low bytePHA ; onto stackJMP 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.message "LAB_1629"LAB_1629JMP (VEC_CC) ; ctrl c check vector; if there was a key press it gets back here ..LAB_1636CMP #$03 ; compare with CTRL-C; perform STOPLAB_STOPBCS LAB_163B ; branch if token follows STOP; else just END; ENDLAB_ENDCLC ; clear the carry, indicate a normal program endLAB_163BBNE LAB_167A ; if wasn't CTRL-C or there is a following byte returnLDA Bpntrh ; get the BASIC execute pointer high byteEOR #>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 bitsLDY Bpntrl ; get BASIC execute pointer low byteSTY Cpntrl ; save continue pointer low byteSTA Cpntrh ; save continue pointer high byteLAB_1647LDA Clinel ; get current line low byteLDY Clineh ; get current line high byteSTA Blinel ; save break line low byteSTY Blineh ; save break line high byteLAB_164FPLA ; pull return address lowPLA ; pull return address highLAB_1651BCC LAB_165E ; if was program end just do warm start; else ..LDA #<LAB_BMSG ; point to "Break" low byteLDY #>LAB_BMSG ; point to "Break" high byteJMP LAB_1269 ; print "Break" and do warm startLAB_165EJMP LAB_1274 ; go do warm start; perform RESTORELAB_RESTOREBNE LAB_RESTOREn ; branch if next character not null (RESTORE n)LAB_161ASEC ; set carry for subtractLDA Smeml ; get start of mem low byteSBC #$01 ; -1LDY Smemh ; get start of mem high byteBCS LAB_1624 ; branch if no underflowLAB_uflowDEY ; else decrement high byteLAB_1624STA Dptrl ; save DATA pointer low byteSTY Dptrh ; save DATA pointer high byteLAB_1628RTS; is RESTORE nLAB_RESTOREnJSR LAB_GFPN ; get fixed-point number into temp integerJSR LAB_SNBL ; scan for next BASIC lineLDA Clineh ; get current line high byteCMP Itemph ; compare with temporary integer high byteBCS LAB_reset_search ; branch if >= (start search from beginning)TYA ; else copy line index to ASEC ; set carry (+1)ADC Bpntrl ; add BASIC execute pointer low byteLDX Bpntrh ; get BASIC execute pointer high byteBCC LAB_go_search ; branch if no overflow to high byteINX ; increment high byteBCS 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_searchLDA Smeml ; get start of mem low byteLDX Smemh ; get start of mem high byte; search for line # in temp (Itempl/Itemph) from (AX)LAB_go_searchJSR LAB_SHLN ; search Basic for temp integer line number from AXBCS LAB_line_found ; if carry set go set pointerJMP LAB_16F7 ; else go do "Undefined statement" errorLAB_line_found; carry already set for subtractLDA Baslnl ; get pointer low byteSBC #$01 ; -1LDY Baslnh ; get pointer high byteBCS 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 NULLLAB_NULLJSR LAB_GTBY ; get byte parameterSTX Nullct ; save new NULL countLAB_167ARTS; perform CONTmessage "LAB_CONT"LAB_CONTBNE LAB_167A ; if following byte exit to do syntax errorLDY Cpntrh ; get continue pointer high byteBNE LAB_166C ; go do continue if we canLDX #$1E ; error code $1E ("Can't continue" error)JMP LAB_XERR ; do error #X, then warm start; we can continue so ..LAB_166CLDA #TK_ON ; set token for ONJSR LAB_IRQ ; set IRQ flagsLDA #TK_ON ; set token for ONJSR LAB_NMI ; set NMI flagsSTY Bpntrh ; save BASIC execute pointer high byteLDA Cpntrl ; get continue pointer low byteSTA Bpntrl ; save BASIC execute pointer low byteLDA Blinel ; get break line low byteLDY Blineh ; get break line high byteSTA Clinel ; set current line low byteSTY Clineh ; set current line high byteRTS; perform RUNLAB_RUNBNE LAB_1696 ; branch if RUN nJMP LAB_1477 ; reset execution to start, clear variables, flush stack and; return; does RUN nLAB_1696JSR LAB_147A ; go do "CLEAR"BEQ LAB_16B0 ; get n and do GOTO n (branch always as CLEAR sets Z=1); perform DOLAB_DOLDA #$05 ; need 5 bytes for DOJSR LAB_1212 ; check room on stack for A bytesLDA Bpntrh ; get BASIC execute pointer high bytePHA ; push on stackLDA Bpntrl ; get BASIC execute pointer low bytePHA ; push on stackLDA Clineh ; get current line high bytePHA ; push on stackLDA Clinel ; get current line low bytePHA ; push on stackLDA #TK_DO ; token for DOPHA ; push on stackJSR LAB_GBYT ; scan memoryJMP LAB_15C2 ; go do interpreter inner loop; perform GOSUBLAB_GOSUBLDA #$05 ; need 5 bytes for GOSUBJSR LAB_1212 ; check room on stack for A bytesLDA Bpntrh ; get BASIC execute pointer high bytePHA ; push on stackLDA Bpntrl ; get BASIC execute pointer low bytePHA ; push on stackLDA Clineh ; get current line high bytePHA ; push on stackLDA Clinel ; get current line low bytePHA ; push on stackLDA #TK_GOSUB ; token for GOSUBPHA ; push on stackLAB_16B0JSR LAB_GBYT ; scan memoryJSR LAB_GOTO ; perform GOTO nJMP LAB_15C2 ; go do interpreter inner loop; (can't RTS, we used the stack!); perform GOTOLAB_GOTOJSR LAB_GFPN ; get fixed-point number into temp integerJSR LAB_SNBL ; scan for next BASIC lineLDA Clineh ; get current line high byteCMP Itemph ; compare with temporary integer high byteBCS LAB_16D0 ; branch if >= (start search from beginning)TYA ; else copy line index to ASEC ; set carry (+1)ADC Bpntrl ; add BASIC execute pointer low byteLDX Bpntrh ; get BASIC execute pointer high byteBCC LAB_16D4 ; branch if no overflow to high byteINX ; increment high byteBCS LAB_16D4 ; branch always (can never be carry); search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml)LAB_16D0LDA Smeml ; get start of mem low byteLDX Smemh ; get start of mem high byte; search for line # in temp (Itempl/Itemph) from (AX)LAB_16D4JSR LAB_SHLN ; search Basic for temp integer line number from AXBCC LAB_16F7 ; if carry clear go do "Undefined statement" error; (unspecified statement); carry already set for subtractLDA Baslnl ; get pointer low byteSBC #$01 ; -1STA Bpntrl ; save BASIC execute pointer low byteLDA Baslnh ; get pointer high byteSBC #$00 ; subtract carrySTA Bpntrh ; save BASIC execute pointer high byteLAB_16E5RTSLAB_DONOKLDX #$22 ; error code $22 ("LOOP without DO" error)JMP LAB_XERR ; do error #X, then warm start; perform LOOPLAB_LOOPTAY ; save following tokenTSX ; copy stack pointerLDA LAB_STAK+3,X ; get token byte from stackCMP #TK_DO ; compare with DO tokenBNE LAB_DONOK ; branch if no matching DOINX ; dump calling routine return addressINX ; dump calling routine return addressTXS ; correct stackTYA ; get saved following token backBEQ LoopAlways ; if no following token loop forever; (stack pointer in X)CMP #':' ; could be ':'BEQ LoopAlways ; if :... loop foreverSBC #TK_UNTIL ; subtract token for UNTIL, we know carry is set hereTAX ; copy to X (if it was UNTIL then Y will be correct)BEQ DoRest ; branch if was UNTILDEX ; decrement resultBNE LAB_16FC ; if not WHILE go do syntax error and warm start; only if the token was WHILE will this failDEX ; set invert result byteDoRestSTX Frnxth ; save invert result byteJSR LAB_IGBY ; increment and scan memoryJSR LAB_EVEX ; evaluate expressionLDA FAC1_e ; get FAC1 exponentBEQ DoCmp ; if =0 go do straight compareLDA #$FF ; else set all bitsDoCmpTSX ; copy stack pointerEOR Frnxth ; EOR with invert byteBNE LoopDone ; if <> 0 clear stack and back to interpreter loop; loop condition wasn't met so do it againLoopAlwaysLDA LAB_STAK+2,X ; get current line low byteSTA Clinel ; save current line low byteLDA LAB_STAK+3,X ; get current line high byteSTA Clineh ; save current line high byteLDA LAB_STAK+4,X ; get BASIC execute pointer low byteSTA Bpntrl ; save BASIC execute pointer low byteLDA LAB_STAK+5,X ; get BASIC execute pointer high byteSTA Bpntrh ; save BASIC execute pointer high byteJSR LAB_GBYT ; scan memoryJMP LAB_15C2 ; go do interpreter inner loop; clear stack and back to interpreter loopLoopDoneINX ; dump DO tokenINX ; dump current line low byteINX ; dump current line high byteINX ; dump BASIC execute pointer low byteINX ; dump BASIC execute pointer high byteTXS ; correct stackJMP LAB_DATA ; go perform DATA (find : or [EOL]); do the return without gosub errorLAB_16F4LDX #$04 ; error code $04 ("RETURN without GOSUB" error).byte $2C ; makes next line BIT LAB_0EA2LAB_16F7 ; do undefined statement errorLDX #$0E ; error code $0E ("Undefined statement" error)JMP LAB_XERR ; do error #X, then warm start; perform RETURNLAB_RETURNBNE LAB_16E5 ; exit if following token (to allow syntax error)LAB_16E8PLA ; dump calling routine return addressPLA ; dump calling routine return addressPLA ; pull tokenCMP #TK_GOSUB ; compare with GOSUB tokenBNE LAB_16F4 ; branch if no matching GOSUBLAB_16FFPLA ; pull current line low byteSTA Clinel ; save current line low bytePLA ; pull current line high byteSTA Clineh ; save current line high bytePLA ; pull BASIC execute pointer low byteSTA Bpntrl ; save BASIC execute pointer low bytePLA ; pull BASIC execute pointer high byteSTA 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 DATALAB_DATAJSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]); set BASIC execute pointerLAB_170FTYA ; copy index to ACLC ; clear carry for addADC Bpntrl ; add BASIC execute pointer low byteSTA Bpntrl ; save BASIC execute pointer low byteBCC LAB_1719 ; skip next if no carryINC Bpntrh ; else increment BASIC execute pointer high byteLAB_1719RTSLAB_16FCJMP LAB_SNER ; do syntax error then warm start; scan for next BASIC statement ([:] or [EOL]); returns Y as index to [:] or [EOL]LAB_SNBSLDX #':' ; set look for character = ":".byte $2C ; makes next line BIT $00A2; scan for next BASIC line; returns Y as index to [EOL]LAB_SNBLLDX #$00 ; set alt search character = [EOL]LDY #$00 ; set search character = [EOL]STY Asrch ; store search characterLAB_1725TXA ; get alt search characterEOR Asrch ; toggle search character, effectively swap with $00STA Asrch ; save swapped search characterLAB_172DLDA (Bpntrl),Y ; get next byteBEQ LAB_1719 ; exit if null [EOL]CMP Asrch ; compare with search characterBEQ LAB_1719 ; exit if foundINY ; increment indexCMP #$22 ; compare current character with open quoteBNE LAB_172D ; if not open quote go get next characterBEQ LAB_1725 ; if found go swap search character for alt search character; perform IFLAB_IFJSR LAB_EVEX ; evaluate the expressionJSR LAB_GBYT ; scan memoryCMP #TK_THEN ; compare with THEN tokenBEQ LAB_174B ; if it was THEN go do IF; wasn't IF .. THEN so must be IF .. GOTOCMP #TK_GOTO ; compare with GOTO tokenBNE LAB_16FC ; if it wasn't GOTO go do syntax errorLDX Bpntrl ; save the basic pointer low byteLDY Bpntrh ; save the basic pointer high byteJSR LAB_IGBY ; increment and scan memoryBCS LAB_16FC ; if not numeric go do syntax errorSTX Bpntrl ; restore the basic pointer low byteSTY Bpntrh ; restore the basic pointer high byteLAB_174BLDA FAC1_e ; get FAC1 exponentBEQ LAB_174E ; if the result was zero go look for an ELSEJSR LAB_IGBY ; else increment and scan memoryBCS LAB_174D ; if not numeric go do var or keywordLAB_174CJMP LAB_GOTO ; else was numeric so do GOTO nmessage "LAB_174D"; is var or keywordLAB_174DCMP #TK_RETURN ; compare the byte with the token for RETURNBNE LAB_174G ; if it wasn't RETURN go interpret BASIC code from (Bpntrl); and return to this code to process any following codeJMP LAB_1602 ; else it was RETURN so interpret BASIC code from (Bpntrl); but don't return hereLAB_174GJSR 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 presentLDY #$00 ; clear the indexLDA (Bpntrl),Y ; get the next BASIC byteCMP #TK_ELSE ; compare it with the token for ELSEBEQ 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 errorRTS ; else return to the interpreter inner loop; perform ELSE after IFLAB_174ELDY #$00 ; clear the BASIC byte indexLDX #$01 ; clear the nesting depthLAB_1750INY ; increment the BASIC byte indexLDA (Bpntrl),Y ; get the next BASIC byteBEQ LAB_1753 ; if EOL go add the pointer and returnCMP #TK_IF ; compare the byte with the token for IFBNE LAB_1752 ; if not IF token skip the depth incrementINX ; else increment the nesting depth ..BNE LAB_1750 ; .. and continue lookingLAB_1752CMP #TK_ELSE ; compare the byte with the token for ELSEBNE LAB_1750 ; if not ELSE token continue lookingDEX ; was ELSE so decrement the nesting depthBNE LAB_1750 ; loop if still nestedINY ; increment the BASIC byte index past the ELSE; found the matching ELSE, now do <{n|statement}>LAB_1753TYA ; else copy line index to ACLC ; clear carry for addADC Bpntrl ; add the BASIC execute pointer low byteSTA Bpntrl ; save the BASIC execute pointer low byteBCC LAB_1754 ; branch if no overflow to high byteINC Bpntrh ; else increment the BASIC execute pointer high byteLAB_1754JSR LAB_GBYT ; scan memoryBCC 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) lineLAB_REMJSR LAB_SNBL ; scan for next BASIC lineJMP LAB_170F ; go set BASIC execute pointer and return, branch alwaysLAB_16FDJMP LAB_SNER ; do syntax error then warm start; perform ONLAB_ONCMP #TK_IRQ ; was it IRQ token ?BNE LAB_NOIN ; if not go check NMIJMP LAB_SIRQ ; else go set-up IRQLAB_NOINCMP #TK_NMI ; was it NMI token ?BNE LAB_NONM ; if not go do normal ON commandJMP LAB_SNMI ; else go set-up NMILAB_NONMJSR LAB_GTBY ; get byte parameterPHA ; push GOTO/GOSUB tokenCMP #TK_GOSUB ; compare with GOSUB tokenBEQ LAB_176B ; branch if GOSUBCMP #TK_GOTO ; compare with GOTO tokenLAB_1767BNE LAB_16FD ; if not GOTO do syntax error then warm start; next character was GOTO or GOSUBLAB_176BDEC FAC1_3 ; decrement index (byte value)BNE LAB_1773 ; branch if not zeroPLA ; pull GOTO/GOSUB tokenJMP LAB_1602 ; go execute itLAB_1773JSR LAB_IGBY ; increment and scan memoryJSR 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_177EPLA ; else pull keyword token (run out of options); also dump +/-1 pointer low byte and exitLAB_177FRTS; takes n * 106 + 11 cycles where n is the number of digits; get fixed-point number into temp integerLAB_GFPNLDX #$00 ; clear regSTX Itempl ; clear temporary integer low byteLAB_1785STX Itemph ; save temporary integer high byteBCS LAB_177F ; return if carry set, end of scan, character was; not 0-9CPX #$19 ; compare high byte with $19TAY ; ensure Zb = 0 if the branch is takenBCS LAB_1767 ; branch if >=, makes max line # 63999 because next; bit does *$0A, = 64000, compare at target will fail; and do syntax errorSBC #'0'-1 ; subtract "0", $2F + carry, from byteTAY ; copy binary digitLDA Itempl ; get temporary integer low byteASL ; *2 low byteROL Itemph ; *2 high byteASL ; *2 low byteROL Itemph ; *2 high byte, *4ADC Itempl ; + low byte, *5STA Itempl ; save itTXA ; get high byte copy to AADC Itemph ; + high byte, *5ASL Itempl ; *2 low byte, *10dROL ; *2 high byte, *10dTAX ; copy high byte back to XTYA ; get binary digit backADC Itempl ; add number low byteSTA Itempl ; save number low byteBCC LAB_17B3 ; if no overflow to high byte get next characterINX ; else increment high byteLAB_17B3JSR LAB_IGBY ; increment and scan memoryJMP LAB_1785 ; loop for next character; perform DECLAB_DECLDA #<LAB_2AFD ; set -1 pointer low byte.byte $2C ; BIT abs to skip the LDA below; perform INCLAB_INCLDA #<LAB_259C ; set 1 pointer low byteLAB_17B5PHA ; save +/-1 pointer low byteLAB_17B7JSR LAB_GVAR ; get var addressLDX Dtypef ; get data type flag, $FF=string, $00=numericBMI IncrErr ; exit if stringSTA Lvarpl ; save var address low byteSTY Lvarph ; save var address high byteJSR LAB_UFAC ; unpack memory (AY) into FAC1PLA ; get +/-1 pointer low bytePHA ; save +/-1 pointer low byteLDY #>LAB_259C ; set +/-1 pointer high byte (both the same)JSR LAB_246C ; add (AY) to FAC1JSR LAB_PFAC ; pack FAC1 into variable (Lvarpl)JSR LAB_GBYT ; scan memoryCMP #',' ; compare with ","BNE LAB_177E ; exit if not "," (either end or error); was "," so another INCR variable to doJSR LAB_IGBY ; increment and scan memoryJMP LAB_17B7 ; go do next varIncrErrJMP LAB_1ABC ; do "Type mismatch" error then warm start; perform LETLAB_LETJSR LAB_GVAR ; get var addressSTA Lvarpl ; save var address low byteSTY Lvarph ; save var address high byteLDA #TK_EQUAL ; get = tokenJSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm startLDA Dtypef ; get data type flag, $FF=string, $00=numericPHA ; push data type flagJSR LAB_EVEX ; evaluate expressionPLA ; pop data type flagROL ; set carry if type = stringJSR LAB_CKTM ; type match check, set C for stringBNE LAB_17D5 ; branch if stringJMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return; string LETLAB_17D5LDY #$02 ; set index to pointer high byteLDA (des_pl),Y ; get string pointer high byteCMP Sstorh ; compare bottom of string space high byteBCC LAB_17F4 ; if less assign value and exit (was in program memory)BNE LAB_17E6 ; branch if >; else was equal so compare low bytesDEY ; decrement indexLDA (des_pl),Y ; get pointer low byteCMP Sstorl ; compare bottom of string space low byteBCC LAB_17F4 ; if less assign value and exit (was in program memory); pointer was >= to bottom of string space pointerLAB_17E6LDY des_ph ; get descriptor pointer high byteCPY Svarh ; compare start of vars high byteBCC 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 byteCMP Svarl ; compare start of vars low byteBCS LAB_17FB ; branch if >= (descriptor is not on stack)LAB_17F4LDA des_pl ; get descriptor pointer low byteLDY des_ph ; get descriptor pointer high byteJMP LAB_1811 ; clean stack, copy descriptor to variable and return; make space and copy stringLAB_17FBLDY #$00 ; index to lengthLDA (des_pl),Y ; get string lengthJSR LAB_209C ; copy stringLDA des_2l ; get descriptor pointer low byteLDY des_2h ; get descriptor pointer high byteSTA ssptr_l ; save descriptor pointer low byteSTY ssptr_h ; save descriptor pointer high byteJSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill)LDA #<FAC1_e ; set descriptor pointer low byteLDY #>FAC1_e ; get descriptor pointer high byte; clean stack and assign value to string variableLAB_1811STA des_2l ; save descriptor_2 pointer low byteSTY des_2h ; save descriptor_2 pointer high byteJSR LAB_22EB ; clean descriptor stack, YA = pointerLDY #$00 ; index to lengthLDA (des_2l),Y ; get string lengthSTA (Lvarpl),Y ; copy to let string variableINY ; index to string pointer low byteLDA (des_2l),Y ; get string pointer low byteSTA (Lvarpl),Y ; copy to let string variableINY ; index to string pointer high byteLDA (des_2l),Y ; get string pointer high byteSTA (Lvarpl),Y ; copy to let string variableRTS; perform GETLAB_GETJSR LAB_GVAR ; get var addressSTA Lvarpl ; save var address low byteSTY Lvarph ; save var address high byteJSR INGET ; get input byteLDX Dtypef ; get data type flag, $FF=string, $00=numericBMI LAB_GETS ; go get string character; was numeric getTAY ; copy character to YJSR LAB_1FD0 ; convert Y to byte in FAC1JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and returnLAB_GETSPHA ; save characterLDA #$01 ; string is single byteBCS LAB_IsByte ; branch if byte receivedPLA ; string is nullLAB_IsByteJSR LAB_MSSP ; make string space A bytes long A=$AC=length,; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byteBEQ LAB_NoSt ; skip store if null stringPLA ; get character backLDY #$00 ; clear indexSTA (str_pl),Y ; save byte in string (byte IS string!)LAB_NoStJSR LAB_RTST ; check for space on descriptor stack then put address; and length on descriptor stack and update stack pointersJMP LAB_17D5 ; do string LET and return; perform PRINTLAB_1829JSR LAB_18C6 ; print string from Sutill/SutilhLAB_182CJSR LAB_GBYT ; scan memoryLAB_PRINTBEQ LAB_CRLF ; if nothing following just print CR/LFLAB_1831CMP #TK_TAB ; compare with TAB( tokenBEQ LAB_18A2 ; go do TAB/SPCCMP #TK_SPC ; compare with SPC( tokenBEQ LAB_18A2 ; go do TAB/SPCCMP #',' ; compare with ","BEQ LAB_188B ; go do move to next TAB markCMP #';' ; compare with ";"BEQ LAB_18BD ; if ";" continue with PRINT processingJSR LAB_EVEX ; evaluate expressionBIT Dtypef ; test data type flag, $FF=string, $00=numericBMI LAB_1829 ; branch if stringJSR LAB_296E ; convert FAC1 to stringJSR LAB_20AE ; print " terminated string to Sutill/SutilhLDY #$00 ; clear index; don't check fit if terminal width byte is zeroLDA TWidth ; get terminal width byteBEQ LAB_185E ; skip check if zeroSEC ; set carry for subtractSBC TPos ; subtract terminal positionSBC (des_pl),Y ; subtract string lengthBCS LAB_185E ; branch if less than terminal widthJSR LAB_CRLF ; else print CR/LFLAB_185EJSR LAB_18C6 ; print string from Sutill/SutilhBEQ LAB_182C ; always go continue processing line; CR/LF return to BASIC from BASIC input handlerLAB_1866LDA #$00 ; clear byteSTA Ibuffs,X ; null terminate inputLDX #<Ibuffs ; set X to buffer start-1 low byteLDY #>Ibuffs ; set Y to buffer start-1 high byte; print CR/LFLAB_CRLFLDA #$0D ; load [CR]JSR LAB_PRNA ; go print the characterLDA #$0A ; load [LF]BNE LAB_PRNA ; go print the character and return, branch alwaysLAB_188BLDA TPos ; get terminal positionCMP Iclim ; compare with input column limitBCC LAB_1897 ; branch if lessJSR LAB_CRLF ; else print CR/LF (next line)BNE LAB_18BD ; continue with PRINT processing (branch always)LAB_1897SEC ; set carry for subtractLAB_1898SBC TabSiz ; subtract TAB sizeBCS LAB_1898 ; loop if result was +veEOR #$FF ; complement itADC #$01 ; +1 (twos complement)BNE LAB_18B6 ; always print A spaces (result is never $00); do TAB/SPCLAB_18A2PHA ; save tokenJSR LAB_SGBY ; scan and get byte parameterCMP #$29 ; is next character )BNE LAB_1910 ; if not do syntax error then warm startPLA ; get token backCMP #TK_TAB ; was it TAB ?BNE LAB_18B7 ; if not go do SPC; calculate TAB offsetTXA ; copy integer value to ASBC TPos ; subtract terminal positionBCC LAB_18BD ; branch if result was < 0 (can't TAB backwards); print A spacesLAB_18B6TAX ; copy result to XLAB_18B7TXA ; set flags on size for SPCBEQ LAB_18BD ; branch if result was = $0, already here; print X spacesLAB_18BAJSR LAB_18E0 ; print " "DEX ; decrement countBNE LAB_18BA ; loop if not all done; continue with PRINT processingLAB_18BDJSR LAB_IGBY ; increment and scan memoryBNE LAB_1831 ; if more to print go do itRTS; print null terminated string from memoryLAB_18C3JSR LAB_20AE ; print " terminated string to Sutill/Sutilh; print string from Sutill/SutilhLAB_18C6JSR 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 byteLDY #$00 ; reset indexTAX ; copy length to XBEQ LAB_188C ; exit (RTS) if null stringLAB_18CDLDA (ut1_pl),Y ; get next byteJSR LAB_PRNA ; go print the characterINY ; increment indexDEX ; decrement countBNE LAB_18CD ; loop if not done yetRTS; Print single format character; print " "LAB_18E0LDA #$20 ; load " ".byte $2C ; change next line to BIT LAB_3FA9; print "?" characterLAB_18E3LDA #$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=0LAB_PRNACMP #' ' ; compare with " "BCC LAB_18F9 ; branch if less (non printing); else printable characterPHA ; save the character; don't check fit if terminal width byte is zeroLDA TWidth ; get terminal widthBNE LAB_18F0 ; branch if not zero (not infinite length); is "infinite line" so check TAB positionLDA TPos ; get positionSBC TabSiz ; subtract TAB size, carry set by CMP #$20 aboveBNE LAB_18F7 ; skip reset if differentSTA TPos ; else reset positionBEQ LAB_18F7 ; go print characterLAB_18F0CMP TPos ; compare with terminal character positionBNE LAB_18F7 ; branch if not at end of lineJSR LAB_CRLF ; else print CR/LFLAB_18F7INC TPos ; increment terminal positionPLA ; get character backLAB_18F9JSR V_OUTP ; output byte via output vectorCMP #$0D ; compare with [CR]BNE LAB_188A ; branch if not [CR]; else print nullct nulls after the [CR]STX TempB ; save buffer indexLDX Nullct ; get null countBEQ LAB_1886 ; branch if no nullsLDA #$00 ; load [NULL]LAB_1880JSR LAB_PRNA ; go print the characterDEX ; decrement countBNE LAB_1880 ; loop if not all doneLDA #$0D ; restore the character (and set the flags)LAB_1886STX TPos ; clear terminal position (X always = zero when we get here)LDX TempB ; restore buffer indexLAB_188AAND #$FF ; set the flagsLAB_188CRTS; handle bad input dataLAB_1904LDA Imode ; get input mode flag, $00=INPUT, $00=READBPL LAB_1913 ; branch if INPUT (go do redo)LDA Dlinel ; get current DATA line low byteLDY Dlineh ; get current DATA line high byteSTA Clinel ; save current line low byteSTY Clineh ; save current line high byteLAB_1910JMP LAB_SNER ; do syntax error then warm start; mode was INPUTLAB_1913LDA #<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 memoryLDA Cpntrl ; get continue pointer low byteLDY Cpntrh ; get continue pointer high byteSTA Bpntrl ; save BASIC execute pointer low byteSTY Bpntrh ; save BASIC execute pointer high byteRTS; perform INPUTLAB_INPUTCMP #$22 ; compare next byte with open quoteBNE LAB_1934 ; branch if no prompt stringJSR LAB_1BC1 ; print "..." stringLDA #$3B ; load A with ";"JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm startJSR LAB_18C6 ; print string from Sutill/Sutilh; done with prompt, now get dataLAB_1934JSR LAB_CKRN ; check not Direct, back here if okJSR LAB_INLN ; print "? " and get BASIC inputLDA #$00 ; set mode = INPUTCMP Ibuffs ; test first byte in bufferBNE LAB_1953 ; branch if not null inputCLC ; was null input so clear carry to exit programJMP LAB_1647 ; go do BREAK exit; perform READLAB_READLDX Dptrl ; get DATA pointer low byteLDY Dptrh ; get DATA pointer high byteLDA #$80 ; set mode = READLAB_1953STA Imode ; set input mode flag, $00=INPUT, $80=READSTX Rdptrl ; save READ pointer low byteSTY Rdptrh ; save READ pointer high byte; READ or INPUT next variable from listLAB_195BJSR LAB_GVAR ; get (var) addressSTA Lvarpl ; save address low byteSTY Lvarph ; save address high byteLDA Bpntrl ; get BASIC execute pointer low byteLDY Bpntrh ; get BASIC execute pointer high byteSTA Itempl ; save as temporary integer low byteSTY Itemph ; save as temporary integer high byteLDX Rdptrl ; get READ pointer low byteLDY Rdptrh ; get READ pointer high byteSTX Bpntrl ; set BASIC execute pointer low byteSTY Bpntrh ; set BASIC execute pointer high byteJSR LAB_GBYT ; scan memoryBNE LAB_1988 ; branch if not null; pointer was to null entryBIT Imode ; test input mode flag, $00=INPUT, $80=READBMI LAB_19DD ; branch if READ; mode was INPUTJSR LAB_18E3 ; print "?" character (double ? for extended input)JSR LAB_INLN ; print "? " and get BASIC inputSTX Bpntrl ; set BASIC execute pointer low byteSTY Bpntrh ; set BASIC execute pointer high byteLAB_1985JSR LAB_GBYT ; scan memoryLAB_1988BIT Dtypef ; test data type flag, $FF=string, $00=numericBPL LAB_19B0 ; branch if numeric; else get stringSTA Srchc ; save search characterCMP #$22 ; was it " ?BEQ LAB_1999 ; branch if soLDA #':' ; else search character is ":"STA Srchc ; set new search characterLDA #',' ; other search character is ","CLC ; clear carry for addLAB_1999STA Asrch ; set second search characterLDA Bpntrl ; get BASIC execute pointer low byteLDY Bpntrh ; get BASIC execute pointer high byteADC #$00 ; c is =1 if we came via the BEQ LAB_1999, else =0BCC LAB_19A4 ; branch if no execute pointer low byte rolloverINY ; else increment high byteLAB_19A4JSR LAB_20B4 ; print Srchc or Asrch terminated string to Sutill/SutilhJSR LAB_23F3 ; restore BASIC execute pointer from temp (Btmpl/Btmph)JSR LAB_17D5 ; go do string LETJMP LAB_19B6 ; go check string terminator; get numeric INPUTLAB_19B0JSR LAB_2887 ; get FAC1 from stringJSR LAB_PFAC ; pack FAC1 into (Lvarpl)LAB_19B6JSR LAB_GBYT ; scan memoryBEQ 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 dataLAB_19C2JSR LAB_IGBY ; increment and scan memoryLAB_19C5LDA 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 nowSTY Rdptrh ; save for nowLDA 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 byteSTY Bpntrh ; set BASIC execute pointer high byteJSR LAB_GBYT ; scan memoryBEQ LAB_1A03 ; if null go do extra ignored messageJSR LAB_1C01 ; else scan for "," , else do syntax error then warm startJMP LAB_195B ; go INPUT next variable from list; find next DATA statement or do "Out of DATA" errorLAB_19DDJSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL])INY ; increment indexTAX ; copy character ([:] or [EOL])BNE LAB_19F6 ; branch if [:]LDX #$06 ; set for "Out of DATA" errorINY ; increment index, now points to next line pointer high byteLDA (Bpntrl),Y ; get next line pointer high byteBEQ LAB_1A54 ; branch if end (eventually does error X)INY ; increment indexLDA (Bpntrl),Y ; get next line # low byteSTA Dlinel ; save current DATA line low byteINY ; increment indexLDA (Bpntrl),Y ; get next line # high byteINY ; increment indexSTA Dlineh ; save current DATA line high byteLAB_19F6LDA (Bpntrl),Y ; get byteINY ; increment indexTAX ; copy to XJSR LAB_170F ; set BASIC execute pointerCPX #TK_DATA ; compare with "DATA" tokenBEQ LAB_1985 ; was "DATA" so go do next READBNE LAB_19DD ; go find next statement if not "DATA"; end of INPUT/READ routineLAB_1A03LDA Rdptrl ; get temp READ pointer low byteLDY Rdptrh ; get temp READ pointer high byteLDX Imode ; get input mode flag, $00=INPUT, $80=READBPL LAB_1A0E ; branch if INPUTJMP LAB_1624 ; save AY as DATA pointer and return; we were getting INPUTLAB_1A0ELDY #$00 ; clear indexLDA (Rdptrl),Y ; get next byteBNE LAB_1A1B ; error if not end of INPUTRTS; user typed too muchLAB_1A1BLDA #<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=0LAB_11A1TSX ; copy stack pointerINX ; +1 pass return addressINX ; +2 pass return addressINX ; +3 pass calling routine return addressINX ; +4 pass calling routine return addressLAB_11A6LDA LAB_STAK+1,X ; get token byte from stackCMP #TK_FOR ; is it FOR tokenBNE LAB_11CE ; exit if not FOR token; was FOR tokenLDA Frnxth ; get var pointer for FOR/NEXT high byteBNE LAB_11BB ; branch if not nullLDA LAB_STAK+2,X ; get FOR variable pointer low byteSTA Frnxtl ; save var pointer for FOR/NEXT low byteLDA LAB_STAK+3,X ; get FOR variable pointer high byteSTA Frnxth ; save var pointer for FOR/NEXT high byteLAB_11BBCMP LAB_STAK+3,X ; compare var pointer with stacked var pointer (high byte)BNE LAB_11C7 ; branch if no matchLDA Frnxtl ; get var pointer for FOR/NEXT low byteCMP LAB_STAK+2,X ; compare var pointer with stacked var pointer (low byte)BEQ LAB_11CE ; exit if match foundLAB_11C7TXA ; copy indexCLC ; clear carry for addADC #$10 ; add FOR stack use sizeTAX ; copy back to indexBNE LAB_11A6 ; loop if not at start of stackLAB_11CERTS; perform NEXTLAB_NEXTBNE LAB_1A46 ; branch if NEXT varLDY #$00 ; else clear YBEQ LAB_1A49 ; branch always (no variable to search for); NEXT varLAB_1A46JSR LAB_GVAR ; get variable addressLAB_1A49STA Frnxtl ; store variable pointer low byteSTY Frnxth ; store variable pointer high byte; (both cleared if no variable defined)JSR LAB_11A1 ; search the stack for FOR activityBEQ LAB_1A56 ; branch if foundLDX #$00 ; else set error $00 ("NEXT without FOR" error)LAB_1A54BEQ LAB_1ABE ; do error #X, then warm startLAB_1A56TXS ; set stack pointer, X set by search, dumps return addressesTXA ; copy stack pointerSEC ; set carry for subtractSBC #$F7 ; point to TO varSTA ut2_pl ; save pointer to TO var for compareADC #$FB ; point to STEP varLDY #>LAB_STAK ; point to stack page high byteJSR LAB_UFAC ; unpack memory (STEP value) into FAC1TSX ; get stack pointer backLDA LAB_STAK+8,X ; get step signSTA FAC1_s ; save FAC1 sign (b7)LDA Frnxtl ; get FOR variable pointer low byteLDY Frnxth ; get FOR variable pointer high byteJSR LAB_246C ; add (FOR variable) to FAC1JSR LAB_PFAC ; pack FAC1 into (FOR variable)LDY #>LAB_STAK ; point to stack page high byteJSR LAB_27FA ; compare FAC1 with (Y,ut2_pl) (TO value)TSX ; get stack pointer backCMP LAB_STAK+8,X ; compare step signBEQ LAB_1A9B ; branch if = (loop complete); loop back and do it all againLDA LAB_STAK+$0D,X ; get FOR line low byteSTA Clinel ; save current line low byteLDA LAB_STAK+$0E,X ; get FOR line high byteSTA Clineh ; save current line high byteLDA LAB_STAK+$10,X ; get BASIC execute pointer low byteSTA Bpntrl ; save BASIC execute pointer low byteLDA LAB_STAK+$0F,X ; get BASIC execute pointer high byteSTA Bpntrh ; save BASIC execute pointer high byteLAB_1A98JMP LAB_15C2 ; go do interpreter inner loop; loop complete so carry onLAB_1A9BTXA ; stack copy to AADC #$0F ; add $10 ($0F+carry) to dump FOR structureTAX ; copy back to indexTXS ; copy to stack pointerJSR LAB_GBYT ; scan memoryCMP #',' ; compare with ","BNE LAB_1A98 ; branch if not "," (go do interpreter inner loop); was "," so another NEXT variable to doJSR LAB_IGBY ; else increment and scan memoryJSR LAB_1A46 ; do NEXT (var); evaluate expression and check is numeric, else do type mismatchLAB_EVNMJSR LAB_EVEX ; evaluate expression; check if source is numeric, else do type mismatchLAB_CTNMCLC ; destination is numeric.byte $24 ; makes next line BIT $38; check if source is string, else do type mismatchLAB_CTSTSEC ; required type is string; type match check, set C for string, clear C for numericLAB_CKTMBIT Dtypef ; test data type flag, $FF=string, $00=numericBMI LAB_1ABA ; branch if data type is string; else data type was numericBCS LAB_1ABC ; if required type is string do type mismatch errorLAB_1AB9RTS; data type was string, now check required typeLAB_1ABABCS LAB_1AB9 ; exit if required type is string; else do type mismatch errorLAB_1ABCLDX #$18 ; error code $18 ("Type mismatch" error)LAB_1ABEJMP LAB_XERR ; do error #X, then warm start; evaluate expressionLAB_EVEXLDX Bpntrl ; get BASIC execute pointer low byteBNE LAB_1AC7 ; skip next if not zeroDEC Bpntrh ; else decrement BASIC execute pointer high byteLAB_1AC7DEC Bpntrl ; decrement BASIC execute pointer low byteLAB_EVEZLDA #$00 ; set null precedence (flag done)LAB_1ACCPHA ; push precedence byteLDA #$02 ; 2 bytesJSR LAB_1212 ; check room on stack for A bytesJSR LAB_GVAL ; get value from lineLDA #$00 ; clear ASTA comp_f ; clear compare function flagLAB_1ADBJSR LAB_GBYT ; scan memoryLAB_1ADESEC ; set carry for subtractSBC #TK_GT ; subtract token for > (lowest comparison function)BCC LAB_1AFA ; branch if < TK_GTCMP #$03 ; compare with ">" to "<" tokensBCS 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 bitsCMP comp_f ; compare with compare function flagBCC LAB_1B53 ; if <(comp_f) do syntax error then warm start; was more than one <, = or >)STA comp_f ; save new compare function flagJSR LAB_IGBY ; increment and scan memoryJMP LAB_1ADE ; go do next character; token is < ">" or > "<" tokensLAB_1AFALDX comp_f ; get compare function flagBNE LAB_1B2A ; branch if compare functionBCS LAB_1B78 ; go do functions; else was < TK_GT so is operator or lowerADC #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 EORBNE LAB_1B0B ; branch if not + tokenBIT Dtypef ; test data type flag, $FF=string, $00=numericBPL 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 returnLAB_1B0BSTA ut1_pl ; save itASL ; *2ADC ut1_pl ; *3TAY ; copy to indexLAB_1B13PLA ; pull previous precedenceCMP LAB_OPPT,Y ; compare with precedence byteBCS LAB_1B7D ; branch if A >=JSR LAB_CTNM ; check if source is numeric, else do type mismatchLAB_1B1CPHA ; save precedenceLAB_1B1DJSR LAB_1B43 ; get vector, execute function then continue evaluationPLA ; restore precedenceLDY prstk ; get precedence stacked flagBPL LAB_1B3C ; branch if stacked valuesTAX ; copy precedence (set flags)BEQ LAB_1B9D ; exit if doneBNE LAB_1B86 ; else pop FAC2 and return, branch alwaysLAB_1B2AROL Dtypef ; shift data type flag into CbTXA ; copy compare function flagSTA Dtypef ; clear data type flag, X is 0xxx xxxxROL ; shift data type into compare function byte b0LDX Bpntrl ; get BASIC execute pointer low byteBNE LAB_1B34 ; branch if no underflowDEC Bpntrh ; else decrement BASIC execute pointer high byteLAB_1B34DEC Bpntrl ; decrement BASIC execute pointer low byteTK_LT_PLUS = TK_LT-TK_PLUSLDY #TK_LT_PLUS*3 ; set offset to last operator entrySTA comp_f ; save new compare function flagBNE LAB_1B13 ; branch alwaysLAB_1B3CCMP LAB_OPPT,Y ;.compare with stacked function precedenceBCS LAB_1B86 ; branch if A >=, pop FAC2 and returnBCC LAB_1B1C ; branch always;.get vector, execute function then continue evaluationLAB_1B43LDA LAB_OPPT+2,Y ; get function vector high bytePHA ; onto stackLDA LAB_OPPT+1,Y ; get function vector low bytePHA ; onto stack; now push sign, round FAC1 and put on stackJSR LAB_1B5B ; function will return here, then the next RTS will call; the functionLDA comp_f ; get compare function flagPHA ; push compare evaluation byteLDA LAB_OPPT,Y ; get precedence byteJMP LAB_1ACC ; continue evaluating expressionLAB_1B53JMP LAB_SNER ; do syntax error then warm start; push sign, round FAC1 and put on stackLAB_1B5BPLA ; get return addr low byteSTA ut1_pl ; save itINC 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 byteSTA ut1_ph ; save itLDA FAC1_s ; get FAC1 sign (b7)PHA ; push sign; round FAC1 and put on stackLAB_1B66JSR LAB_27BA ; round FAC1LDA FAC1_3 ; get FAC1 mantissa3PHA ; push on stackLDA FAC1_2 ; get FAC1 mantissa2PHA ; push on stackLDA FAC1_1 ; get FAC1 mantissa1PHA ; push on stackLDA FAC1_e ; get FAC1 exponentPHA ; push on stackJMP (ut1_pl) ; return, sort of; do functionsLAB_1B78LDY #$FF ; flag functionPLA ; pull precedence byteLAB_1B7BBEQ LAB_1B9D ; exit if doneLAB_1B7DCMP #$64 ; compare previous precedence with $64BEQ LAB_1B84 ; branch if was $64 (< function)JSR LAB_CTNM ; check if source is numeric, else do type mismatchLAB_1B84STY prstk ; save precedence stacked flag; pop FAC2 and returnLAB_1B86PLA ; pop byteLSR ; shift out comparison evaluation lowest bitSTA Cflag ; save comparison evaluation flagPLA ; pop exponentSTA FAC2_e ; save FAC2 exponentPLA ; pop mantissa1STA FAC2_1 ; save FAC2 mantissa1PLA ; pop mantissa2STA FAC2_2 ; save FAC2 mantissa2PLA ; pop mantissa3STA FAC2_3 ; save FAC2 mantissa3PLA ; pop signSTA FAC2_s ; save FAC2 sign (b7)EOR FAC1_s ; EOR FAC1 sign (b7)STA FAC_sc ; save sign compare (FAC1 EOR FAC2)LAB_1B9DLDA FAC1_e ; get FAC1 exponentRTS; print "..." string to string util areaLAB_1BC1LDA Bpntrl ; get BASIC execute pointer low byteLDY Bpntrh ; get BASIC execute pointer high byteADC #$00 ; add carry to low byteBCC LAB_1BCA ; branch if no overflowINY ; increment high byteLAB_1BCAJSR LAB_20AE ; print " terminated string to Sutill/SutilhJMP LAB_23F3 ; restore BASIC execute pointer from temp and return; get value from lineLAB_GVALJSR LAB_IGBY ; increment and scan memoryBCS LAB_1BAC ; branch if not numeric character; else numeric string found (e.g. 123)LAB_1BA9JMP LAB_2887 ; get FAC1 from string and return; get value from line .. continued; wasn't a number so ..LAB_1BACTAX ; set the flagsBMI 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 numberCMP #'%' ; else compare with "%"BEQ LAB_1BA9 ; branch if "%", binary numberCMP #'.' ; 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 parenthesesCMP #'(' ; compare with "("BNE LAB_1C18 ; if not "(" get (var), return value in FAC1 and $ flagLAB_1BF7JSR 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 startLAB_1BFBLDA #$29 ; load A with ")"; scan for CHR$(A) , else do syntax error then warm startLAB_SCCALDY #$00 ; clear indexCMP (Bpntrl),Y ; check next byte is = ABNE LAB_SNER ; if not do syntax error then warm startJMP LAB_IGBY ; increment and scan memory then return; scan for "(" , else do syntax error then warm startLAB_1BFELDA #$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 startLAB_1C01LDA #$2C ; load A with ","BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start; (branch always); syntax error then warm startLAB_SNERLDX #$02 ; error code $02 ("Syntax" error)JMP LAB_XERR ; do error #X, then warm start; get value from line .. continued; do tokensLAB_1BD0CMP #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 NOTBNE LAB_1BE7 ; branch if not token for NOT; was NOT tokenTK_EQUAL_PLUS = TK_EQUAL-TK_PLUSLDY #TK_EQUAL_PLUS*3 ; offset to NOT functionBNE LAB_1C13 ; do set-up for function then execute (branch always); do = compareLAB_EQUALJSR LAB_EVIR ; evaluate integer expression (no sign check)LDA FAC1_3 ; get FAC1 mantissa3EOR #$FF ; invert itTAY ; copy itLDA FAC1_2 ; get FAC1 mantissa2EOR #$FF ; invert itJMP LAB_AYFC ; save and convert integer AY to FAC1 and return; get value from line .. continued; wasn't +, -, or NOT so ..LAB_1BE7CMP #TK_FN ; compare with token for FNBNE LAB_1BEE ; branch if not token for FNJMP LAB_201E ; go evaluate FNx; get value from line .. continued; wasn't +, -, NOT or FN so ..LAB_1BEESBC #TK_SGN ; subtract with token for SGNBCS LAB_1C27 ; if a function token go do itJMP LAB_SNER ; else do syntax error; set-up for functionsLAB_1C11TK_GT_PLUS = TK_GT-TK_PLUSLDY #TK_GT_PLUS*3 ; set offset from base to > operatorLAB_1C13PLA ; dump return address low bytePLA ; dump return address high byteJMP LAB_1B1D ; execute function then continue evaluation; variable name set-up; get (var), return value in FAC_1 and $ flagLAB_1C18JSR LAB_GVAR ; get (var) addressSTA FAC1_2 ; save address low byte in FAC1 mantissa2STY FAC1_3 ; save address high byte in FAC1 mantissa3LDX Dtypef ; get data type flag, $FF=string, $00=numericBMI LAB_1C25 ; if string then return (does RTS)LAB_1C24JMP LAB_UFAC ; unpack memory (AY) into FAC1LAB_1C25RTS; 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 stringsLAB_1C27ASL ; *2 (2 bytes per function address)TAY ; copy to indexLDA LAB_FTBM,Y ; get function jump vector high bytePHA ; push functions jump vector high byteLDA LAB_FTBL,Y ; get function jump vector low bytePHA ; push functions jump vector low byteLDA LAB_FTPM,Y ; get function pre process vector high byteBEQ LAB_1C56 ; skip pre process if null vectorPHA ; push functions pre process vector high byteLDA LAB_FTPL,Y ; get function pre process vector low bytePHA ; push functions pre process vector low byteLAB_1C56RTS ; do function, or pre process, call; process string expression in parenthesisLAB_PPFSJSR LAB_1BF7 ; process expression in parenthesisJMP LAB_CTST ; check if source is string then do function,; else do type mismatch; process numeric expression in parenthesisLAB_PPFNJSR LAB_1BF7 ; process expression in parenthesisJMP LAB_CTNM ; check if source is numeric then do function,; else do type mismatch; set numeric data type and increment BASIC execute pointerLAB_PPBILSR Dtypef ; clear data type flag, $FF=string, $00=numericJMP LAB_IGBY ; increment and scan memory then do function; process string for LEFT$, RIGHT$ or MID$LAB_LRMSJSR LAB_EVEZ ; evaluate (should be string) expressionJSR LAB_1C01 ; scan for ",", else do syntax error then warm startJSR LAB_CTST ; check if source is string, else do type mismatchPLA ; get function jump vector low byteTAX ; save functions jump vector low bytePLA ; get function jump vector high byteTAY ; save functions jump vector high byteLDA des_ph ; get descriptor pointer high bytePHA ; push string pointer high byteLDA des_pl ; get descriptor pointer low bytePHA ; push string pointer low byteTYA ; get function jump vector high byte backPHA ; save functions jump vector high byteTXA ; get function jump vector low byte backPHA ; save functions jump vector low byteJSR LAB_GTBY ; get byte parameterTXA ; copy byte parameter to ARTS ; go do function; process numeric expression(s) for BIN$ or HEX$LAB_BHSSJSR LAB_EVEZ ; process expressionJSR LAB_CTNM ; check if source is numeric, else do type mismatchLDA FAC1_e ; get FAC1 exponentCMP #$98 ; compare with exponent = 2^24BCS LAB_BHER ; branch if n>=2^24 (is too big)JSR LAB_2831 ; convert FAC1 floating-to-fixedLDX #$02 ; 3 bytes to doLAB_CFACLDA FAC1_1,X ; get byte from FAC1STA nums_1,X ; save byte to tempDEX ; decrement indexBPL LAB_CFAC ; copy FAC1 mantissa to tempJSR LAB_GBYT ; get next BASIC byteLDX #$00 ; set default to no leading "0"sCMP #')' ; compare with close bracketBEQ LAB_1C54 ; if ")" go do rest of functionJSR LAB_SCGB ; scan for "," and get byteJSR LAB_GBYT ; get last byte backCMP #')' ; is next character )BNE LAB_BHER ; if not ")" go do errorLAB_1C54RTS ; else do functionLAB_BHERJMP LAB_FCER ; do function call error then warm start; perform EOR; added operator format is the same as AND or OR, precedence is the same as OR; this bit worked first time but it took a while to sort out the operator table; pointers and offsets afterwards!LAB_EORJSR GetFirst ; get first integer expression (no sign check)EOR XOAw_l ; EOR with expression 1 low byteTAY ; save in YLDA FAC1_2 ; get FAC1 mantissa2EOR XOAw_h ; EOR with expression 1 high byteJMP LAB_AYFC ; save and convert integer AY to FAC1 and return; perform ORLAB_ORJSR GetFirst ; get first integer expression (no sign check)ORA XOAw_l ; OR with expression 1 low byteTAY ; save in YLDA FAC1_2 ; get FAC1 mantissa2ORA XOAw_h ; OR with expression 1 high byteJMP LAB_AYFC ; save and convert integer AY to FAC1 and return; perform ANDLAB_ANDJSR GetFirst ; get first integer expression (no sign check)AND XOAw_l ; AND with expression 1 low byteTAY ; save in YLDA FAC1_2 ; get FAC1 mantissa2AND XOAw_h ; AND with expression 1 high byteJMP LAB_AYFC ; save and convert integer AY to FAC1 and return; get first value for OR, AND or EORGetFirstJSR LAB_EVIR ; evaluate integer expression (no sign check)LDA FAC1_2 ; get FAC1 mantissa2STA XOAw_h ; save itLDA FAC1_3 ; get FAC1 mantissa3STA XOAw_l ; save itJSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression)JSR LAB_EVIR ; evaluate integer expression (no sign check)LDA FAC1_3 ; get FAC1 mantissa3LAB_1C95RTS; perform comparisons; do < compareLAB_LTHANJSR LAB_CKTM ; type match check, set C for stringBCS LAB_1CAE ; branch if string; do numeric < compareLDA FAC2_s ; get FAC2 sign (b7)ORA #$7F ; set all non sign bitsAND FAC2_1 ; and FAC2 mantissa1 (AND in sign bit)STA FAC2_1 ; save FAC2 mantissa1LDA #<FAC2_e ; set pointer low byte to FAC2LDY #>FAC2_e ; set pointer high byte to FAC2JSR LAB_27F8 ; compare FAC1 with FAC2 (AY)TAX ; copy resultJMP LAB_1CE1 ; go evaluate result; do string < compareLAB_1CAELSR Dtypef ; clear data type flag, $FF=string, $00=numericDEC comp_f ; clear < bit in compare function flagJSR LAB_22B6 ; pop string off descriptor stack, or from top of string; space returns with A = length, X=pointer low byte,; Y=pointer high byteSTA str_ln ; save lengthSTX str_pl ; save string pointer low byteSTY str_ph ; save string pointer high byteLDA FAC2_2 ; get descriptor pointer low byteLDY FAC2_3 ; get descriptor pointer high byteJSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space; returns with A = length, X=pointer low byte,; Y=pointer high byteSTX FAC2_2 ; save string pointer low byteSTY FAC2_3 ; save string pointer high byteTAX ; copy lengthSEC ; set carry for subtractSBC str_ln ; subtract string 1 lengthBEQ LAB_1CD6 ; branch if str 1 length = string 2 lengthLDA #$01 ; set str 1 length > string 2 lengthBCC LAB_1CD6 ; branch if soLDX str_ln ; get string 1 lengthLDA #$FF ; set str 1 length < string 2 lengthLAB_1CD6STA FAC1_s ; save length compareLDY #$FF ; set indexINX ; adjust for loopLAB_1CDBINY ; increment indexDEX ; decrement countBNE LAB_1CE6 ; branch if still bytes to doLDX FAC1_s ; get length compare backLAB_1CE1BMI LAB_1CF2 ; branch if str 1 < str 2CLC ; flag str 1 <= str 2BCC LAB_1CF2 ; go evaluate resultLAB_1CE6LDA (FAC2_2),Y ; get string 2 byteCMP (FAC1_1),Y ; compare with string 1 byteBEQ LAB_1CDB ; loop if bytes =LDX #$FF ; set str 1 < string 2BCS LAB_1CF2 ; branch if soLDX #$01 ; set str 1 > string 2LAB_1CF2INX ; x = 0, 1 or 2TXA ; copy to AROL ; *2 (1, 2 or 4)AND Cflag ; AND with comparison evaluation flagBEQ LAB_1CFB ; branch if 0 (compare is false)LDA #$FF ; else set result trueLAB_1CFBJMP LAB_27DB ; save A as integer byte and returnLAB_1CFEJSR LAB_1C01 ; scan for ",", else do syntax error then warm start; perform DIMLAB_DIMTAX ; copy "DIM" flag to XJSR LAB_1D10 ; search for variableJSR LAB_GBYT ; scan memoryBNE LAB_1CFE ; scan for "," and loop if not nullRTS; perform << (left shift)LAB_LSHIFTJSR GetPair ; get integer expression and byte (no sign check)LDA FAC1_2 ; get expression high byteLDX TempB ; get shift countBEQ NoShift ; branch if zeroCPX #$10 ; compare bit count with 16dBCS TooBig ; branch if >=Ls_loopASL FAC1_3 ; shift low byteROL ; shift high byteDEX ; decrement bit countBNE Ls_loop ; loop if shift not completeLDY FAC1_3 ; get expression low byteJMP LAB_AYFC ; save and convert integer AY to FAC1 and return; perform >> (right shift)LAB_RSHIFTJSR GetPair ; get integer expression and byte (no sign check)LDA FAC1_2 ; get expression high byteLDX TempB ; get shift countBEQ NoShift ; branch if zeroCPX #$10 ; compare bit count with 16dBCS TooBig ; branch if >=Rs_loopLSR ; shift high byteROR FAC1_3 ; shift low byteDEX ; decrement bit countBNE Rs_loop ; loop if shift not completeNoShiftLDY FAC1_3 ; get expression low byteJMP LAB_AYFC ; save and convert integer AY to FAC1 and returnTooBigLDA #$00 ; clear high byteTAY ; copy to low byteJMP LAB_AYFC ; save and convert integer AY to FAC1 and returnGetPairJSR LAB_EVBY ; evaluate byte expression, result in XSTX TempB ; save itJSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression)JMP LAB_EVIR ; evaluate integer expression (no sign check); search for variable; return pointer to variable in Cvaral/CvarahLAB_GVARLDX #$00 ; set DIM flag = $00JSR LAB_GBYT ; scan memory (1st character)LAB_1D10STX Defdim ; save DIM flagLAB_1D12STA Varnm1 ; save 1st characterAND #$7F ; clear FN flag bitJSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z"BCS LAB_1D1F ; branch if okJMP LAB_SNER ; else syntax error then warm start; was variable name so ..LAB_1D1FLDX #$00 ; clear 2nd character tempSTX Dtypef ; clear data type flag, $FF=string, $00=numericJSR LAB_IGBY ; increment and scan memory (2nd character)BCC LAB_1D2D ; branch if character = "0"-"9" (ok); 2nd character wasn't "0" to "9" so ..JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z"BCC LAB_1D38 ; branch if <"A" or >"Z" (go check if string)LAB_1D2DTAX ; copy 2nd character; ignore further (valid) characters in the variable nameLAB_1D2EJSR LAB_IGBY ; increment and scan memory (3rd character)BCC LAB_1D2E ; loop if character = "0"-"9" (ignore)JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z"BCS LAB_1D2E ; loop if character = "A"-"Z" (ignore); check if string variableLAB_1D38CMP #'$' ; compare with "$"BNE LAB_1D47 ; branch if not string; to introduce a new variable type (% suffix for integers say) then this branch; will need to go to that check and then that branch, if it fails, go to LAB_1D47; type is stringLDA #$FF ; set data type = stringSTA Dtypef ; set data type flag, $FF=string, $00=numericTXA ; get 2nd character backORA #$80 ; set top bit (indicate string var)TAX ; copy back to 2nd character tempJSR LAB_IGBY ; increment and scan memory; after we have determined the variable type we need to come back here to determine; if it's an array of type. this would plug in a%(b[,c[,d]])) integer arrays nicelyLAB_1D47 ; gets here with character after var name in ASTX Varnm2 ; save 2nd characterORA Sufnxf ; or with subscript/FNX flag (or FN name)CMP #'(' ; compare with "("BNE LAB_1D53 ; branch if not "("JMP LAB_1E17 ; go find, or make, array; either find or create var; var name (1st two characters only!) is in Varnm1,Varnm2; variable name wasn't var(... so look for plain varLAB_1D53LDA #$00 ; clear ASTA Sufnxf ; clear subscript/FNX flagLDA Svarl ; get start of vars low byteLDX Svarh ; get start of vars high byteLDY #$00 ; clear indexLAB_1D5DSTX Vrschh ; save search address high byteLAB_1D5FSTA Vrschl ; save search address low byteCPX Sarryh ; compare high address with var space endBNE LAB_1D69 ; skip next compare if <>; high addresses were = so compare low addressesCMP Sarryl ; compare low address with var space endBEQ LAB_1D8B ; if not found go make new varLAB_1D69LDA Varnm1 ; get 1st character of var to findCMP (Vrschl),Y ; compare with variable name 1st characterBNE LAB_1D77 ; branch if no match; 1st characters match so compare 2nd charactersLDA Varnm2 ; get 2nd character of var to findINY ; index to point to variable name 2nd characterCMP (Vrschl),Y ; compare with variable name 2nd characterBEQ LAB_1DD7 ; branch if match (found var)DEY ; else decrement index (now = $00)LAB_1D77CLC ; clear carry for addLDA Vrschl ; get search address low byteADC #$06 ; +6 (offset to next var name)BCC LAB_1D5F ; loop if no overflow to high byteINX ; else increment high byteBNE LAB_1D5D ; loop always (RAM doesn't extend to $FFFF !); check byte, return C=0 if<"A" or >"Z" or "a" to "z"LAB_CASCCMP #'a' ; compare with "a"BCS LAB_1D83 ; go check <"z"+1; check byte, return C=0 if<"A" or >"Z"LAB_1D82CMP #'A' ; compare with "A"BCC LAB_1D8A ; exit if less; carry is setSBC #$5B ; subtract "Z"+1SEC ; set carrySBC #$A5 ; subtract $A5 (restore byte); carry clear if byte>$5ALAB_1D8ARTSLAB_1D83SBC #$7B ; subtract "z"+1SEC ; set carrySBC #$85 ; subtract $85 (restore byte); carry clear if byte>$7ARTS; reached end of variable mem without match; .. so create new variableLAB_1D8BPLA ; pop return address low bytePHA ; push return address low byteLAB_1C18p2 = LAB_1C18+2CMP #<LAB_1C18p2 ; compare with expected calling routine return low byteBNE LAB_1D98 ; if not get (var) go create new var; This will only drop through if the call was from LAB_1C18 and is only called; from there if it is searching for a variable from the RHS of a LET a=b statement; it prevents the creation of variables not assigned a value.; value returned by this is either numeric zero (exponent byte is $00) or null string; (descriptor length byte is $00). in fact a pointer to any $00 byte would have done.; doing this saves 6 bytes of variable memory and 168 machine cycles of time; this is where you would put the undefined variable error call e.g.; ; variable doesn't exist so flag error; LDX #$24 ; error code $24 ("undefined variable" error); JMP LAB_XERR ; do error #X then warm start; the above code has been tested and works a treat! (it replaces the three code lines; below); else return dummy null valueLDA #<LAB_1D96 ; low byte point to $00,$00; (uses part of misc constants table)LDY #>LAB_1D96 ; high byte point to $00,$00RTS; create new numeric variableLAB_1D98LDA Sarryl ; get var mem end low byteLDY Sarryh ; get var mem end high byteSTA Ostrtl ; save old block start low byteSTY Ostrth ; save old block start high byteLDA Earryl ; get array mem end low byteLDY Earryh ; get array mem end high byteSTA Obendl ; save old block end low byteSTY Obendh ; save old block end high byteCLC ; clear carry for addADC #$06 ; +6 (space for one var)BCC LAB_1DAE ; branch if no overflow to high byteINY ; else increment high byteLAB_1DAESTA Nbendl ; set new block end low byteSTY Nbendh ; set new block end high byteJSR LAB_11CF ; open up space in memoryLDA Nbendl ; get new start low byteLDY Nbendh ; get new start high byte (-$100)INY ; correct high byteSTA Sarryl ; save new var mem end low byteSTY Sarryh ; save new var mem end high byteLDY #$00 ; clear indexLDA Varnm1 ; get var name 1st characterSTA (Vrschl),Y ; save var name 1st characterINY ; increment indexLDA Varnm2 ; get var name 2nd characterSTA (Vrschl),Y ; save var name 2nd characterLDA #$00 ; clear AINY ; increment indexSTA (Vrschl),Y ; initialise var byteINY ; increment indexSTA (Vrschl),Y ; initialise var byteINY ; increment indexSTA (Vrschl),Y ; initialise var byteINY ; increment indexSTA (Vrschl),Y ; initialise var byte; found a match for var ((Vrschl) = ptr)LAB_1DD7LDA Vrschl ; get var address low byteCLC ; clear carry for addADC #$02 ; +2 (offset past var name bytes)LDY Vrschh ; get var address high byteBCC LAB_1DE1 ; branch if no overflow from addINY ; else increment high byteLAB_1DE1STA Cvaral ; save current var address low byteSTY Cvarah ; save current var address high byteRTS; set-up array pointer (Adatal/h) to first element in array; set Adatal,Adatah to Astrtl,Astrth+2*Dimcnt+#$05LAB_1DE6LDA Dimcnt ; get # of dimensions (1, 2 or 3)ASL ; *2 (also clears the carry !)ADC #$05 ; +5 (result is 7, 9 or 11 here)ADC Astrtl ; add array start pointer low byteLDY Astrth ; get array pointer high byteBCC LAB_1DF2 ; branch if no overflowINY ; else increment high byteLAB_1DF2STA Adatal ; save array data pointer low byteSTY Adatah ; save array data pointer high byteRTS; evaluate integer expressionLAB_EVINJSR LAB_IGBY ; increment and scan memoryJSR LAB_EVNM ; evaluate expression and check is numeric,; else do type mismatch; evaluate integer expression (no check)LAB_EVPILDA FAC1_s ; get FAC1 sign (b7)BMI LAB_1E12 ; do function call error if -ve; evaluate integer expression (no sign check)LAB_EVIRLDA FAC1_e ; get FAC1 exponentCMP #$90 ; compare with exponent = 2^16 (n>2^15)BCC LAB_1E14 ; branch if n<2^16 (is ok)LDA #<LAB_1DF7 ; set pointer low byte to -32768LDY #>LAB_1DF7 ; set pointer high byte to -32768JSR LAB_27F8 ; compare FAC1 with (AY)LAB_1E12BNE LAB_FCER ; if <> do function call error then warm startLAB_1E14JMP LAB_2831 ; convert FAC1 floating-to-fixed and return; find or make arrayLAB_1E17LDA Defdim ; get DIM flagPHA ; push itLDA Dtypef ; get data type flag, $FF=string, $00=numericPHA ; push itLDY #$00 ; clear dimensions count; now get the array dimension(s) and stack it (them) before the data type and DIM flagLAB_1E1FTYA ; copy dimensions countPHA ; save itLDA Varnm2 ; get array name 2nd bytePHA ; save itLDA Varnm1 ; get array name 1st bytePHA ; save itJSR LAB_EVIN ; evaluate integer expressionPLA ; pull array name 1st byteSTA Varnm1 ; restore array name 1st bytePLA ; pull array name 2nd byteSTA Varnm2 ; restore array name 2nd bytePLA ; pull dimensions countTAY ; restore itTSX ; copy stack pointerLDA LAB_STAK+2,X ; get DIM flagPHA ; push itLDA LAB_STAK+1,X ; get data type flagPHA ; push itLDA FAC1_2 ; get this dimension size high byteSTA LAB_STAK+2,X ; stack before flag bytesLDA FAC1_3 ; get this dimension size low byteSTA LAB_STAK+1,X ; stack before flag bytesINY ; increment dimensions countJSR LAB_GBYT ; scan memoryCMP #',' ; compare with ","BEQ LAB_1E1F ; if found go do next dimensionSTY Dimcnt ; store dimensions countJSR LAB_1BFB ; scan for ")" , else do syntax error then warm startPLA ; pull data type flagSTA Dtypef ; restore data type flag, $FF=string, $00=numericPLA ; pull DIM flagSTA Defdim ; restore DIM flagLDX Sarryl ; get array mem start low byteLDA Sarryh ; get array mem start high byte; now check to see if we are at the end of array memory (we would be if there were; no arrays).LAB_1E5CSTX Astrtl ; save as array start pointer low byteSTA Astrth ; save as array start pointer high byteCMP Earryh ; compare with array mem end high byteBNE LAB_1E68 ; branch if not reached array mem endCPX Earryl ; else compare with array mem end low byteBEQ LAB_1EA1 ; go build array if not found; search for arrayLAB_1E68LDY #$00 ; clear indexLDA (Astrtl),Y ; get array name first byteINY ; increment index to second name byteCMP Varnm1 ; compare with this array name first byteBNE LAB_1E77 ; branch if no matchLDA Varnm2 ; else get this array name second byteCMP (Astrtl),Y ; compare with array name second byteBEQ LAB_1E8D ; array found so branch; no matchLAB_1E77INY ; increment indexLDA (Astrtl),Y ; get array size low byteCLC ; clear carry for addADC Astrtl ; add array start pointer low byteTAX ; copy low byte to XINY ; increment indexLDA (Astrtl),Y ; get array size high byteADC Astrth ; add array mem pointer high byteBCC LAB_1E5C ; if no overflow go check next array; do array bounds errorLAB_1E85LDX #$10 ; error code $10 ("Array bounds" error).byte $2C ; makes next bit BIT LAB_08A2; do function call errorLAB_FCERLDX #$08 ; error code $08 ("Function call" error)LAB_1E8AJMP LAB_XERR ; do error #X, then warm start; found array, are we trying to dimension it?LAB_1E8DLDX #$12 ; set error $12 ("Double dimension" error)LDA Defdim ; get DIM flagBNE LAB_1E8A ; if we are trying to dimension it do error #X, then warm; start; found the array and we're not dimensioning it so we must find an element in itJSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array; (Astrtl,Astrth points to start of array)LDA Dimcnt ; get dimensions countLDY #$04 ; set index to array's # of dimensionsCMP (Astrtl),Y ; compare with no of dimensionsBNE LAB_1E85 ; if wrong do array bounds error, could do "Wrong; dimensions" error here .. if we want a different; error messageJMP LAB_1F28 ; found array so go get element; (could jump to LAB_1F28 as all LAB_1F24 does is take; Dimcnt and save it at (Astrtl),Y which is already the; same or we would have taken the BNE); array not found, so build itLAB_1EA1JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array; (Astrtl,Astrth points to start of array)JSR LAB_121F ; check available memory, "Out of memory" error if no room; addr to check is in AY (low/high)LDY #$00 ; clear Y (don't need to clear A)STY Aspth ; clear array data size high byteLDA Varnm1 ; get variable name 1st byteSTA (Astrtl),Y ; save array name 1st byteINY ; increment indexLDA Varnm2 ; get variable name 2nd byteSTA (Astrtl),Y ; save array name 2nd byteLDA Dimcnt ; get dimensions countLDY #$04 ; index to dimension countSTY Asptl ; set array data size low byte (four bytes per element)STA (Astrtl),Y ; set array's dimensions count; now calculate the size of the data space for the arrayCLC ; clear carry for add (clear on subsequent loops)LAB_1EC0LDX #$0B ; set default dimension value low byteLDA #$00 ; set default dimension value high byteBIT Defdim ; test default DIM flagBVC LAB_1ED0 ; branch if b6 of Defdim is clearPLA ; else pull dimension value low byteADC #$01 ; +1 (allow for zeroeth element)TAX ; copy low byte to XPLA ; pull dimension value high byteADC #$00 ; add carry from low byteLAB_1ED0INY ; index to dimension value high byteSTA (Astrtl),Y ; save dimension value high byteINY ; index to dimension value high byteTXA ; get dimension value low byteSTA (Astrtl),Y ; save dimension value low byteJSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl)STX Asptl ; save array data size low byteSTA Aspth ; save array data size high byteLDY ut1_pl ; restore index (saved by subroutine)DEC Dimcnt ; decrement dimensions countBNE LAB_1EC0 ; loop while not = 0ADC Adatah ; add size high byte to first element high byte; (carry is always clear here)BCS LAB_1F45 ; if overflow go do "Out of memory" errorSTA Adatah ; save end of array high byteTAY ; copy end high byte to YTXA ; get array size low byteADC Adatal ; add array start low byteBCC LAB_1EF3 ; branch if no carryINY ; else increment end of array high byteBEQ LAB_1F45 ; if overflow go do "Out of memory" error; set-up mostly complete, now zero the arrayLAB_1EF3JSR LAB_121F ; check available memory, "Out of memory" error if no room; addr to check is in AY (low/high)STA Earryl ; save array mem end low byteSTY Earryh ; save array mem end high byteLDA #$00 ; clear byte for array clearINC Aspth ; increment array size high byte (now block count)LDY Asptl ; get array size low byte (now index to block)BEQ LAB_1F07 ; branch if low byte = $00message "LAB_1F02"LAB_1F02DEY ; decrement index (do 0 to n-1)STA (Adatal),Y ; zero byteBNE LAB_1F02 ; loop until this block doneLAB_1F07DEC Adatah ; decrement array pointer high byteDEC Aspth ; decrement block count high byteBNE LAB_1F02 ; loop until all blocks doneINC Adatah ; correct for last loopSEC ; set carry for subtractLDY #$02 ; index to array size low byteLDA Earryl ; get array mem end low byteSBC Astrtl ; subtract array start low byteSTA (Astrtl),Y ; save array size low byteINY ; index to array size high byteLDA Earryh ; get array mem end high byteSBC Astrth ; subtract array start high byteSTA (Astrtl),Y ; save array size high byteLDA Defdim ; get default DIM flagBNE LAB_1F7B ; exit (RET) if this was a DIM command; else, find elementINY ; index to # of dimensionsLAB_1F24LDA (Astrtl),Y ; get array's dimension countSTA Dimcnt ; save it; we have found, or built, the array. now we need to find the elementLAB_1F28LDA #$00 ; clear byteSTA Asptl ; clear array data pointer low byteLAB_1F2CSTA Aspth ; save array data pointer high byteINY ; increment index (point to array bound high byte)PLA ; pull array index low byteTAX ; copy to XSTA FAC1_2 ; save index low byte to FAC1 mantissa2PLA ; pull array index high byteSTA FAC1_3 ; save index high byte to FAC1 mantissa3CMP (Astrtl),Y ; compare with array bound high byteBCC LAB_1F48 ; branch if within boundsBNE LAB_1F42 ; if outside bounds do array bounds error; else high byte was = so test low bytesINY ; index to array bound low byteTXA ; get array index low byteCMP (Astrtl),Y ; compare with array bound low byteBCC LAB_1F49 ; branch if within boundsLAB_1F42JMP LAB_1E85 ; else do array bounds errorLAB_1F45JMP LAB_OMER ; do "Out of memory" error then warm startLAB_1F48INY ; index to array bound low byteLAB_1F49LDA Aspth ; get array data pointer high byteORA Asptl ; OR with array data pointer low byteBEQ LAB_1F5A ; branch if array data pointer = null (skip multiply)JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl)TXA ; get result low byteADC FAC1_2 ; add index low byte from FAC1 mantissa2TAX ; save result low byteTYA ; get result high byteLDY ut1_pl ; restore indexLAB_1F5AADC FAC1_3 ; add index high byte from FAC1 mantissa3STX Asptl ; save array data pointer low byteDEC Dimcnt ; decrement dimensions countBNE LAB_1F2C ; loop if dimensions still to doASL Asptl ; array data pointer low byte * 2ROL ; array data pointer high byte * 2ASL Asptl ; array data pointer low byte * 4ROL ; array data pointer high byte * 4TAY ; copy high byteLDA Asptl ; get low byteADC Adatal ; add array data start pointer low byteSTA Cvaral ; save as current var address low byteTYA ; get high byte backADC Adatah ; add array data start pointer high byteSTA Cvarah ; save as current var address high byteTAY ; copy high byte to YLDA Cvaral ; get current var address low byteLAB_1F7BRTS; does XY = (Astrtl),Y * (Asptl)LAB_1F7CSTY ut1_pl ; save indexLDA (Astrtl),Y ; get dimension size low byteSTA dims_l ; save dimension size low byteDEY ; decrement indexLDA (Astrtl),Y ; get dimension size high byteSTA dims_h ; save dimension size high byteLDA #$10 ; count = $10 (16 bit multiply)STA numbit ; save bit countLDX #$00 ; clear result low byteLDY #$00 ; clear result high byteLAB_1F8FTXA ; get result low byteASL ; *2TAX ; save result low byteTYA ; get result high byteROL ; *2TAY ; save result high byteBCS LAB_1F45 ; if overflow go do "Out of memory" errorASL Asptl ; shift multiplier low byteROL Aspth ; shift multiplier high byteBCC LAB_1FA8 ; skip add if no carryCLC ; else clear carry for addTXA ; get result low byteADC dims_l ; add dimension size low byteTAX ; save result low byteTYA ; get result high byteADC dims_h ; add dimension size high byteTAY ; save result high byteBCS LAB_1F45 ; if overflow go do "Out of memory" errorLAB_1FA8DEC numbit ; decrement bit countBNE LAB_1F8F ; loop until all doneRTS; perform FRE()LAB_FRELDA Dtypef ; get data type flag, $FF=string, $00=numericBPL LAB_1FB4 ; branch if numericJSR 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; FRE(n) was numeric so do thisLAB_1FB4JSR LAB_GARB ; go do garbage collectionSEC ; set carry for subtractLDA Sstorl ; get bottom of string space low byteSBC Earryl ; subtract array mem end low byteTAY ; copy result to YLDA Sstorh ; get bottom of string space high byteSBC Earryh ; subtract array mem end high byte; save and convert integer AY to FAC1LAB_AYFCLSR Dtypef ; clear data type flag, $FF=string, $00=numericSTA FAC1_1 ; save FAC1 mantissa1STY FAC1_2 ; save FAC1 mantissa2LDX #$90 ; set exponent=2^16 (integer)JMP LAB_27E3 ; set exp=X, clear FAC1_3, normalise and return; perform POS()LAB_POSLDY TPos ; get terminal position; convert Y to byte in FAC1LAB_1FD0LDA #$00 ; clear high byteBEQ LAB_AYFC ; always save and convert integer AY to FAC1 and return; check not Direct (used by DEF and INPUT)LAB_CKRNLDX Clineh ; get current line high byteINX ; increment itBNE LAB_1F7B ; return if can continue not direct mode; else do illegal direct errorLAB_1FD9LDX #$16 ; error code $16 ("Illegal direct" error)LAB_1FDBJMP LAB_XERR ; go do error #X, then warm start; perform DEFLAB_DEFJSR LAB_200B ; check FNx syntaxSTA func_l ; save function pointer low byteSTY func_h ; save function pointer high byteJSR LAB_CKRN ; check not Direct (back here if ok)JSR LAB_1BFE ; scan for "(" , else do syntax error then warm startLDA #$80 ; set flag for FNxSTA Sufnxf ; save subscript/FNx flagJSR LAB_GVAR ; get (var) addressJSR LAB_CTNM ; check if source is numeric, else do type mismatchJSR LAB_1BFB ; scan for ")" , else do syntax error then warm startLDA #TK_EQUAL ; get = tokenJSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm startLDA Cvarah ; get current var address high bytePHA ; push itLDA Cvaral ; get current var address low bytePHA ; push itLDA Bpntrh ; get BASIC execute pointer high bytePHA ; push itLDA Bpntrl ; get BASIC execute pointer low bytePHA ; push itJSR LAB_DATA ; go perform DATAJMP LAB_207A ; put execute pointer and variable pointer into function; and return; check FNx syntaxLAB_200BLDA #TK_FN ; get FN" tokenJSR LAB_SCCA ; scan for CHR$(A) , else do syntax error then warm start; return character after AORA #$80 ; set FN flag bitSTA Sufnxf ; save FN flag so array variable test failsJSR LAB_1D12 ; search for FN variableJMP LAB_CTNM ; check if source is numeric and return, else do type; mismatch; Evaluate FNxLAB_201EJSR LAB_200B ; check FNx syntaxPHA ; push function pointer low byteTYA ; copy function pointer high bytePHA ; push function pointer high byteJSR LAB_1BFE ; scan for "(", else do syntax error then warm startJSR LAB_EVEX ; evaluate expressionJSR LAB_1BFB ; scan for ")", else do syntax error then warm startJSR LAB_CTNM ; check if source is numeric, else do type mismatchPLA ; pop function pointer high byteSTA func_h ; restore itPLA ; pop function pointer low byteSTA func_l ; restore itLDX #$20 ; error code $20 ("Undefined function" error)LDY #$03 ; index to variable pointer high byteLDA (func_l),Y ; get variable pointer high byteBEQ LAB_1FDB ; if zero go do undefined function errorSTA Cvarah ; save variable address high byteDEY ; index to variable address low byteLDA (func_l),Y ; get variable address low byteSTA Cvaral ; save variable address low byteTAX ; copy address low byte; now stack the function variable value before useINY ; index to mantissa_3LAB_2043LDA (Cvaral),Y ; get byte from variablePHA ; stack itDEY ; decrement indexBPL LAB_2043 ; loop until variable stackedLDY Cvarah ; get variable address high byteJSR LAB_2778 ; pack FAC1 (function expression value) into (XY); (function variable), return Y=0, alwaysLDA Bpntrh ; get BASIC execute pointer high bytePHA ; push itLDA Bpntrl ; get BASIC execute pointer low bytePHA ; push itLDA (func_l),Y ; get function execute pointer low byteSTA Bpntrl ; save as BASIC execute pointer low byteINY ; index to high byteLDA (func_l),Y ; get function execute pointer high byteSTA Bpntrh ; save as BASIC execute pointer high byteLDA Cvarah ; get variable address high bytePHA ; push itLDA Cvaral ; get variable address low bytePHA ; push itJSR LAB_EVNM ; evaluate expression and check is numeric,; else do type mismatchPLA ; pull variable address low byteSTA func_l ; save variable address low bytePLA ; pull variable address high byteSTA func_h ; save variable address high byteJSR LAB_GBYT ; scan memoryBEQ LAB_2074 ; branch if null (should be [EOL] marker)JMP LAB_SNER ; else syntax error then warm start; restore Bpntrl,Bpntrh and function variable from stackLAB_2074PLA ; pull BASIC execute pointer low byteSTA Bpntrl ; restore BASIC execute pointer low bytePLA ; pull BASIC execute pointer high byteSTA Bpntrh ; restore BASIC execute pointer high byte; put execute pointer and variable pointer into functionLAB_207ALDY #$00 ; clear indexPLA ; pull BASIC execute pointer low byteSTA (func_l),Y ; save to functionINY ; increment indexPLA ; pull BASIC execute pointer high byteSTA (func_l),Y ; save to functionINY ; increment indexPLA ; pull current var address low byteSTA (func_l),Y ; save to functionINY ; increment indexPLA ; pull current var address high byteSTA (func_l),Y ; save to functionRTS; perform STR$()LAB_STRSJSR LAB_CTNM ; check if source is numeric, else do type mismatchJSR LAB_296E ; convert FAC1 to stringLDA #<Decssp1 ; set result string low pointerLDY #>Decssp1 ; set result string high pointerBEQ LAB_20AE ; print null terminated string to Sutill/Sutilh; Do string vector; copy des_pl/h to des_2l/h and make string space A bytes longLAB_209CLDX des_pl ; get descriptor pointer low byteLDY des_ph ; get descriptor pointer high byteSTX des_2l ; save descriptor pointer low byteSTY des_2h ; save descriptor pointer high byte; make string space A bytes long; A=length, X=Sutill=ptr low byte, Y=Sutilh=ptr high byteLAB_MSSPJSR LAB_2115 ; make space in string memory for string A long; return X=Sutill=ptr low byte, Y=Sutilh=ptr high byteSTX str_pl ; save string pointer low byteSTY str_ph ; save string pointer high byteSTA str_ln ; save lengthRTS; Scan, set up string; print " terminated string to Sutill/SutilhLAB_20AELDX #$22 ; set terminator to "STX Srchc ; set search character (terminator 1)STX Asrch ; set terminator 2; print [Srchc] or [Asrch] terminated string to Sutill/Sutilh; source is AYLAB_20B4STA ssptr_l ; store string start low byteSTY ssptr_h ; store string start high byteSTA str_pl ; save string pointer low byteSTY str_ph ; save string pointer high byteLDY #$FF ; set length to -1LAB_20BEINY ; increment lengthLDA (ssptr_l),Y ; get byte from stringBEQ LAB_20CF ; exit loop if null byte [EOS]CMP Srchc ; compare with search character (terminator 1)BEQ LAB_20CB ; branch if terminatorCMP Asrch ; compare with terminator 2BNE LAB_20BE ; loop if not terminator 2LAB_20CBCMP #$22 ; compare with "BEQ LAB_20D0 ; branch if " (carry set if = !)LAB_20CFCLC ; clear carry for add (only if [EOL] terminated string)LAB_20D0STY str_ln ; save length in FAC1 exponentTYA ; copy length to AADC ssptr_l ; add string start low byteSTA Sendl ; save string end low byteLDX ssptr_h ; get string start high byteBCC LAB_20DC ; branch if no low byte overflowINX ; else increment high byteLAB_20DCSTX Sendh ; save string end high byteLDA ssptr_h ; get string start high byteCMP #>Ram_base ; compare with start of program memoryBCS LAB_RTST ; branch if not in utility area; string in utility area, move to string memoryTYA ; copy length to AJSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes; longLDX ssptr_l ; get string start low byteLDY ssptr_h ; get string start high byteJSR LAB_2298 ; store string A bytes long from XY to (Sutill); check for space on descriptor stack then ..; put string address and length on descriptor stack and update stack pointersLAB_RTSTLDX next_s ; get string stack pointerCPX #des_sk+$09 ; compare with max+1BNE LAB_20F8 ; branch if space on string stack; else do string too complex errorLDX #$1C ; error code $1C ("String too complex" error)LAB_20F5JMP LAB_XERR ; do error #X, then warm start; put string address and length on descriptor stack and update stack pointersLAB_20F8LDA str_ln ; get string lengthSTA PLUS_0,X ; put on string stackLDA str_pl ; get string pointer low byteSTA PLUS_1,X ; put on string stackLDA str_ph ; get string pointer high byteSTA PLUS_2,X ; put on string stackLDY #$00 ; clear YSTX des_pl ; save string descriptor pointer low byteSTY des_ph ; save string descriptor pointer high byte (always $00)DEY ; Y = $FFSTY Dtypef ; save data type flag, $FF=stringSTX last_sl ; save old stack pointer (current top item)INX ; update stack pointerINX ; update stack pointerINX ; update stack pointerSTX next_s ; save new top item valueRTS; Build descriptor; make space in string memory for string A long; return X=Sutill=ptr low byte, Y=Sutill=ptr high byteLAB_2115LSR Gclctd ; clear garbage collected flag (b7); make space for string A longLAB_2117PHA ; save string lengthEOR #$FF ; complement itSEC ; set carry for subtract (twos comp add)ADC Sstorl ; add bottom of string space low byte (subtract length)LDY Sstorh ; get bottom of string space high byteBCS LAB_2122 ; skip decrement if no underflowDEY ; decrement bottom of string space high byteLAB_2122CPY Earryh ; compare with array mem end high byteBCC LAB_2137 ; do out of memory error if lessBNE LAB_212C ; if not = skip next testCMP Earryl ; compare with array mem end low byteBCC LAB_2137 ; do out of memory error if lessLAB_212CSTA Sstorl ; save bottom of string space low byteSTY Sstorh ; save bottom of string space high byteSTA Sutill ; save string utility ptr low byteSTY Sutilh ; save string utility ptr high byteTAX ; copy low byte to XPLA ; get string length backRTSLAB_2137LDX #$0C ; error code $0C ("Out of memory" error)LDA Gclctd ; get garbage collected flagBMI LAB_20F5 ; if set then do error code XJSR LAB_GARB ; else go do garbage collectionLDA #$80 ; flag for garbage collectedSTA Gclctd ; set garbage collected flagPLA ; pull lengthBNE LAB_2117 ; go try again (loop always, length should never be = $00); garbage collection routineLAB_GARBLDX Ememl ; get end of mem low byteLDA Ememh ; get end of mem high byte; re-run routine from last endingLAB_214BSTX Sstorl ; set string storage low byteSTA Sstorh ; set string storage high byteLDY #$00 ; clear indexSTY garb_h ; clear working pointer high byte (flag no strings to move)LDA Earryl ; get array mem end low byteLDX Earryh ; get array mem end high byteSTA Histrl ; save as highest string low byteSTX Histrh ; save as highest string high byteLDA #des_sk ; set descriptor stack pointerSTA ut1_pl ; save descriptor stack pointer low byteSTY ut1_ph ; save descriptor stack pointer high byte ($00)LAB_2161CMP next_s ; compare with descriptor stack pointerBEQ LAB_216A ; branch if =JSR LAB_21D7 ; go garbage collect descriptor stackBEQ LAB_2161 ; loop always; done stacked strings, now do string varsLAB_216AASL g_step ; set step size = $06LDA Svarl ; get start of vars low byteLDX Svarh ; get start of vars high byteSTA ut1_pl ; save as pointer low byteSTX ut1_ph ; save as pointer high byteLAB_2176CPX Sarryh ; compare start of arrays high byteBNE LAB_217E ; branch if no high byte matchCMP Sarryl ; else compare start of arrays low byteBEQ LAB_2183 ; branch if = var mem endLAB_217EJSR LAB_21D1 ; go garbage collect stringsBEQ LAB_2176 ; loop always; done string vars, now do string arraysLAB_2183STA Nbendl ; save start of arrays low byte as working pointerSTX Nbendh ; save start of arrays high byte as working pointerLDA #$04 ; set step sizeSTA g_step ; save step sizeLAB_218BLDA Nbendl ; get pointer low byteLDX Nbendh ; get pointer high byteLAB_218FCPX Earryh ; compare with array mem end high byteBNE LAB_219A ; branch if not at endCMP Earryl ; else compare with array mem end low byteBEQ LAB_2216 ; tidy up and exit if at endLAB_219ASTA ut1_pl ; save pointer low byteSTX ut1_ph ; save pointer high byteLDY #$02 ; set indexLDA (ut1_pl),Y ; get array size low byteADC Nbendl ; add start of this array low byteSTA Nbendl ; save start of next array low byteINY ; increment indexLDA (ut1_pl),Y ; get array size high byteADC Nbendh ; add start of this array high byteSTA Nbendh ; save start of next array high byteLDY #$01 ; set indexLDA (ut1_pl),Y ; get name second byteBPL LAB_218B ; skip if not string array; was string array so ..LDY #$04 ; set indexLDA (ut1_pl),Y ; get # of dimensionsASL ; *2ADC #$05 ; +5 (array header size)JSR LAB_2208 ; go set up for first elementLAB_21C4CPX Nbendh ; compare with start of next array high byteBNE LAB_21CC ; branch if <> (go do this array)CMP Nbendl ; else compare element pointer low byte with next array; low byteBEQ LAB_218F ; if equal then go do next arrayLAB_21CCJSR LAB_21D7 ; go defrag array stringsBEQ LAB_21C4 ; go do next array string (loop always); defrag string variables; enter with XA = variable pointer; return with XA = next variable pointerLAB_21D1INY ; increment index (Y was $00)LDA (ut1_pl),Y ; get var name byte 2BPL LAB_2206 ; if not string, step pointer to next var and returnINY ; else increment indexLAB_21D7LDA (ut1_pl),Y ; get string lengthBEQ LAB_2206 ; if null, step pointer to next string and returnINY ; else increment indexLDA (ut1_pl),Y ; get string pointer low byteTAX ; copy to XINY ; increment indexLDA (ut1_pl),Y ; get string pointer high byteCMP Sstorh ; compare bottom of string space high byteBCC LAB_21EC ; branch if lessBNE LAB_2206 ; if greater, step pointer to next string and return; high bytes were = so compare low bytesCPX Sstorl ; compare bottom of string space low byteBCS LAB_2206 ; if >=, step pointer to next string and return; string pointer is < string storage pointer (pos in mem)LAB_21ECCMP Histrh ; compare to highest string high byteBCC LAB_2207 ; if <, step pointer to next string and returnBNE LAB_21F6 ; if > update pointers, step to next and return; high bytes were = so compare low bytesCPX Histrl ; compare to highest string low byteBCC LAB_2207 ; if <, step pointer to next string and return; string is in string memory spaceLAB_21F6STX Histrl ; save as new highest string low byteSTA Histrh ; save as new highest string high byteLDA ut1_pl ; get start of vars(descriptors) low byteLDX ut1_ph ; get start of vars(descriptors) high byteSTA garb_l ; save as working pointer low byteSTX garb_h ; save as working pointer high byteDEY ; decrement index DIFFERSDEY ; decrement index (should point to descriptor start)STY g_indx ; save index pointer; step pointer to next stringLAB_2206CLC ; clear carry for addLAB_2207LDA g_step ; get step sizeLAB_2208ADC ut1_pl ; add pointer low byteSTA ut1_pl ; save pointer low byteBCC LAB_2211 ; branch if no overflowINC ut1_ph ; else increment high byteLAB_2211LDX ut1_ph ; get pointer high byteLDY #$00 ; clear YRTS; search complete, now either exit or set-up and move stringLAB_2216DEC g_step ; decrement step size (now $03 for descriptor stack)LDX garb_h ; get string to move high byteBEQ LAB_2211 ; exit if nothing to moveLDY g_indx ; get index byte back (points to descriptor)CLC ; clear carry for addLDA (garb_l),Y ; get string lengthADC Histrl ; add highest string low byteSTA Obendl ; save old block end low pointerLDA Histrh ; get highest string high byteADC #$00 ; add any carrySTA Obendh ; save old block end high byteLDA Sstorl ; get bottom of string space low byteLDX Sstorh ; get bottom of string space high byteSTA Nbendl ; save new block end low byteSTX Nbendh ; save new block end high byteJSR LAB_11D6 ; open up space in memory, don't set array endLDY g_indx ; get index byteINY ; point to descriptor low byteLDA Nbendl ; get string pointer low byteSTA (garb_l),Y ; save new string pointer low byteTAX ; copy string pointer low byteINC Nbendh ; correct high byte (move sets high byte -1)LDA Nbendh ; get new string pointer high byteINY ; point to descriptor high byteSTA (garb_l),Y ; save new string pointer high byteJMP LAB_214B ; re-run routine from last ending; (but don't collect this string); concatenate; add strings, string 1 is in descriptor des_pl, string 2 is in lineLAB_224DLDA des_ph ; get descriptor pointer high bytePHA ; put on stackLDA des_pl ; get descriptor pointer low bytePHA ; put on stackJSR LAB_GVAL ; get value from lineJSR LAB_CTST ; check if source is string, else do type mismatchPLA ; get descriptor pointer low byte backSTA ssptr_l ; set pointer low bytePLA ; get descriptor pointer high byte backSTA ssptr_h ; set pointer high byteLDY #$00 ; clear indexLDA (ssptr_l),Y ; get length_1 from descriptorCLC ; clear carry for addADC (des_pl),Y ; add length_2BCC LAB_226D ; branch if no overflowLDX #$1A ; else set error code $1A ("String too long" error)JMP LAB_XERR ; do error #X, then warm startLAB_226DJSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes; longJSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill)LDA des_2l ; get descriptor pointer low byteLDY des_2h ; get descriptor pointer high byteJSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space; returns with A = length, ut1_pl = pointer low byte,; ut1_ph = pointer high byteJSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill)LDA ssptr_l ;.set descriptor pointer low byteLDY ssptr_h ;.set descriptor pointer high byteJSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space; returns with A = length, X=ut1_pl=pointer low byte,; Y=ut1_ph=pointer high byteJSR LAB_RTST ; check for space on descriptor stack then put string; address and length on descriptor stack and update stack; pointersJMP LAB_1ADB ;.continue evaluation; copy string from descriptor (sdescr) to (Sutill)LAB_228ALDY #$00 ; clear indexLDA (sdescr),Y ; get string lengthPHA ; save on stackINY ; increment indexLDA (sdescr),Y ; get source string pointer low byteTAX ; copy to XINY ; increment indexLDA (sdescr),Y ; get source string pointer high byteTAY ; copy to YPLA ; get length back; store string A bytes long from YX to (Sutill)LAB_2298STX ut1_pl ; save source string pointer low byteSTY ut1_ph ; save source string pointer high byte; store string A bytes long from (ut1_pl) to (Sutill)LAB_229CTAX ; copy length to index (don't count with Y)BEQ LAB_22B2 ; branch if = $0 (null string) no need to add zero lengthLDY #$00 ; zero pointer (copy forward)LAB_22A0LDA (ut1_pl),Y ; get source byteSTA (Sutill),Y ; save destination byteINY ; increment indexDEX ; decrement counterBNE LAB_22A0 ; loop while <> 0TYA ; restore length from YLAB_22A9CLC ; clear carry for addADC Sutill ; add string utility ptr low byteSTA Sutill ; save string utility ptr low byteBCC LAB_22B2 ; branch if no carryINC Sutilh ; else increment string utility ptr high byteLAB_22B2RTS; evaluate stringLAB_EVSTJSR LAB_CTST ; check if source is string, else do type mismatch; pop string off descriptor stack, or from top of string space; returns with A = length, X=pointer low byte, Y=pointer high byteLAB_22B6LDA des_pl ; get descriptor pointer low byteLDY des_ph ; get descriptor pointer high byte; pop (YA) descriptor off stack or from top of string space; returns with A = length, X=ut1_pl=pointer low byte, Y=ut1_ph=pointer high byteLAB_22BASTA ut1_pl ; save descriptor pointer low byteSTY ut1_ph ; save descriptor pointer high byteJSR LAB_22EB ; clean descriptor stack, YA = pointerPHP ; save status flagsLDY #$00 ; clear indexLDA (ut1_pl),Y ; get length from string descriptorPHA ; put on stackINY ; increment indexLDA (ut1_pl),Y ; get string pointer low byte from descriptorTAX ; copy to XINY ; increment indexLDA (ut1_pl),Y ; get string pointer high byte from descriptorTAY ; copy to YPLA ; get string length backPLP ; restore statusBNE LAB_22E6 ; branch if pointer <> last_sl,last_shCPY Sstorh ; compare bottom of string space high byteBNE LAB_22E6 ; branch if <>CPX Sstorl ; else compare bottom of string space low byteBNE LAB_22E6 ; branch if <>PHA ; save string lengthCLC ; clear carry for addADC Sstorl ; add bottom of string space low byteSTA Sstorl ; save bottom of string space low byteBCC LAB_22E5 ; skip increment if no overflowINC Sstorh ; increment bottom of string space high byteLAB_22E5PLA ; restore string lengthLAB_22E6STX ut1_pl ; save string pointer low byteSTY ut1_ph ; save string pointer high byteRTS; clean descriptor stack, YA = pointer; checks if AY is on the descriptor stack, if so does a stack discardLAB_22EBCPY last_sh ; compare pointer high byteBNE LAB_22FB ; exit if <>CMP last_sl ; compare pointer low byteBNE LAB_22FB ; exit if <>STA next_s ; save descriptor stack pointerSBC #$03 ; -3STA last_sl ; save low byte -3LDY #$00 ; clear high byteLAB_22FBRTS; perform CHR$()LAB_CHRSJSR LAB_EVBY ; evaluate byte expression, result in XTXA ; copy to APHA ; save characterLDA #$01 ; string is single byteJSR LAB_MSSP ; make string space A bytes long A=$AC=length,; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high bytePLA ; get character backLDY #$00 ; clear indexSTA (str_pl),Y ; save byte in string (byte IS string!)JMP LAB_RTST ; check for space on descriptor stack then put string; address and length on descriptor stack and update stack; pointers; perform LEFT$()LAB_LEFTPHA ; push byte parameterJSR LAB_236F ; pull string data and byte parameter from stack; return pointer in des_2l/h, byte in A (and X), Y=0CMP (des_2l),Y ; compare byte parameter with string lengthTYA ; clear ABEQ LAB_2316 ; go do string copy (branch always); perform RIGHT$()LAB_RIGHTPHA ; push byte parameterJSR LAB_236F ; pull string data and byte parameter from stack; return pointer in des_2l/h, byte in A (and X), Y=0CLC ; clear carry for add-1SBC (des_2l),Y ; subtract string lengthEOR #$FF ; invert it (A=LEN(expression$)-l)LAB_2316BCC LAB_231C ; branch if string length > byte parameterLDA (des_2l),Y ; else make parameter = lengthTAX ; copy to byte parameter copyTYA ; clear string start offsetLAB_231CPHA ; save string start offsetLAB_231DTXA ; copy byte parameter (or string length if <)LAB_231EPHA ; save string lengthJSR LAB_MSSP ; make string space A bytes long A=$AC=length,; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byteLDA des_2l ; get descriptor pointer low byteLDY des_2h ; get descriptor pointer high byteJSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space; returns with A = length, X=ut1_pl=pointer low byte,; Y=ut1_ph=pointer high bytePLA ; get string length backTAY ; copy length to YPLA ; get string start offset backCLC ; clear carry for addADC ut1_pl ; add start offset to string start pointer low byteSTA ut1_pl ; save string start pointer low byteBCC LAB_2335 ; branch if no overflowINC ut1_ph ; else increment string start pointer high byteLAB_2335TYA ; copy length to AJSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill)JMP LAB_RTST ; check for space on descriptor stack then put string; address and length on descriptor stack and update stack; pointers; perform MID$()LAB_MIDSPHA ; push byte parameterLDA #$FF ; set default length = 255STA mids_l ; save default lengthJSR LAB_GBYT ; scan memoryCMP #')' ; compare with ")"BEQ LAB_2358 ; branch if = ")" (skip second byte get)JSR LAB_1C01 ; scan for "," , else do syntax error then warm startJSR LAB_GTBY ; get byte parameter (use copy in mids_l)LAB_2358JSR LAB_236F ; pull string data and byte parameter from stack; return pointer in des_2l/h, byte in A (and X), Y=0DEX ; decrement start indexTXA ; copy to APHA ; save string start offsetCLC ; clear carry for sub-1LDX #$00 ; clear output string lengthSBC (des_2l),Y ; subtract string lengthBCS LAB_231D ; if start>string length go do null stringEOR #$FF ; complement -lengthCMP mids_l ; compare byte parameterBCC LAB_231E ; if length>remaining string go do RIGHT$LDA mids_l ; get length byteBCS LAB_231E ; go do string copy (branch always); pull string data and byte parameter from stack; return pointer in des_2l/h, byte in A (and X), Y=0LAB_236FJSR LAB_1BFB ; scan for ")" , else do syntax error then warm startPLA ; pull return address low byte (return address)STA Fnxjpl ; save functions jump vector low bytePLA ; pull return address high byte (return address)STA Fnxjph ; save functions jump vector high bytePLA ; pull byte parameterTAX ; copy byte parameter to XPLA ; pull string pointer low byteSTA des_2l ; save itPLA ; pull string pointer high byteSTA des_2h ; save itLDY #$00 ; clear indexTXA ; copy byte parameterBEQ LAB_23A8 ; if null do function call error then warm startINC Fnxjpl ; increment function jump vector low byte; (JSR pushes return addr-1. this is all very nice; but will go tits up if either call is on a page; boundary!)JMP (Fnxjpl) ; in effect, RTS; perform LCASE$()LAB_LCASEJSR LAB_EVST ; evaluate stringSTA str_ln ; set string lengthTAY ; copy length to YBEQ NoString ; branch if null stringJSR LAB_MSSP ; make string space A bytes long A=length,; X=Sutill=ptr low byte, Y=Sutilh=ptr high byteSTX str_pl ; save string pointer low byteSTY str_ph ; save string pointer high byteTAY ; get string length backLC_loopDEY ; decrement indexLDA (ut1_pl),Y ; get byte from stringJSR LAB_1D82 ; is character "A" to "Z"BCC NoUcase ; branch if not upper case alphaORA #$20 ; convert upper to lower caseNoUcaseSTA (Sutill),Y ; save byte back to stringTYA ; test indexBNE LC_loop ; loop if not all doneBEQ NoString ; tidy up and exit, branch always; perform UCASE$()LAB_UCASEJSR LAB_EVST ; evaluate stringSTA str_ln ; set string lengthTAY ; copy length to YBEQ NoString ; branch if null stringJSR LAB_MSSP ; make string space A bytes long A=length,; X=Sutill=ptr low byte, Y=Sutilh=ptr high byteSTX str_pl ; save string pointer low byteSTY str_ph ; save string pointer high byteTAY ; get string length backUC_loopDEY ; decrement indexLDA (ut1_pl),Y ; get byte from stringJSR LAB_CASC ; is character "a" to "z" (or "A" to "Z")BCC NoLcase ; branch if not alphaAND #$DF ; convert lower to upper caseNoLcaseSTA (Sutill),Y ; save byte back to stringTYA ; test indexBNE UC_loop ; loop if not all doneNoStringJMP LAB_RTST ; check for space on descriptor stack then put string; address and length on descriptor stack and update stack; pointers; perform SADD()LAB_SADDJSR LAB_IGBY ; increment and scan memoryJSR LAB_GVAR ; get var addressJSR LAB_1BFB ; scan for ")", else do syntax error then warm startJSR LAB_CTST ; check if source is string, else do type mismatchLDY #$02 ; index to string pointer high byteLDA (Cvaral),Y ; get string pointer high byteTAX ; copy string pointer high byte to XDEY ; index to string pointer low byteLDA (Cvaral),Y ; get string pointer low byteTAY ; copy string pointer low byte to YTXA ; copy string pointer high byte to AJMP LAB_AYFC ; save and convert integer AY to FAC1 and return; perform LEN()LAB_LENSJSR LAB_ESGL ; evaluate string, get length in A (and Y)JMP LAB_1FD0 ; convert Y to byte in FAC1 and return; evaluate string, get length in YLAB_ESGLJSR LAB_EVST ; evaluate stringTAY ; copy length to YRTS; perform ASC()LAB_ASCJSR LAB_ESGL ; evaluate string, get length in A (and Y)BEQ LAB_23A8 ; if null do function call error then warm startLDY #$00 ; set index to first characterLDA (ut1_pl),Y ; get byteTAY ; copy to YJMP LAB_1FD0 ; convert Y to byte in FAC1 and return; do function call error then warm startLAB_23A8JMP LAB_FCER ; do function call error then warm start; scan and get byte parameterLAB_SGBYJSR LAB_IGBY ; increment and scan memory; get byte parameterLAB_GTBYJSR LAB_EVNM ; evaluate expression and check is numeric,; else do type mismatch; evaluate byte expression, result in XLAB_EVBYJSR LAB_EVPI ; evaluate integer expression (no check)LDY FAC1_2 ; get FAC1 mantissa2BNE LAB_23A8 ; if top byte <> 0 do function call error then warm startLDX FAC1_3 ; get FAC1 mantissa3JMP LAB_GBYT ; scan memory and return; perform VAL()LAB_VALJSR LAB_ESGL ; evaluate string, get length in A (and Y)BNE LAB_23C5 ; branch if not null string; string was null so set result = $00JMP LAB_24F1 ; clear FAC1 exponent and sign and returnLAB_23C5LDX Bpntrl ; get BASIC execute pointer low byteLDY Bpntrh ; get BASIC execute pointer high byteSTX Btmpl ; save BASIC execute pointer low byteSTY Btmph ; save BASIC execute pointer high byteLDX ut1_pl ; get string pointer low byteSTX Bpntrl ; save as BASIC execute pointer low byteCLC ; clear carryADC ut1_pl ; add string lengthSTA ut2_pl ; save string end low byteLDA ut1_ph ; get string pointer high byteSTA Bpntrh ; save as BASIC execute pointer high byteADC #$00 ; add carry to high byteSTA ut2_ph ; save string end high byteLDY #$00 ; set index to $00LDA (ut2_pl),Y ; get string end +1 bytePHA ; push itTYA ; clear ASTA (ut2_pl),Y ; terminate string with $00JSR LAB_GBYT ; scan memoryJSR LAB_2887 ; get FAC1 from stringPLA ; restore string end +1 byteLDY #$00 ; set index to zeroSTA (ut2_pl),Y ; put string end byte back; restore BASIC execute pointer from temp (Btmpl/Btmph)LAB_23F3LDX Btmpl ; get BASIC execute pointer low byte backLDY Btmph ; get BASIC execute pointer high byte backSTX Bpntrl ; save BASIC execute pointer low byteSTY Bpntrh ; save BASIC execute pointer high byteRTS; get two parameters for POKE or WAITLAB_GADBJSR LAB_EVNM ; evaluate expression and check is numeric,; else do type mismatchJSR LAB_F2FX ; save integer part of FAC1 in temporary integer; scan for "," and get byte, else do Syntax error then warm startLAB_SCGBJSR LAB_1C01 ; scan for "," , else do syntax error then warm startLDA Itemph ; save temporary integer high bytePHA ; on stackLDA Itempl ; save temporary integer low bytePHA ; on stackJSR LAB_GTBY ; get byte parameterPLA ; pull low byteSTA Itempl ; restore temporary integer low bytePLA ; pull high byteSTA Itemph ; restore temporary integer high byteRTS; convert float to fixed routine. accepts any value that fits in 24 bits, +ve or; -ve and converts it into a right truncated integer in Itempl and Itemph; save unsigned 16 bit integer part of FAC1 in temporary integerLAB_F2FXLDA FAC1_e ; get FAC1 exponentCMP #$98 ; compare with exponent = 2^24BCS LAB_23A8 ; if >= do function call error then warm startLAB_F2FUJSR LAB_2831 ; convert FAC1 floating-to-fixedLDA FAC1_2 ; get FAC1 mantissa2LDY FAC1_3 ; get FAC1 mantissa3STY Itempl ; save temporary integer low byteSTA Itemph ; save temporary integer high byteRTS; perform PEEK()LAB_PEEKJSR LAB_F2FX ; save integer part of FAC1 in temporary integerLDX #$00 ; clear indexLDA (Itempl,X) ; get byte via temporary integer (addr)TAY ; copy byte to YJMP LAB_1FD0 ; convert Y to byte in FAC1 and return; perform POKELAB_POKEJSR LAB_GADB ; get two parameters for POKE or WAITTXA ; copy byte argument to ALDX #$00 ; clear indexSTA (Itempl,X) ; save byte via temporary integer (addr)RTS; perform DEEK()LAB_DEEKJSR LAB_F2FX ; save integer part of FAC1 in temporary integerLDX #$00 ; clear indexLDA (Itempl,X) ; PEEK low byteTAY ; copy to YINC Itempl ; increment pointer low byteBNE Deekh ; skip high increment if no rolloverINC Itemph ; increment pointer high byteDeekhLDA (Itempl,X) ; PEEK high byteJMP LAB_AYFC ; save and convert integer AY to FAC1 and return; perform DOKELAB_DOKEJSR LAB_EVNM ; evaluate expression and check is numeric,; else do type mismatchJSR LAB_F2FX ; convert floating-to-fixedSTY Frnxtl ; save pointer low byte (float to fixed returns word in AY)STA Frnxth ; save pointer high byteJSR LAB_1C01 ; scan for "," , else do syntax error then warm startJSR LAB_EVNM ; evaluate expression and check is numeric,; else do type mismatchJSR LAB_F2FX ; convert floating-to-fixedTYA ; copy value low byte (float to fixed returns word in AY)LDX #$00 ; clear indexSTA (Frnxtl,X) ; POKE low byteINC Frnxtl ; increment pointer low byteBNE Dokeh ; skip high increment if no rolloverINC Frnxth ; increment pointer high byteDokehLDA Itemph ; get value high byteSTA (Frnxtl,X) ; POKE high byteJMP LAB_GBYT ; scan memory and return; perform SWAPLAB_SWAPJSR LAB_GVAR ; get var1 addressSTA Lvarpl ; save var1 address low byteSTY Lvarph ; save var1 address high byteLDA Dtypef ; get data type flag, $FF=string, $00=numericPHA ; save data type flagJSR LAB_1C01 ; scan for "," , else do syntax error then warm startJSR LAB_GVAR ; get var2 address (pointer in Cvaral/h)PLA ; pull var1 data type flagEOR Dtypef ; compare with var2 data typeBPL SwapErr ; exit if not both the same typeLDY #$03 ; four bytes to swap (either value or descriptor+1)SwapLpLDA (Lvarpl),Y ; get byte from var1TAX ; save var1 byteLDA (Cvaral),Y ; get byte from var2STA (Lvarpl),Y ; save byte to var1TXA ; restore var1 byteSTA (Cvaral),Y ; save byte to var2DEY ; decrement indexBPL SwapLp ; loop until doneRTSSwapErrJMP LAB_1ABC ; do "Type mismatch" error then warm start; perform CALLLAB_CALLJSR LAB_EVNM ; evaluate expression and check is numeric,; else do type mismatchJSR LAB_F2FX ; convert floating-to-fixedLDA #>CallExit ; set return address high bytePHA ; put on stackLDA #<CallExit-1 ; set return address low bytePHA ; put on stackJMP (Itempl) ; do indirect jump to user routine; if the called routine exits correctly then it will return to here. this will then get; the next byte for the interpreter and returnCallExitJMP LAB_GBYT ; scan memory and return; perform WAITLAB_WAITJSR LAB_GADB ; get two parameters for POKE or WAITSTX Frnxtl ; save byteLDX #$00 ; clear maskJSR LAB_GBYT ; scan memoryBEQ LAB_2441 ; skip if no third argumentJSR LAB_SCGB ; scan for "," and get byte, else SN error then warm startLAB_2441STX Frnxth ; save EOR argumentLAB_2445LDA (Itempl),Y ; get byte via temporary integer (addr)EOR Frnxth ; EOR with second argument (mask)AND Frnxtl ; AND with first argument (byte)BEQ LAB_2445 ; loop if result is zeroLAB_244DRTS; perform subtraction, FAC1 from (AY)LAB_2455JSR LAB_264D ; unpack memory (AY) into FAC2; perform subtraction, FAC1 from FAC2LAB_SUBTRACTLDA FAC1_s ; get FAC1 sign (b7)EOR #$FF ; complement itSTA FAC1_s ; save FAC1 sign (b7)EOR FAC2_s ; EOR with FAC2 sign (b7)STA FAC_sc ; save sign compare (FAC1 EOR FAC2)LDA FAC1_e ; get FAC1 exponentJMP LAB_ADD ; go add FAC2 to FAC1; perform additionLAB_2467JSR LAB_257B ; shift FACX A times right (>8 shifts)BCC LAB_24A8 ;.go subtract mantissas; add 0.5 to FAC1LAB_244ELDA #<LAB_2A96 ; set 0.5 pointer low byteLDY #>LAB_2A96 ; set 0.5 pointer high byte; add (AY) to FAC1LAB_246CJSR LAB_264D ; unpack memory (AY) into FAC2; add FAC2 to FAC1LAB_ADDBNE LAB_2474 ; branch if FAC1 was not zero; copy FAC2 to FAC1LAB_279BLDA FAC2_s ; get FAC2 sign (b7); save FAC1 sign and copy ABS(FAC2) to FAC1LAB_279DSTA FAC1_s ; save FAC1 sign (b7)LDX #$04 ; 4 bytes to copyLAB_27A1LDA FAC1_o,X ; get byte from FAC2,XSTA FAC1_e-1,X ; save byte at FAC1,XDEX ; decrement countBNE LAB_27A1 ; loop if not all doneSTX FAC1_r ; clear FAC1 rounding byteRTS; FAC1 is non zeroLAB_2474LDX FAC1_r ; get FAC1 rounding byteSTX FAC2_r ; save as FAC2 rounding byteLDX #FAC2_e ; set index to FAC2 exponent addrLDA FAC2_e ; get FAC2 exponentLAB_247CTAY ; copy exponentBEQ LAB_244D ; exit if zeroSEC ; set carry for subtractSBC FAC1_e ; subtract FAC1 exponentBEQ LAB_24A8 ; branch if = (go add mantissa)BCC LAB_2498 ; branch if <; FAC2>FAC1STY FAC1_e ; save FAC1 exponentLDY FAC2_s ; get FAC2 sign (b7)STY FAC1_s ; save FAC1 sign (b7)EOR #$FF ; complement AADC #$00 ; +1 (twos complement, carry is set)LDY #$00 ; clear YSTY FAC2_r ; clear FAC2 rounding byteLDX #FAC1_e ; set index to FAC1 exponent addrBNE LAB_249C ; branch alwaysLAB_2498LDY #$00 ; clear YSTY FAC1_r ; clear FAC1 rounding byteLAB_249CCMP #$F9 ; compare exponent diff with $F9BMI LAB_2467 ; branch if range $79-$F8TAY ; copy exponent difference to YLDA FAC1_r ; get FAC1 rounding byteLSR PLUS_1,X ; shift FAC? mantissa1JSR LAB_2592 ; shift FACX Y times right; exponents are equal now do mantissa subtractLAB_24A8BIT FAC_sc ; test sign compare (FAC1 EOR FAC2)BPL LAB_24F8 ; if = add FAC2 mantissa to FAC1 mantissa and returnLDY #FAC1_e ; set index to FAC1 exponent addrCPX #FAC2_e ; compare X to FAC2 exponent addrBEQ LAB_24B4 ; branch if =LDY #FAC2_e ; else set index to FAC2 exponent addr; subtract smaller from bigger (take sign of bigger)LAB_24B4SEC ; set carry for subtractEOR #$FF ; ones complement AADC FAC2_r ; add FAC2 rounding byteSTA FAC1_r ; save FAC1 rounding byteLDA PLUS_3,Y ; get FACY mantissa3SBC PLUS_3,X ; subtract FACX mantissa3STA FAC1_3 ; save FAC1 mantissa3LDA PLUS_2,Y ; get FACY mantissa2SBC PLUS_2,X ; subtract FACX mantissa2STA FAC1_2 ; save FAC1 mantissa2LDA PLUS_1,Y ; get FACY mantissa1SBC PLUS_1,X ; subtract FACX mantissa1STA FAC1_1 ; save FAC1 mantissa1; do ABS and normalise FAC1LAB_24D0BCS LAB_24D5 ; branch if number is +veJSR LAB_2537 ; negate FAC1; normalise FAC1LAB_24D5LDY #$00 ; clear YTYA ; clear ACLC ; clear carry for addLAB_24D9LDX FAC1_1 ; get FAC1 mantissa1BNE LAB_251B ; if not zero normalise FAC1LDX FAC1_2 ; get FAC1 mantissa2STX FAC1_1 ; save FAC1 mantissa1LDX FAC1_3 ; get FAC1 mantissa3STX FAC1_2 ; save FAC1 mantissa2LDX FAC1_r ; get FAC1 rounding byteSTX FAC1_3 ; save FAC1 mantissa3STY FAC1_r ; clear FAC1 rounding byteADC #$08 ; add x to exponent offsetCMP #$18 ; compare with $18 (max offset, all bits would be =0)BNE LAB_24D9 ; loop if not max; clear FAC1 exponent and signLAB_24F1LDA #$00 ; clear ALAB_24F3STA FAC1_e ; set FAC1 exponent; save FAC1 signLAB_24F5STA FAC1_s ; save FAC1 sign (b7)RTS; add FAC2 mantissa to FAC1 mantissaLAB_24F8ADC FAC2_r ; add FAC2 rounding byteSTA FAC1_r ; save FAC1 rounding byteLDA FAC1_3 ; get FAC1 mantissa3ADC FAC2_3 ; add FAC2 mantissa3STA FAC1_3 ; save FAC1 mantissa3LDA FAC1_2 ; get FAC1 mantissa2ADC FAC2_2 ; add FAC2 mantissa2STA FAC1_2 ; save FAC1 mantissa2LDA FAC1_1 ; get FAC1 mantissa1ADC FAC2_1 ; add FAC2 mantissa1STA FAC1_1 ; save FAC1 mantissa1BCS LAB_252A ; if carry then normalise FAC1 for C=1RTS ; else just exitLAB_2511ADC #$01 ; add 1 to exponent offsetASL FAC1_r ; shift FAC1 rounding byteROL FAC1_3 ; shift FAC1 mantissa3ROL FAC1_2 ; shift FAC1 mantissa2ROL FAC1_1 ; shift FAC1 mantissa1; normalise FAC1LAB_251BBPL LAB_2511 ; loop if not normalisedSEC ; set carry for subtractSBC FAC1_e ; subtract FAC1 exponentBCS LAB_24F1 ; branch if underflow (set result = $0)EOR #$FF ; complement exponentADC #$01 ; +1 (twos complement)STA FAC1_e ; save FAC1 exponent; test and normalise FAC1 for C=0/1LAB_2528BCC LAB_2536 ; exit if no overflow; normalise FAC1 for C=1LAB_252AINC FAC1_e ; increment FAC1 exponentBEQ LAB_2564 ; if zero do overflow error and warm startROR FAC1_1 ; shift FAC1 mantissa1ROR FAC1_2 ; shift FAC1 mantissa2ROR FAC1_3 ; shift FAC1 mantissa3ROR FAC1_r ; shift FAC1 rounding byteLAB_2536RTS; negate FAC1LAB_2537LDA FAC1_s ; get FAC1 sign (b7)EOR #$FF ; complement itSTA FAC1_s ; save FAC1 sign (b7); twos complement FAC1 mantissaLAB_253DLDA FAC1_1 ; get FAC1 mantissa1EOR #$FF ; complement itSTA FAC1_1 ; save FAC1 mantissa1LDA FAC1_2 ; get FAC1 mantissa2EOR #$FF ; complement itSTA FAC1_2 ; save FAC1 mantissa2LDA FAC1_3 ; get FAC1 mantissa3EOR #$FF ; complement itSTA FAC1_3 ; save FAC1 mantissa3LDA FAC1_r ; get FAC1 rounding byteEOR #$FF ; complement itSTA FAC1_r ; save FAC1 rounding byteINC FAC1_r ; increment FAC1 rounding byteBNE LAB_2563 ; exit if no overflow; increment FAC1 mantissaLAB_2559INC FAC1_3 ; increment FAC1 mantissa3BNE LAB_2563 ; finished if no rolloverINC FAC1_2 ; increment FAC1 mantissa2BNE LAB_2563 ; finished if no rolloverINC FAC1_1 ; increment FAC1 mantissa1LAB_2563RTS; do overflow error (overflow exit)LAB_2564LDX #$0A ; error code $0A ("Overflow" error)JMP LAB_XERR ; do error #X, then warm start; shift FCAtemp << A+8 timesLAB_2569LDX #FACt_1-1 ; set offset to FACtempLAB_256BLDY PLUS_3,X ; get FACX mantissa3STY FAC1_r ; save as FAC1 rounding byteLDY PLUS_2,X ; get FACX mantissa2STY PLUS_3,X ; save FACX mantissa3LDY PLUS_1,X ; get FACX mantissa1STY PLUS_2,X ; save FACX mantissa2LDY FAC1_o ; get FAC1 overflow byteSTY PLUS_1,X ; save FACX mantissa1; shift FACX -A times right (> 8 shifts)LAB_257BADC #$08 ; add 8 to shift countBMI LAB_256B ; go do 8 shift if still -veBEQ LAB_256B ; go do 8 shift if zeroSBC #$08 ; else subtract 8 againTAY ; save count to YLDA FAC1_r ; get FAC1 rounding byteBCS LAB_259A ;.LAB_2588ASL PLUS_1,X ; shift FACX mantissa1BCC LAB_258E ; branch if +veINC PLUS_1,X ; this sets b7 eventuallyLAB_258EROR PLUS_1,X ; shift FACX mantissa1 (correct for ASL)ROR PLUS_1,X ; shift FACX mantissa1 (put carry in b7); shift FACX Y times rightLAB_2592ROR PLUS_2,X ; shift FACX mantissa2ROR PLUS_3,X ; shift FACX mantissa3ROR ; shift FACX rounding byteINY ; increment exponent diffBNE LAB_2588 ; branch if range adjust not completeLAB_259ACLC ; just clear itRTS; perform LOG()LAB_LOGJSR LAB_27CA ; test sign and zeroBEQ LAB_25C4 ; if zero do function call error then warm startBPL LAB_25C7 ; skip error if +veLAB_25C4JMP LAB_FCER ; do function call error then warm start (-ve)LAB_25C7LDA FAC1_e ; get FAC1 exponentSBC #$7F ; normalise itPHA ; save itLDA #$80 ; set exponent to zeroSTA FAC1_e ; save FAC1 exponentLDA #<LAB_25AD ; set 1/root2 pointer low byteLDY #>LAB_25AD ; set 1/root2 pointer high byteJSR LAB_246C ; add (AY) to FAC1 (1/root2)LDA #<LAB_25B1 ; set root2 pointer low byteLDY #>LAB_25B1 ; set root2 pointer high byteJSR LAB_26CA ; convert AY and do (AY)/FAC1 (root2/(x+(1/root2)))LDA #<LAB_259C ; set 1 pointer low byteLDY #>LAB_259C ; set 1 pointer high byteJSR LAB_2455 ; subtract (AY) from FAC1 ((root2/(x+(1/root2)))-1)LDA #<LAB_25A0 ; set pointer low byte to counterLDY #>LAB_25A0 ; set pointer high byte to counterJSR LAB_2B6E ; ^2 then series evaluationLDA #<LAB_25B5 ; set -0.5 pointer low byteLDY #>LAB_25B5 ; set -0.5 pointer high byteJSR LAB_246C ; add (AY) to FAC1PLA ; restore FAC1 exponentJSR LAB_2912 ; evaluate new ASCII digitLDA #<LAB_25B9 ; set LOG(2) pointer low byteLDY #>LAB_25B9 ; set LOG(2) pointer high byte; do convert AY, FCA1*(AY)LAB_25FBJSR LAB_264D ; unpack memory (AY) into FAC2LAB_MULTIPLYBEQ LAB_264C ; exit if zeroJSR LAB_2673 ; test and adjust accumulatorsLDA #$00 ; clear ASTA FACt_1 ; clear temp mantissa1STA FACt_2 ; clear temp mantissa2STA FACt_3 ; clear temp mantissa3LDA FAC1_r ; get FAC1 rounding byteJSR LAB_2622 ; go do shift/add FAC2LDA FAC1_3 ; get FAC1 mantissa3JSR LAB_2622 ; go do shift/add FAC2LDA FAC1_2 ; get FAC1 mantissa2JSR LAB_2622 ; go do shift/add FAC2LDA FAC1_1 ; get FAC1 mantissa1JSR LAB_2627 ; go do shift/add FAC2JMP LAB_273C ; copy temp to FAC1, normalise and returnLAB_2622BNE LAB_2627 ; branch if byte <> zeroJMP LAB_2569 ; shift FCAtemp << A+8 times; else do shift and addLAB_2627LSR ; shift byteORA #$80 ; set top bit (mark for 8 times)LAB_262ATAY ; copy resultBCC LAB_2640 ; skip next if bit was zeroCLC ; clear carry for addLDA FACt_3 ; get temp mantissa3ADC FAC2_3 ; add FAC2 mantissa3STA FACt_3 ; save temp mantissa3LDA FACt_2 ; get temp mantissa2ADC FAC2_2 ; add FAC2 mantissa2STA FACt_2 ; save temp mantissa2LDA FACt_1 ; get temp mantissa1ADC FAC2_1 ; add FAC2 mantissa1STA FACt_1 ; save temp mantissa1LAB_2640ROR FACt_1 ; shift temp mantissa1ROR FACt_2 ; shift temp mantissa2ROR FACt_3 ; shift temp mantissa3ROR FAC1_r ; shift temp rounding byteTYA ; get byte backLSR ; shift byteBNE LAB_262A ; loop if all bits not doneLAB_264CRTS; unpack memory (AY) into FAC2LAB_264DSTA ut1_pl ; save pointer low byteSTY ut1_ph ; save pointer high byteLDY #$03 ; 4 bytes to get (0-3)LDA (ut1_pl),Y ; get mantissa3STA FAC2_3 ; save FAC2 mantissa3DEY ; decrement indexLDA (ut1_pl),Y ; get mantissa2STA FAC2_2 ; save FAC2 mantissa2DEY ; decrement indexLDA (ut1_pl),Y ; get mantissa1+signSTA FAC2_s ; save FAC2 sign (b7)EOR FAC1_s ; EOR with FAC1 sign (b7)STA FAC_sc ; save sign compare (FAC1 EOR FAC2)LDA FAC2_s ; recover FAC2 sign (b7)ORA #$80 ; set 1xxx xxx (set normal bit)STA FAC2_1 ; save FAC2 mantissa1DEY ; decrement indexLDA (ut1_pl),Y ; get exponent byteSTA FAC2_e ; save FAC2 exponentLDA FAC1_e ; get FAC1 exponentRTS; test and adjust accumulatorsLAB_2673LDA FAC2_e ; get FAC2 exponentLAB_2675BEQ LAB_2696 ; branch if FAC2 = $00 (handle underflow)CLC ; clear carry for addADC FAC1_e ; add FAC1 exponentBCC LAB_2680 ; branch if sum of exponents <$0100BMI LAB_269B ; do overflow errorCLC ; clear carry for the add.byte $2C ; makes next line BIT $1410LAB_2680BPL LAB_2696 ; if +ve go handle underflowADC #$80 ; adjust exponentSTA FAC1_e ; save FAC1 exponentBNE LAB_268B ; branch if not zeroJMP LAB_24F5 ; save FAC1 sign and returnLAB_268BLDA FAC_sc ; get sign compare (FAC1 EOR FAC2)STA FAC1_s ; save FAC1 sign (b7)LAB_268FRTS; handle overflow and underflowLAB_2690LDA FAC1_s ; get FAC1 sign (b7)BPL LAB_269B ; do overflow error; handle underflowLAB_2696PLA ; pop return address low bytePLA ; pop return address high byteJMP LAB_24F1 ; clear FAC1 exponent and sign and return; multiply by 10LAB_269EJSR LAB_27AB ; round and copy FAC1 to FAC2TAX ; copy exponent (set the flags)BEQ LAB_268F ; exit if zeroCLC ; clear carry for addADC #$02 ; add two to exponent (*4)BCS LAB_269B ; do overflow error if > $FFLDX #$00 ; clear byteSTX FAC_sc ; clear sign compare (FAC1 EOR FAC2)JSR LAB_247C ; add FAC2 to FAC1 (*5)INC FAC1_e ; increment FAC1 exponent (*10)BNE LAB_268F ; if non zero just do RTSLAB_269BJMP LAB_2564 ; do overflow error and warm start; divide by 10LAB_26B9JSR LAB_27AB ; round and copy FAC1 to FAC2LDA #<LAB_26B5 ; set pointer to 10d low addrLDY #>LAB_26B5 ; set pointer to 10d high addrLDX #$00 ; clear sign; divide by (AY) (X=sign)LAB_26C2STX FAC_sc ; save sign compare (FAC1 EOR FAC2)JSR LAB_UFAC ; unpack memory (AY) into FAC1JMP LAB_DIVIDE ; do FAC2/FAC1; Perform divide-by; convert AY and do (AY)/FAC1LAB_26CAJSR LAB_264D ; unpack memory (AY) into FAC2; Perform divide-intoLAB_DIVIDEBEQ LAB_2737 ; if zero go do /0 errorJSR LAB_27BA ; round FAC1LDA #$00 ; clear ASEC ; set carry for subtractSBC FAC1_e ; subtract FAC1 exponent (2s complement)STA FAC1_e ; save FAC1 exponentJSR LAB_2673 ; test and adjust accumulatorsINC FAC1_e ; increment FAC1 exponentBEQ LAB_269B ; if zero do overflow errorLDX #$FF ; set index for pre incrementLDA #$01 ; set bit to flag byte saveLAB_26E4LDY FAC2_1 ; get FAC2 mantissa1CPY FAC1_1 ; compare FAC1 mantissa1BNE LAB_26F4 ; branch if <>LDY FAC2_2 ; get FAC2 mantissa2CPY FAC1_2 ; compare FAC1 mantissa2BNE LAB_26F4 ; branch if <>LDY FAC2_3 ; get FAC2 mantissa3CPY FAC1_3 ; compare FAC1 mantissa3LAB_26F4PHP ; save FAC2-FAC1 compare statusROL ; shift the result byteBCC LAB_2702 ; if no carry skip the byte saveLDY #$01 ; set bit to flag byte saveINX ; else increment the index to FACtCPX #$02 ; compare with the index to FACt_3BMI LAB_2701 ; if not last byte just go save itBNE LAB_272B ; if all done go save FAC1 rounding byte, normalise and; returnLDY #$40 ; set bit to flag byte save for the rounding byteLAB_2701STA FACt_1,X ; write result byte to FACt_1 + indexTYA ; copy the next save byte flagLAB_2702PLP ; restore FAC2-FAC1 compare statusBCC LAB_2704 ; if FAC2 < FAC1 then skip the subtractTAY ; save FAC2-FAC1 compare statusLDA FAC2_3 ; get FAC2 mantissa3SBC FAC1_3 ; subtract FAC1 mantissa3STA FAC2_3 ; save FAC2 mantissa3LDA FAC2_2 ; get FAC2 mantissa2SBC FAC1_2 ; subtract FAC1 mantissa2STA FAC2_2 ; save FAC2 mantissa2LDA FAC2_1 ; get FAC2 mantissa1SBC FAC1_1 ; subtract FAC1 mantissa1STA FAC2_1 ; save FAC2 mantissa1TYA ; restore FAC2-FAC1 compare status; FAC2 = FAC2*2LAB_2704ASL FAC2_3 ; shift FAC2 mantissa3ROL FAC2_2 ; shift FAC2 mantissa2ROL FAC2_1 ; shift FAC2 mantissa1BCS LAB_26F4 ; loop with no compareBMI LAB_26E4 ; loop with compareBPL LAB_26F4 ; loop always with no compare; do A<<6, save as FAC1 rounding byte, normalise and returnLAB_272BLSR ; shift b1 - b0 ..ROR ; ..ROR ; .. to b7 - b6STA FAC1_r ; save FAC1 rounding bytePLP ; dump FAC2-FAC1 compare statusJMP LAB_273C ; copy temp to FAC1, normalise and return; do "Divide by zero" errorLAB_2737LDX #$14 ; error code $14 ("Divide by zero" error)JMP LAB_XERR ; do error #X, then warm start; copy temp to FAC1 and normaliseLAB_273CLDA FACt_1 ; get temp mantissa1STA FAC1_1 ; save FAC1 mantissa1LDA FACt_2 ; get temp mantissa2STA FAC1_2 ; save FAC1 mantissa2LDA FACt_3 ; get temp mantissa3STA FAC1_3 ; save FAC1 mantissa3JMP LAB_24D5 ; normalise FAC1 and return; unpack memory (AY) into FAC1LAB_UFACSTA ut1_pl ; save pointer low byteSTY ut1_ph ; save pointer high byteLDY #$03 ; 4 bytes to doLDA (ut1_pl),Y ; get last byteSTA FAC1_3 ; save FAC1 mantissa3DEY ; decrement indexLDA (ut1_pl),Y ; get last-1 byteSTA FAC1_2 ; save FAC1 mantissa2DEY ; decrement indexLDA (ut1_pl),Y ; get second byteSTA FAC1_s ; save FAC1 sign (b7)ORA #$80 ; set 1xxx xxxx (add normal bit)STA FAC1_1 ; save FAC1 mantissa1DEY ; decrement indexLDA (ut1_pl),Y ; get first byte (exponent)STA FAC1_e ; save FAC1 exponentSTY FAC1_r ; clear FAC1 rounding byteRTS; pack FAC1 into AdatalLAB_276ELDX #<Adatal ; set pointer low byteLAB_2770LDY #>Adatal ; set pointer high byteBEQ LAB_2778 ; pack FAC1 into (XY) and return; pack FAC1 into (Lvarpl)LAB_PFACLDX Lvarpl ; get destination pointer low byteLDY Lvarph ; get destination pointer high byte; pack FAC1 into (XY)LAB_2778JSR LAB_27BA ; round FAC1STX ut1_pl ; save pointer low byteSTY ut1_ph ; save pointer high byteLDY #$03 ; set indexLDA FAC1_3 ; get FAC1 mantissa3STA (ut1_pl),Y ; store in destinationDEY ; decrement indexLDA FAC1_2 ; get FAC1 mantissa2STA (ut1_pl),Y ; store in destinationDEY ; decrement indexLDA FAC1_s ; get FAC1 sign (b7)ORA #$7F ; set bits x111 1111AND FAC1_1 ; AND in FAC1 mantissa1STA (ut1_pl),Y ; store in destinationDEY ; decrement indexLDA FAC1_e ; get FAC1 exponentSTA (ut1_pl),Y ; store in destinationSTY FAC1_r ; clear FAC1 rounding byteRTS; round and copy FAC1 to FAC2LAB_27ABJSR LAB_27BA ; round FAC1; copy FAC1 to FAC2LAB_27AELDX #$05 ; 5 bytes to copyLAB_27B0LDA FAC1_e-1,X ; get byte from FAC1,XSTA FAC1_o,X ; save byte at FAC2,XDEX ; decrement countBNE LAB_27B0 ; loop if not all doneSTX FAC1_r ; clear FAC1 rounding byteLAB_27B9RTS; round FAC1LAB_27BALDA FAC1_e ; get FAC1 exponentBEQ LAB_27B9 ; exit if zeroASL FAC1_r ; shift FAC1 rounding byteBCC LAB_27B9 ; exit if no overflow; round FAC1 (no check)LAB_27C2JSR LAB_2559 ; increment FAC1 mantissaBNE LAB_27B9 ; branch if no overflowJMP LAB_252A ; normalise FAC1 for C=1 and return; get FAC1 sign; return A=FF,C=1/-ve A=01,C=0/+veLAB_27CALDA FAC1_e ; get FAC1 exponentBEQ LAB_27D7 ; exit if zero (already correct SGN(0)=0); return A=FF,C=1/-ve A=01,C=0/+ve; no = 0 checkLAB_27CELDA FAC1_s ; else get FAC1 sign (b7); return A=FF,C=1/-ve A=01,C=0/+ve; no = 0 check, sign in ALAB_27D0ROL ; move sign bit to carryLDA #$FF ; set byte for -ve resultBCS LAB_27D7 ; return if sign was set (-ve)LDA #$01 ; else set byte for +ve resultLAB_27D7RTS; perform SGN()LAB_SGNJSR LAB_27CA ; get FAC1 sign; return A=$FF/-ve A=$01/+ve; save A as integer byteLAB_27DBSTA FAC1_1 ; save FAC1 mantissa1LDA #$00 ; clear ASTA FAC1_2 ; clear FAC1 mantissa2LDX #$88 ; set exponent; set exp=X, clearFAC1 mantissa3 and normaliseLAB_27E3LDA FAC1_1 ; get FAC1 mantissa1EOR #$FF ; complement itROL ; sign bit into carry; set exp=X, clearFAC1 mantissa3 and normaliseLAB_STFALDA #$00 ; clear ASTA FAC1_3 ; clear FAC1 mantissa3STX FAC1_e ; set FAC1 exponentSTA FAC1_r ; clear FAC1 rounding byteSTA FAC1_s ; clear FAC1 sign (b7)JMP LAB_24D0 ; do ABS and normalise FAC1; perform ABS()LAB_ABSLSR FAC1_s ; clear FAC1 sign (put zero in b7)RTS; compare FAC1 with (AY); returns A=$00 if FAC1 = (AY); returns A=$01 if FAC1 > (AY); returns A=$FF if FAC1 < (AY)LAB_27F8STA ut2_pl ; save pointer low byteLAB_27FASTY ut2_ph ; save pointer high byteLDY #$00 ; clear indexLDA (ut2_pl),Y ; get exponentINY ; increment indexTAX ; copy (AY) exponent to XBEQ LAB_27CA ; branch if (AY) exponent=0 and get FAC1 sign; A=FF,C=1/-ve A=01,C=0/+veLDA (ut2_pl),Y ; get (AY) mantissa1 (with sign)EOR FAC1_s ; EOR FAC1 sign (b7)BMI LAB_27CE ; if signs <> do return A=FF,C=1/-ve; A=01,C=0/+ve and returnCPX FAC1_e ; compare (AY) exponent with FAC1 exponentBNE LAB_2828 ; branch if differentLDA (ut2_pl),Y ; get (AY) mantissa1 (with sign)ORA #$80 ; normalise top bitCMP FAC1_1 ; compare with FAC1 mantissa1BNE LAB_2828 ; branch if differentINY ; increment indexLDA (ut2_pl),Y ; get mantissa2CMP FAC1_2 ; compare with FAC1 mantissa2BNE LAB_2828 ; branch if differentINY ; increment indexLDA #$7F ; set for 1/2 value rounding byteCMP FAC1_r ; compare with FAC1 rounding byte (set carry)LDA (ut2_pl),Y ; get mantissa3SBC FAC1_3 ; subtract FAC1 mantissa3BEQ LAB_2850 ; exit if mantissa3 equal; gets here if number <> FAC1LAB_2828LDA FAC1_s ; get FAC1 sign (b7)BCC LAB_282E ; branch if FAC1 > (AY)EOR #$FF ; else toggle FAC1 signLAB_282EJMP LAB_27D0 ; return A=FF,C=1/-ve A=01,C=0/+ve; convert FAC1 floating-to-fixedLAB_2831LDA FAC1_e ; get FAC1 exponentBEQ LAB_287F ; if zero go clear FAC1 and returnSEC ; set carry for subtractSBC #$98 ; subtract maximum integer range exponentBIT FAC1_s ; test FAC1 sign (b7)BPL LAB_2845 ; branch if FAC1 +ve; FAC1 was -veTAX ; copy subtracted exponentLDA #$FF ; overflow for -ve numberSTA FAC1_o ; set FAC1 overflow byteJSR LAB_253D ; twos complement FAC1 mantissaTXA ; restore subtracted exponentLAB_2845LDX #FAC1_e ; set index to FAC1CMP #$F9 ; compare exponent resultBPL LAB_2851 ; if < 8 shifts shift FAC1 A times right and returnJSR LAB_257B ; shift FAC1 A times right (> 8 shifts)STY FAC1_o ; clear FAC1 overflow byteLAB_2850RTS; shift FAC1 A times rightLAB_2851TAY ; copy shift countLDA FAC1_s ; get FAC1 sign (b7)AND #$80 ; mask sign bit only (x000 0000)LSR FAC1_1 ; shift FAC1 mantissa1ORA FAC1_1 ; OR sign in b7 FAC1 mantissa1STA FAC1_1 ; save FAC1 mantissa1JSR LAB_2592 ; shift FAC1 Y times rightSTY FAC1_o ; clear FAC1 overflow byteRTS; perform INT()LAB_INTLDA FAC1_e ; get FAC1 exponentCMP #$98 ; compare with max intBCS LAB_2886 ; exit if >= (already int, too big for fractional part!)JSR LAB_2831 ; convert FAC1 floating-to-fixedSTY FAC1_r ; save FAC1 rounding byteLDA FAC1_s ; get FAC1 sign (b7)STY FAC1_s ; save FAC1 sign (b7)EOR #$80 ; toggle FAC1 signROL ; shift into carryLDA #$98 ; set new exponentSTA FAC1_e ; save FAC1 exponentLDA FAC1_3 ; get FAC1 mantissa3STA Temp3 ; save for EXP() functionJMP LAB_24D0 ; do ABS and normalise FAC1; clear FAC1 and returnLAB_287FSTA FAC1_1 ; clear FAC1 mantissa1STA FAC1_2 ; clear FAC1 mantissa2STA FAC1_3 ; clear FAC1 mantissa3TAY ; clear YLAB_2886RTS; get FAC1 from string; this routine now handles hex and binary values from strings; starting with "$" and "%" respectivelyLAB_2887LDY #$00 ; clear YSTY Dtypef ; clear data type flag, $FF=string, $00=numericLDX #$09 ; set indexLAB_288BSTY numexp,X ; clear byteDEX ; decrement indexBPL LAB_288B ; loop until numexp to negnum (and FAC1) = $00BCC LAB_28FE ; branch if 1st character numeric; get FAC1 from string .. first character wasn't numericCMP #'-' ; else compare with "-"BNE LAB_289A ; branch if not "-"STX negnum ; set flag for -ve number (X = $FF)BEQ LAB_289C ; branch always (go scan and check for hex/bin); get FAC1 from string .. first character wasn't numeric or -LAB_289ACMP #'+' ; else compare with "+"BNE LAB_289D ; branch if not "+" (go check for hex/bin); was "+" or "-" to start, so get next characterLAB_289CJSR LAB_IGBY ; increment and scan memoryBCC LAB_28FE ; branch if numeric character; code here for hex and binary numbersLAB_289DCMP #'$' ; else compare with "$"BNE LAB_NHEX ; branch if not "$"JMP LAB_CHEX ; branch if "$"LAB_NHEXCMP #'%' ; else compare with "%"BNE LAB_28A3 ; branch if not "%" (continue original code)JMP LAB_CBIN ; branch if "%"LAB_289EJSR LAB_IGBY ; increment and scan memory (ignore + or get next number)LAB_28A1BCC LAB_28FE ; branch if numeric character; get FAC1 from string .. character wasn't numeric, -, +, hex or binaryLAB_28A3CMP #'.' ; else compare with "."BEQ LAB_28D5 ; branch if "."; get FAC1 from string .. character wasn't numeric, -, + or .CMP #'E' ; else compare with "E"BNE LAB_28DB ; branch if not "E"; was "E" so evaluate exponential partJSR LAB_IGBY ; increment and scan memoryBCC LAB_28C7 ; branch if numeric characterCMP #TK_MINUS ; else compare with token for -BEQ LAB_28C2 ; branch if token for -CMP #'-' ; else compare with "-"BEQ LAB_28C2 ; branch if "-"CMP #TK_PLUS ; else compare with token for +BEQ LAB_28C4 ; branch if token for +CMP #'+' ; else compare with "+"BEQ LAB_28C4 ; branch if "+"BNE LAB_28C9 ; branch alwaysLAB_28C2ROR expneg ; set exponent -ve flag (C, which=1, into b7)LAB_28C4JSR LAB_IGBY ; increment and scan memoryLAB_28C7BCC LAB_2925 ; branch if numeric characterLAB_28C9BIT expneg ; test exponent -ve flagBPL LAB_28DB ; if +ve go evaluate exponent; else do exponent = -exponentLDA #$00 ; clear resultSEC ; set carry for subtractSBC expcnt ; subtract exponent byteJMP LAB_28DD ; go evaluate exponentLAB_28D5ROR numdpf ; set decimal point flagBIT numdpf ; test decimal point flagBVC LAB_289E ; branch if only one decimal point so far; evaluate exponentLAB_28DBLDA expcnt ; get exponent count byteLAB_28DDSEC ; set carry for subtractSBC numexp ; subtract numerator exponentSTA expcnt ; save exponent count byteBEQ LAB_28F6 ; branch if no adjustmentBPL LAB_28EF ; else if +ve go do FAC1*10^expcnt; else go do FAC1/10^(0-expcnt)LAB_28E6JSR LAB_26B9 ; divide by 10INC expcnt ; increment exponent count byteBNE LAB_28E6 ; loop until all doneBEQ LAB_28F6 ; branch alwaysLAB_28EFJSR LAB_269E ; multiply by 10DEC expcnt ; decrement exponent count byteBNE LAB_28EF ; loop until all doneLAB_28F6LDA negnum ; get -ve flagBMI LAB_28FB ; if -ve do - FAC1 and returnRTS; do - FAC1 and returnLAB_28FBJMP LAB_GTHAN ; do - FAC1 and return; do unsigned FAC1*10+numberLAB_28FEPHA ; save characterBIT numdpf ; test decimal point flagBPL LAB_2905 ; skip exponent increment if not setINC numexp ; else increment number exponentLAB_2905JSR LAB_269E ; multiply FAC1 by 10PLA ; restore characterAND #$0F ; convert to binaryJSR LAB_2912 ; evaluate new ASCII digitJMP LAB_289E ; go do next character; evaluate new ASCII digitLAB_2912PHA ; save digitJSR LAB_27AB ; round and copy FAC1 to FAC2PLA ; restore digitJSR LAB_27DB ; save A as integer byteLDA FAC2_s ; get FAC2 sign (b7)EOR FAC1_s ; toggle with FAC1 sign (b7)STA FAC_sc ; save sign compare (FAC1 EOR FAC2)LDX FAC1_e ; get FAC1 exponentJMP LAB_ADD ; add FAC2 to FAC1 and return; evaluate next character of exponential part of numberLAB_2925LDA expcnt ; get exponent count byteCMP #$0A ; compare with 10 decimalBCC LAB_2934 ; branch if lessLDA #$64 ; make all -ve exponents = -100 decimal (causes underflow)BIT expneg ; test exponent -ve flagBMI LAB_2942 ; branch if -veJMP LAB_2564 ; else do overflow errorLAB_2934ASL ; * 2ASL ; * 4ADC expcnt ; * 5ASL ; * 10LDY #$00 ; set indexADC (Bpntrl),Y ; add character (will be $30 too much!)SBC #'0'-1 ; convert character to binaryLAB_2942STA expcnt ; save exponent count byteJMP LAB_28C4 ; go get next character; print " in line [LINE #]"LAB_2953LDA #<LAB_LMSG ; point to " in line " message low byteLDY #>LAB_LMSG ; point to " in line " message high byteJSR LAB_18C3 ; print null terminated string from memory; print Basic line #LDA Clineh ; get current line high byteLDX Clinel ; get current line low byte; print XA as unsigned integerLAB_295ESTA FAC1_1 ; save low byte as FAC1 mantissa1STX FAC1_2 ; save high byte as FAC1 mantissa2LDX #$90 ; set exponent to 16d bitsSEC ; set integer is +ve flagJSR LAB_STFA ; set exp=X, clearFAC1 mantissa3 and normaliseLDY #$00 ; clear indexTYA ; clear AJSR LAB_297B ; convert FAC1 to string, skip sign character saveJMP LAB_18C3 ; print null terminated string from memory and return; convert FAC1 to ASCII string result in (AY); not any more, moved scratchpad to page 0LAB_296ELDY #$01 ; set index = 1LDA #$20 ; character = " " (assume +ve)BIT FAC1_s ; test FAC1 sign (b7)BPL LAB_2978 ; branch if +veLDA #$2D ; else character = "-"LAB_2978STA Decss,Y ; save leading character (" " or "-")LAB_297BSTA FAC1_s ; clear FAC1 sign (b7)STY Sendl ; save indexINY ; increment indexLDX FAC1_e ; get FAC1 exponentBNE LAB_2989 ; branch if FAC1<>0; exponent was $00 so FAC1 is 0LDA #'0' ; set character = "0"JMP LAB_2A89 ; save last character, [EOT] and exit; FAC1 is some non zero valueLAB_2989LDA #$00 ; clear (number exponent count)CPX #$81 ; compare FAC1 exponent with $81 (>1.00000)BCS LAB_299A ; branch if FAC1=>1; FAC1<1LDA #<LAB_294F ; set pointer low byte to 1,000,000LDY #>LAB_294F ; set pointer high byte to 1,000,000JSR LAB_25FB ; do convert AY, FCA1*(AY)LDA #$FA ; set number exponent count (-6)LAB_299ASTA numexp ; save number exponent countLAB_299CLDA #<LAB_294B ; set pointer low byte to 999999.4375 (max before sci note)LDY #>LAB_294B ; set pointer high byte to 999999.4375JSR LAB_27F8 ; compare FAC1 with (AY)BEQ LAB_29C3 ; exit if FAC1 = (AY)BPL LAB_29B9 ; go do /10 if FAC1 > (AY); FAC1 < (AY)LAB_29A7LDA #<LAB_2947 ; set pointer low byte to 99999.9375LDY #>LAB_2947 ; set pointer high byte to 99999.9375JSR LAB_27F8 ; compare FAC1 with (AY)BEQ LAB_29B2 ; branch if FAC1 = (AY) (allow decimal places)BPL LAB_29C0 ; branch if FAC1 > (AY) (no decimal places); FAC1 <= (AY)LAB_29B2JSR LAB_269E ; multiply by 10DEC numexp ; decrement number exponent countBNE LAB_29A7 ; go test again (branch always)LAB_29B9JSR LAB_26B9 ; divide by 10INC numexp ; increment number exponent countBNE LAB_299C ; go test again (branch always); now we have just the digits to doLAB_29C0JSR LAB_244E ; add 0.5 to FAC1 (round FAC1)LAB_29C3JSR LAB_2831 ; convert FAC1 floating-to-fixedLDX #$01 ; set default digits before dp = 1LDA numexp ; get number exponent countCLC ; clear carry for addADC #$07 ; up to 6 digits before pointBMI LAB_29D8 ; if -ve then 1 digit before dpCMP #$08 ; A>=8 if n>=1E6BCS LAB_29D9 ; branch if >= $08; carry is clearADC #$FF ; take 1 from digit countTAX ; copy to ALDA #$02 ;.set exponent adjustLAB_29D8SEC ; set carry for subtractLAB_29D9SBC #$02 ; -2STA expcnt ;.save exponent adjustSTX numexp ; save digits before dp countTXA ; copy to ABEQ LAB_29E4 ; branch if no digits before dpBPL LAB_29F7 ; branch if digits before dpLAB_29E4LDY Sendl ; get output string indexLDA #$2E ; character "."INY ; increment indexSTA Decss,Y ; save to output stringTXA ;.BEQ LAB_29F5 ;.LDA #'0' ; character "0"INY ; increment indexSTA Decss,Y ; save to output stringLAB_29F5STY Sendl ; save output string indexLAB_29F7LDY #$00 ; clear index (point to 100,000)LDX #$80 ;LAB_29FBLDA FAC1_3 ; get FAC1 mantissa3CLC ; clear carry for addADC LAB_2A9C,Y ; add -ve LSBSTA FAC1_3 ; save FAC1 mantissa3LDA FAC1_2 ; get FAC1 mantissa2ADC LAB_2A9B,Y ; add -ve NMSBSTA FAC1_2 ; save FAC1 mantissa2LDA FAC1_1 ; get FAC1 mantissa1ADC LAB_2A9A,Y ; add -ve MSBSTA FAC1_1 ; save FAC1 mantissa1INX ;BCS LAB_2A18 ;BPL LAB_29FB ; not -ve so try againBMI LAB_2A1A ;LAB_2A18BMI LAB_29FB ;LAB_2A1ATXA ;BCC LAB_2A21 ;EOR #$FF ;ADC #$0A ;LAB_2A21ADC #'0'-1 ; add "0"-1 to resultINY ; increment index ..INY ; .. to next less ..INY ; .. power of tenSTY Cvaral ; save as current var address low byteLDY Sendl ; get output string indexINY ; increment output string indexTAX ; copy character to XAND #$7F ; mask out top bitSTA Decss,Y ; save to output stringDEC numexp ; decrement # of characters before the dpBNE LAB_2A3B ; branch if still characters to do; else output the pointLDA #$2E ; character "."INY ; increment output string indexSTA Decss,Y ; save to output stringLAB_2A3BSTY Sendl ; save output string indexLDY Cvaral ; get current var address low byteTXA ; get character backEOR #$FF ;AND #$80 ;TAX ;CPY #$12 ; compare index with maxBNE LAB_29FB ; loop if not max; now remove trailing zeroesLDY Sendl ; get output string indexLAB_2A4BLDA Decss,Y ; get character from output stringDEY ; decrement output string indexCMP #'0' ; compare with "0"BEQ LAB_2A4B ; loop until non "0" character foundCMP #'.' ; compare with "."BEQ LAB_2A58 ; branch if was dp; restore last characterINY ; increment output string indexLAB_2A58LDA #$2B ; character "+"LDX expcnt ; get exponent countBEQ LAB_2A8C ; if zero go set null terminator and exit; exponent isn't zero so write exponentBPL LAB_2A68 ; branch if exponent count +veLDA #$00 ; clear ASEC ; set carry for subtractSBC expcnt ; subtract exponent count adjust (convert -ve to +ve)TAX ; copy exponent count to XLDA #'-' ; character "-"LAB_2A68STA Decss+2,Y ; save to output stringLDA #$45 ; character "E"STA Decss+1,Y ; save exponent sign to output stringTXA ; get exponent count backLDX #'0'-1 ; one less than "0" characterSEC ; set carry for subtractLAB_2A74INX ; increment 10's characterSBC #$0A ;.subtract 10 from exponent countBCS LAB_2A74 ; loop while still >= 0ADC #':' ; add character ":" ($30+$0A, result is 10 less that value)STA Decss+4,Y ; save to output stringTXA ; copy 10's characterSTA Decss+3,Y ; save to output stringLDA #$00 ; set null terminatorSTA Decss+5,Y ; save to output stringBEQ LAB_2A91 ; go set string pointer (AY) and exit (branch always); save last character, [EOT] and exitLAB_2A89STA Decss,Y ; save last character to output string; set null terminator and exitLAB_2A8CLDA #$00 ; set null terminatorSTA Decss+1,Y ; save after last character; set string pointer (AY) and exitLAB_2A91LDA #<Decssp1 ; set result string low pointerLDY #>Decssp1 ; set result string high pointerRTS; perform power functionLAB_POWERBEQ LAB_EXP ; go do EXP()LDA FAC2_e ; get FAC2 exponentBNE LAB_2ABF ; branch if FAC2<>0JMP LAB_24F3 ; clear FAC1 exponent and sign and returnLAB_2ABFLDX #<func_l ; set destination pointer low byteLDY #>func_l ; set destination pointer high byteJSR LAB_2778 ; pack FAC1 into (XY)LDA FAC2_s ; get FAC2 sign (b7)BPL LAB_2AD9 ; branch if FAC2>0; else FAC2 is -ve and can only be raised to an; integer power which gives an x +j0 resultJSR LAB_INT ; perform INTLDA #<func_l ; set source pointer low byteLDY #>func_l ; set source pointer high byteJSR LAB_27F8 ; compare FAC1 with (AY)BNE LAB_2AD9 ; branch if FAC1 <> (AY) to allow Function Call error; this will leave FAC1 -ve and cause a Function Call; error when LOG() is calledTYA ; clear sign b7LDY Temp3 ; save mantissa 3 from INT() function as sign in Y; for possible later negation, b0LAB_2AD9JSR LAB_279D ; save FAC1 sign and copy ABS(FAC2) to FAC1TYA ; copy sign back ..PHA ; .. and save itJSR LAB_LOG ; do LOG(n)LDA #<garb_l ; set pointer low byteLDY #>garb_l ; set pointer high byteJSR LAB_25FB ; do convert AY, FCA1*(AY) (square the value)JSR LAB_EXP ; go do EXP(n)PLA ; pull sign from stackLSR ; b0 is to be tested, shift to CbBCC LAB_2AF9 ; if no bit then exit; Perform negation; do - FAC1LAB_GTHANLDA FAC1_e ; get FAC1 exponentBEQ LAB_2AF9 ; exit if FAC1_e = $00LDA FAC1_s ; get FAC1 sign (b7)EOR #$FF ; complement itSTA FAC1_s ; save FAC1 sign (b7)LAB_2AF9RTS; perform EXP() (x^e)LAB_EXPLDA #<LAB_2AFA ; set 1.443 pointer low byteLDY #>LAB_2AFA ; set 1.443 pointer high byteJSR LAB_25FB ; do convert AY, FCA1*(AY)LDA FAC1_r ; get FAC1 rounding byteADC #$50 ; +$50/$100BCC LAB_2B2B ; skip rounding if no carryJSR LAB_27C2 ; round FAC1 (no check)LAB_2B2BSTA FAC2_r ; save FAC2 rounding byteJSR LAB_27AE ; copy FAC1 to FAC2LDA FAC1_e ; get FAC1 exponentCMP #$88 ; compare with EXP limit (256d)BCC LAB_2B39 ; branch if lessLAB_2B36JSR LAB_2690 ; handle overflow and underflowLAB_2B39JSR LAB_INT ; perform INTLDA Temp3 ; get mantissa 3 from INT() functionCLC ; clear carry for addADC #$81 ; normalise +1BEQ LAB_2B36 ; if $00 go handle overflowSEC ; set carry for subtractSBC #$01 ; now correct for exponentPHA ; save FAC2 exponent; swap FAC1 and FAC2LDX #$04 ; 4 bytes to doLAB_2B49LDA FAC2_e,X ; get FAC2,XLDY FAC1_e,X ; get FAC1,XSTA FAC1_e,X ; save FAC1,XSTY FAC2_e,X ; save FAC2,XDEX ; decrement count/indexBPL LAB_2B49 ; loop if not all doneLDA FAC2_r ; get FAC2 rounding byteSTA FAC1_r ; save as FAC1 rounding byteJSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1JSR LAB_GTHAN ; do - FAC1LDA #<LAB_2AFE ; set counter pointer low byteLDY #>LAB_2AFE ; set counter pointer high byteJSR LAB_2B84 ; go do series evaluationLDA #$00 ; clear ASTA FAC_sc ; clear sign compare (FAC1 EOR FAC2)PLA ;.get saved FAC2 exponentJMP LAB_2675 ; test and adjust accumulators and return; ^2 then series evaluationLAB_2B6ESTA Cptrl ; save count pointer low byteSTY Cptrh ; save count pointer high byteJSR LAB_276E ; pack FAC1 into AdatalLDA #<Adatal ; set pointer low byte (Y already $00)JSR LAB_25FB ; do convert AY, FCA1*(AY)JSR LAB_2B88 ; go do series evaluationLDA #<Adatal ; pointer to original # low byteLDY #>Adatal ; pointer to original # high byteJMP LAB_25FB ; do convert AY, FCA1*(AY) and return; series evaluationLAB_2B84STA Cptrl ; save count pointer low byteSTY Cptrh ; save count pointer high byteLAB_2B88LDX #<numexp ; set pointer low byteJSR LAB_2770 ; set pointer high byte and pack FAC1 into numexpLDA (Cptrl),Y ; get constants countSTA numcon ; save constants countLDY Cptrl ; get count pointer low byteINY ; increment it (now constants pointer)TYA ; copy itBNE LAB_2B97 ; skip next if no overflowINC Cptrh ; else increment high byteLAB_2B97STA Cptrl ; save low byteLDY Cptrh ; get high byteLAB_2B9BJSR LAB_25FB ; do convert AY, FCA1*(AY)LDA Cptrl ; get constants pointer low byteLDY Cptrh ; get constants pointer high byteCLC ; clear carry for addADC #$04 ; +4 to low pointer (4 bytes per constant)BCC LAB_2BA8 ; skip next if no overflowINY ; increment high byteLAB_2BA8STA Cptrl ; save pointer low byteSTY Cptrh ; save pointer high byteJSR LAB_246C ; add (AY) to FAC1LDA #<numexp ; set pointer low byte to partial @ numexpLDY #>numexp ; set pointer high byte to partial @ numexpDEC numcon ; decrement constants countBNE LAB_2B9B ; loop until all doneRTS; RND(n), 32 bit Galoise version. make n=0 for 19th next number in sequence or n<>0; to get 19th next number in sequence after seed n. This version of the PRNG uses; the Galois method and a sample of 65536 bytes produced gives the following values.; Entropy = 7.997442 bits per byte; Optimum compression would reduce these 65536 bytes by 0 percent; Chi square distribution for 65536 samples is 232.01, and; randomly would exceed this value 75.00 percent of the time; Arithmetic mean value of data bytes is 127.6724, 127.5 would be random; Monte Carlo value for Pi is 3.122871269, error 0.60 percent; Serial correlation coefficient is -0.000370, totally uncorrelated would be 0.0LAB_RNDLDA FAC1_e ; get FAC1 exponentBEQ NextPRN ; do next random # if zero; else get seed into random number storeLDX #Rbyte4 ; set PRNG pointer low byteLDY #$00 ; set PRNG pointer high byteJSR LAB_2778 ; pack FAC1 into (XY)NextPRNLDX #$AF ; set EOR byteLDY #$13 ; do this nineteen timesLoopPRNASL Rbyte1 ; shift PRNG most significant byteROL Rbyte2 ; shift PRNG middle byteROL Rbyte3 ; shift PRNG least significant byteROL Rbyte4 ; shift PRNG extra byteBCC Ninc1 ; branch if bit 32 clearTXA ; set EOR byteEOR Rbyte1 ; EOR PRNG extra byteSTA Rbyte1 ; save new PRNG extra byteNinc1DEY ; decrement loop countBNE LoopPRN ; loop if not all doneLDX #$02 ; three bytes to copyCopyPRNGLDA Rbyte1,X ; get PRNG byteSTA FAC1_1,X ; save FAC1 byteDEXBPL CopyPRNG ; loop if not completeLDA #$80 ; set the exponentSTA FAC1_e ; save FAC1 exponentASL ; clear ASTA FAC1_s ; save FAC1 signJMP LAB_24D5 ; normalise FAC1 and return; perform COS()LAB_COSLDA #<LAB_2C78 ; set (pi/2) pointer low byteLDY #>LAB_2C78 ; set (pi/2) pointer high byteJSR LAB_246C ; add (AY) to FAC1; perform SIN()LAB_SINJSR LAB_27AB ; round and copy FAC1 to FAC2LDA #<LAB_2C7C ; set (2*pi) pointer low byteLDY #>LAB_2C7C ; set (2*pi) pointer high byteLDX FAC2_s ; get FAC2 sign (b7)JSR LAB_26C2 ; divide by (AY) (X=sign)JSR LAB_27AB ; round and copy FAC1 to FAC2JSR LAB_INT ; perform INTLDA #$00 ; clear byteSTA FAC_sc ; clear sign compare (FAC1 EOR FAC2)JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1LDA #<LAB_2C80 ; set 0.25 pointer low byteLDY #>LAB_2C80 ; set 0.25 pointer high byteJSR LAB_2455 ; perform subtraction, (AY) from FAC1LDA FAC1_s ; get FAC1 sign (b7)PHA ; save FAC1 signBPL LAB_2C35 ; branch if +ve; FAC1 sign was -veJSR LAB_244E ; add 0.5 to FAC1LDA FAC1_s ; get FAC1 sign (b7)BMI LAB_2C38 ; branch if -veLDA Cflag ; get comparison evaluation flagEOR #$FF ; toggle flagSTA Cflag ; save comparison evaluation flagLAB_2C35JSR LAB_GTHAN ; do - FAC1LAB_2C38LDA #<LAB_2C80 ; set 0.25 pointer low byteLDY #>LAB_2C80 ; set 0.25 pointer high byteJSR LAB_246C ; add (AY) to FAC1PLA ; restore FAC1 signBPL LAB_2C45 ; branch if was +ve; else correct FAC1JSR LAB_GTHAN ; do - FAC1LAB_2C45LDA #<LAB_2C84 ; set pointer low byte to counterLDY #>LAB_2C84 ; set pointer high byte to counterJMP LAB_2B6E ; ^2 then series evaluation and return; perform TAN()LAB_TANJSR LAB_276E ; pack FAC1 into AdatalLDA #$00 ; clear byteSTA Cflag ; clear comparison evaluation flagJSR LAB_SIN ; go do SIN(n)LDX #<func_l ; set sin(n) pointer low byteLDY #>func_l ; set sin(n) pointer high byteJSR LAB_2778 ; pack FAC1 into (XY)LDA #<Adatal ; set n pointer low addrLDY #>Adatal ; set n pointer high addrJSR LAB_UFAC ; unpack memory (AY) into FAC1LDA #$00 ; clear byteSTA FAC1_s ; clear FAC1 sign (b7)LDA Cflag ; get comparison evaluation flagJSR LAB_2C74 ; save flag and go do series evaluationLDA #<func_l ; set sin(n) pointer low byteLDY #>func_l ; set sin(n) pointer high byteJMP LAB_26CA ; convert AY and do (AY)/FAC1LAB_2C74PHA ; save comparison evaluation flagJMP LAB_2C35 ; go do series evaluation; perform USR()LAB_USRJSR Usrjmp ; call user codeJMP LAB_1BFB ; scan for ")", else do syntax error then warm start; perform ATN()LAB_ATNLDA FAC1_s ; get FAC1 sign (b7)PHA ; save signBPL LAB_2CA1 ; branch if +veJSR LAB_GTHAN ; else do - FAC1LAB_2CA1LDA FAC1_e ; get FAC1 exponentPHA ; push exponentCMP #$81 ; compare with 1BCC LAB_2CAF ; branch if FAC1<1LDA #<LAB_259C ; set 1 pointer low byteLDY #>LAB_259C ; set 1 pointer high byteJSR LAB_26CA ; convert AY and do (AY)/FAC1LAB_2CAFLDA #<LAB_2CC9 ; set pointer low byte to counterLDY #>LAB_2CC9 ; set pointer high byte to counterJSR LAB_2B6E ; ^2 then series evaluationPLA ; restore old FAC1 exponentCMP #$81 ; compare with 1BCC LAB_2CC2 ; branch if FAC1<1LDA #<LAB_2C78 ; set (pi/2) pointer low byteLDY #>LAB_2C78 ; set (pi/2) pointer high byteJSR LAB_2455 ; perform subtraction, (AY) from FAC1LAB_2CC2PLA ; restore FAC1 signBPL LAB_2D04 ; exit if was +veJMP LAB_GTHAN ; else do - FAC1 and return; perform BITSETLAB_BITSETJSR LAB_GADB ; get two parameters for POKE or WAITCPX #$08 ; only 0 to 7 are allowedBCS FCError ; branch if > 7LDA #$00 ; clear ASEC ; set the carryS_BitsROL ; shift bitDEX ; decrement bit numberBPL S_Bits ; loop if still +veINX ; make X = $00ORA (Itempl,X) ; or with byte via temporary integer (addr)STA (Itempl,X) ; save byte via temporary integer (addr)LAB_2D04RTS; perform BITCLRLAB_BITCLRJSR LAB_GADB ; get two parameters for POKE or WAITCPX #$08 ; only 0 to 7 are allowedBCS FCError ; branch if > 7LDA #$FF ; set AS_BitcROL ; shift bitDEX ; decrement bit numberBPL S_Bitc ; loop if still +veINX ; make X = $00AND (Itempl,X) ; and with byte via temporary integer (addr)STA (Itempl,X) ; save byte via temporary integer (addr)RTSFCErrorJMP LAB_FCER ; do function call error then warm start; perform BITTST()LAB_BTSTJSR LAB_IGBY ; increment BASIC pointerJSR LAB_GADB ; get two parameters for POKE or WAITCPX #$08 ; only 0 to 7 are allowedBCS FCError ; branch if > 7JSR LAB_GBYT ; get next BASIC byteCMP #')' ; is next character ")"BEQ TST_OK ; if ")" go do rest of functionJMP LAB_SNER ; do syntax error then warm startTST_OKJSR LAB_IGBY ; update BASIC execute pointer (to character past ")")LDA #$00 ; clear ASEC ; set the carryT_BitsROL ; shift bitDEX ; decrement bit numberBPL T_Bits ; loop if still +veINX ; make X = $00AND (Itempl,X) ; AND with byte via temporary integer (addr)BEQ LAB_NOTT ; branch if zero (already correct)LDA #$FF ; set for -1 resultLAB_NOTTJMP LAB_27DB ; go do SGN tail; perform BIN$()LAB_BINSCPX #$19 ; max + 1BCS BinFErr ; exit if too big ( > or = )STX TempB ; save # of characters ($00 = leading zero remove)LDA #$18 ; need A byte long spaceJSR LAB_MSSP ; make string space A bytes longLDY #$17 ; set indexLDX #$18 ; character countNextB1LSR nums_1 ; shift highest byteROR nums_2 ; shift middle byteROR nums_3 ; shift lowest byte bit 0 to carryTXA ; load with "0"/2ROL ; shift in carrySTA (str_pl),Y ; save to temp string + indexDEY ; decrement indexBPL NextB1 ; loop if not doneLDA TempB ; get # of charactersBEQ EndBHS ; branch if truncateTAX ; copy length to XSEC ; set carry for add !EOR #$FF ; 1's complementADC #$18 ; add 24dBEQ GoPr2 ; if zero print whole stringBNE GoPr1 ; else go make output string; this is the exit code and is also used by HEX$(); truncate string to remove leading "0"sEndBHSTAY ; clear index (A=0, X=length here)NextB2LDA (str_pl),Y ; get character from stringCMP #'0' ; compare with "0"BNE GoPr ; if not "0" then go print string from hereDEX ; decrement character countBEQ GoPr3 ; if zero then end of string so go print itINY ; else increment indexBPL NextB2 ; loop always; make fixed length output string - ignore overflows!GoPr3INX ; need at least 1 characterGoPrTYA ; copy resultGoPr1CLC ; clear carry for addADC str_pl ; add low addressSTA str_pl ; save low addressLDA #$00 ; do high byteADC str_ph ; add high addressSTA str_ph ; save high addressGoPr2STX str_ln ; X holds string lengthJSR LAB_IGBY ; update BASIC execute pointer (to character past ")")JMP LAB_RTST ; check for space on descriptor stack then put address; and length on descriptor stack and update stack pointersBinFErrJMP LAB_FCER ; do function call error then warm start; perform HEX$()LAB_HEXSCPX #$07 ; max + 1BCS BinFErr ; exit if too big ( > or = )STX TempB ; save # of charactersLDA #$06 ; need 6 bytes for stringJSR LAB_MSSP ; make string space A bytes longLDY #$05 ; set string indexSED ; need decimal mode for nibble convertLDA nums_3 ; get lowest byteJSR LAB_A2HX ; convert A to ASCII hex byte and outputLDA nums_2 ; get middle byteJSR LAB_A2HX ; convert A to ASCII hex byte and outputLDA nums_1 ; get highest byteJSR LAB_A2HX ; convert A to ASCII hex byte and outputCLD ; back to binaryLDX #$06 ; character countLDA TempB ; get # of charactersBEQ EndBHS ; branch if truncateTAX ; copy length to XSEC ; set carry for add !EOR #$FF ; 1's complementADC #$06 ; add 6dBEQ GoPr2 ; if zero print whole stringBNE GoPr1 ; else go make output string (branch always); convert A to ASCII hex byte and output .. note set decimal mode before callingLAB_A2HXTAX ; save byteAND #$0F ; mask off top bitsJSR LAB_AL2X ; convert low nibble to ASCII and outputTXA ; get byte backLSR ; /2 shift high nibble to low nibbleLSR ; /4LSR ; /8LSR ; /16LAB_AL2XCMP #$0A ; set carry for +1 if >9ADC #'0' ; add ASCII "0"STA (str_pl),Y ; save to temp stringDEY ; decrement counterRTSLAB_NLTOSTA FAC1_e ; save FAC1 exponentLDA #$00 ; clear sign compareLAB_MLTESTA FAC_sc ; save sign compare (FAC1 EOR FAC2)TXA ; restore characterJSR LAB_2912 ; evaluate new ASCII digit; gets here if the first character was "$" for hex; get hex numberLAB_CHEXJSR LAB_IGBY ; increment and scan memoryBCC LAB_ISHN ; branch if numeric characterORA #$20 ; case convert, allow "A" to "F" and "a" to "f"SBC #'a' ; subtract "a" (carry set here)CMP #$06 ; compare normalised with $06 (max+1)BCS LAB_EXCH ; exit if >"f" or <"0"ADC #$0A ; convert to nibbleLAB_ISHNAND #$0F ; convert to binaryTAX ; save nibbleLDA FAC1_e ; get FAC1 exponentBEQ LAB_MLTE ; skip multiply if zeroADC #$04 ; add four to exponent (*16 - carry clear here)BCC LAB_NLTO ; if no overflow do evaluate digitLAB_MLTOJMP LAB_2564 ; do overflow error and warm startLAB_NXCHTAX ; save bitLDA FAC1_e ; get FAC1 exponentBEQ LAB_MLBT ; skip multiply if zeroINC FAC1_e ; increment FAC1 exponent (*2)BEQ LAB_MLTO ; do overflow error if = $00LDA #$00 ; clear sign compareLAB_MLBTSTA FAC_sc ; save sign compare (FAC1 EOR FAC2)TXA ; restore bitJSR LAB_2912 ; evaluate new ASCII digit; gets here if the first character was "%" for binary; get binary numberLAB_CBINJSR LAB_IGBY ; increment and scan memoryEOR #'0' ; convert "0" to 0 etc.CMP #$02 ; compare with max+1BCC LAB_NXCH ; branch exit if < 2LAB_EXCHJMP LAB_28F6 ; evaluate -ve flag and return; ctrl-c check routine. includes limited "life" byte save for INGET routine; now also the code that checks to see if an interrupt has occurredCTRLCLDA ccflag ; get [CTRL-C] check flagBNE LAB_FBA2 ; exit if inhibitedJSR V_INPT ; scan input deviceBCC LAB_FBA0 ; exit if buffer emptySTA ccbyte ; save received byteLDX #$20 ; "life" timer for bytesSTX ccnull ; set countdownJMP LAB_1636 ; return to BASICLAB_FBA0LDX ccnull ; get countdown byteBEQ LAB_FBA2 ; exit if finishedDEC ccnull ; else decrement countdownLAB_FBA2LDX #NmiBase ; set pointer to NMI valuesJSR LAB_CKIN ; go check interruptLDX #IrqBase ; set pointer to IRQ valuesJSR LAB_CKIN ; go check interruptLAB_CRTSRTS; check whichever interrupt is indexed by XLAB_CKINLDA PLUS_0,X ; get interrupt flag byteBPL LAB_CRTS ; branch if interrupt not enabled; we disable the interrupt here and make two new commands RETIRQ and RETNMI to; automatically enable the interrupt when we exitASL ; move happened bit to setup bitAND #$40 ; mask happened bitsBEQ LAB_CRTS ; if no interrupt then exitSTA PLUS_0,X ; save interrupt flag byteTXA ; copy index ..TAY ; .. to YPLA ; dump return address low byte, call from CTRL-CPLA ; dump return address high byteLDA #$05 ; need 5 bytes for GOSUBJSR LAB_1212 ; check room on stack for A bytesLDA Bpntrh ; get BASIC execute pointer high bytePHA ; push on stackLDA Bpntrl ; get BASIC execute pointer low bytePHA ; push on stackLDA Clineh ; get current line high bytePHA ; push on stackLDA Clinel ; get current line low bytePHA ; push on stackLDA #TK_GOSUB ; token for GOSUBPHA ; push on stackLDA PLUS_1,Y ; get interrupt code pointer low byteSTA Bpntrl ; save as BASIC execute pointer low byteLDA PLUS_2,Y ; get interrupt code pointer high byteSTA Bpntrh ; save as BASIC execute pointer high byteJMP LAB_15C2 ; go do interpreter inner loop; can't RTS, we used the stack! the RTS from the ctrl-c; check will be taken when the RETIRQ/RETNMI/RETURN is; executed at the end of the subroutine; get byte from input device, no waiting; returns with carry set if byte in AINGETJSR V_INPT ; call scan input deviceBCS LAB_FB95 ; if byte go reset timerLDA ccnull ; get countdownBEQ LAB_FB96 ; exit if emptyLDA ccbyte ; get last received byteSEC ; flag we got a byteLAB_FB95LDX #$00 ; clear XSTX ccnull ; clear timer because we got a byteLAB_FB96RTS; these routines only enable the interrupts if the set-up flag is set; if not they have no effect; perform IRQ {ON|OFF|CLEAR}LAB_IRQLDX #IrqBase ; set pointer to IRQ values.byte $2C ; make next line BIT abs.; perform NMI {ON|OFF|CLEAR}LAB_NMILDX #NmiBase ; set pointer to NMI valuesCMP #TK_ON ; compare with token for ONBEQ LAB_INON ; go turn on interruptCMP #TK_OFF ; compare with token for OFFBEQ LAB_IOFF ; go turn off interruptEOR #TK_CLEAR ; compare with token for CLEAR, A = $00 if = TK_CLEARBEQ LAB_INEX ; go clear interrupt flags and returnJMP LAB_SNER ; do syntax error then warm startLAB_IOFFLDA #$7F ; clear AAND PLUS_0,X ; AND with interrupt setup flagBPL LAB_INEX ; go clear interrupt enabled flag and returnLAB_INONLDA PLUS_0,X ; get interrupt setup flagASL ; Shift bit to enabled flagORA PLUS_0,X ; OR with flag byteLAB_INEXSTA PLUS_0,X ; save interrupt flag byteJMP LAB_IGBY ; update BASIC execute pointer and return; these routines set up the pointers and flags for the interrupt routines; note that the interrupts are also enabled by these commands; perform ON IRQLAB_SIRQCLI ; enable interruptsLDX #IrqBase ; set pointer to IRQ values.byte $2C ; make next line BIT abs.; perform ON NMILAB_SNMILDX #NmiBase ; set pointer to NMI valuesSTX TempB ; save interrupt pointerJSR LAB_IGBY ; increment and scan memory (past token)JSR LAB_GFPN ; get fixed-point number into temp integerLDA Smeml ; get start of mem low byteLDX Smemh ; get start of mem high byteJSR LAB_SHLN ; search Basic for temp integer line number from AXBCS LAB_LFND ; if carry set go set-up interruptJMP LAB_16F7 ; else go do "Undefined statement" error and warm startLAB_LFNDLDX TempB ; get interrupt pointerLDA Baslnl ; get pointer low byteSBC #$01 ; -1 (carry already set for subtract)STA PLUS_1,X ; save as interrupt pointer low byteLDA Baslnh ; get pointer high byteSBC #$00 ; subtract carrySTA PLUS_2,X ; save as interrupt pointer high byteLDA #$C0 ; set interrupt enabled/setup bitsSTA PLUS_0,X ; set interrupt flagsLAB_IRTSRTS; return from IRQ service, restores the enabled flag.; perform RETIRQLAB_RETIRQBNE LAB_IRTS ; exit if following token (to allow syntax error)LDA IrqBase ; get interrupt flagsASL ; copy setup to enabled (b7)ORA IrqBase ; OR in setup flagSTA IrqBase ; save enabled flagJMP LAB_16E8 ; go do rest of RETURN; return from NMI service, restores the enabled flag.; perform RETNMILAB_RETNMIBNE LAB_IRTS ; exit if following token (to allow syntax error)LDA NmiBase ; get set-up flagASL ; copy setup to enabled (b7)ORA NmiBase ; OR in setup flagSTA NmiBase ; save enabled flagJMP LAB_16E8 ; go do rest of RETURN; MAX() MIN() pre processLAB_MMPPJSR LAB_EVEZ ; process expressionJMP LAB_CTNM ; check if source is numeric, else do type mismatch; perform MAX()LAB_MAXJSR LAB_PHFA ; push FAC1, evaluate expression,; pull FAC2 and compare with FAC1BPL LAB_MAX ; branch if no swap to doLDA FAC2_1 ; get FAC2 mantissa1ORA #$80 ; set top bit (clear sign from compare)STA FAC2_1 ; save FAC2 mantissa1JSR LAB_279B ; copy FAC2 to FAC1BEQ LAB_MAX ; go do next (branch always); perform MIN()LAB_MINJSR LAB_PHFA ; push FAC1, evaluate expression,; pull FAC2 and compare with FAC1BMI LAB_MIN ; branch if no swap to doBEQ LAB_MIN ; branch if no swap to doLDA FAC2_1 ; get FAC2 mantissa1ORA #$80 ; set top bit (clear sign from compare)STA FAC2_1 ; save FAC2 mantissa1JSR LAB_279B ; copy FAC2 to FAC1BEQ LAB_MIN ; go do next (branch always); exit routine. don't bother returning to the loop code; check for correct exit, else so syntax errorLAB_MMECCMP #')' ; is it end of function?BNE LAB_MMSE ; if not do MAX MIN syntax errorPLA ; dump return address low bytePLA ; dump return address high byteJMP LAB_IGBY ; update BASIC execute pointer (to chr past ")")LAB_MMSEJMP LAB_SNER ; do syntax error then warm start; check for next, evaluate and return or exit; this is the routine that does most of the workLAB_PHFAJSR LAB_GBYT ; get next BASIC byteCMP #',' ; is there more ?BNE LAB_MMEC ; if not go do end check; push FAC1JSR LAB_27BA ; round FAC1LDA FAC1_s ; get FAC1 signORA #$7F ; set all non sign bitsAND FAC1_1 ; AND FAC1 mantissa1 (AND in sign bit)PHA ; push on stackLDA FAC1_2 ; get FAC1 mantissa2PHA ; push on stackLDA FAC1_3 ; get FAC1 mantissa3PHA ; push on stackLDA FAC1_e ; get FAC1 exponentPHA ; push on stackJSR LAB_IGBY ; scan and get next BASIC byte (after ",")JSR LAB_EVNM ; evaluate expression and check is numeric,; else do type mismatch; pop FAC2 (MAX/MIN expression so far)PLA ; pop exponentSTA FAC2_e ; save FAC2 exponentPLA ; pop mantissa3STA FAC2_3 ; save FAC2 mantissa3PLA ; pop mantissa1STA FAC2_2 ; save FAC2 mantissa2PLA ; pop sign/mantissa1STA FAC2_1 ; save FAC2 sign/mantissa1STA FAC2_s ; save FAC2 sign; compare FAC1 with (packed) FAC2LDA #<FAC2_e ; set pointer low byte to FAC2LDY #>FAC2_e ; set pointer high byte to FAC2JMP LAB_27F8 ; compare FAC1 with FAC2 (AY) and return; returns A=$00 if FAC1 = (AY); returns A=$01 if FAC1 > (AY); returns A=$FF if FAC1 < (AY); perform WIDTHLAB_WDTHCMP #',' ; is next byte ","BEQ LAB_TBSZ ; if so do tab sizeJSR LAB_GTBY ; get byte parameterTXA ; copy width to ABEQ LAB_NSTT ; branch if set for infinite lineCPX #$10 ; else make min width = 16dBCC TabErr ; if less do function call error and exit; this next compare ensures that we can't exit WIDTH via an error leaving the; tab size greater than the line length.CPX TabSiz ; compare with tab sizeBCS LAB_NSTT ; branch if >= tab sizeSTX TabSiz ; else make tab size = terminal widthLAB_NSTTSTX TWidth ; set the terminal widthJSR LAB_GBYT ; get BASIC byte backBEQ WExit ; exit if no followingCMP #',' ; else is it ","BNE LAB_MMSE ; if not do syntax errorLAB_TBSZJSR LAB_SGBY ; scan and get byte parameterTXA ; copy TAB sizeBMI TabErr ; if >127 do function call error and exitCPX #$01 ; compare with min-1BCC TabErr ; if <=1 do function call error and exitLDA TWidth ; set flags for widthBEQ LAB_SVTB ; skip check if infinite lineCPX TWidth ; compare TAB with widthBEQ LAB_SVTB ; ok if =BCS TabErr ; branch if too bigLAB_SVTBSTX TabSiz ; save TAB size; calculate tab column limit from TAB size. The Iclim is set to the last tab; position on a line that still has at least one whole tab width between it; and the end of the line.WExitLDA TWidth ; get widthBEQ LAB_SULP ; branch if infinite lineCMP TabSiz ; compare with tab sizeBCS LAB_WDLP ; branch if >= tab sizeSTA TabSiz ; else make tab size = terminal widthLAB_SULPSEC ; set carry for subtractLAB_WDLPSBC TabSiz ; subtract tab sizeBCS LAB_WDLP ; loop while no borrowADC TabSiz ; add tab size backCLC ; clear carry for addADC TabSiz ; add tab size back againSTA Iclim ; save for nowLDA TWidth ; get width backSEC ; set carry for subtractSBC Iclim ; subtract remainderSTA Iclim ; save tab column limitLAB_NOSQRTSTabErrJMP LAB_FCER ; do function call error then warm start; perform SQR()LAB_SQRLDA FAC1_s ; get FAC1 signBMI TabErr ; if -ve do function call errorLDA FAC1_e ; get exponentBEQ LAB_NOSQ ; if zero just return; else do rootJSR LAB_27AB ; round and copy FAC1 to FAC2LDA #$00 ; clear ASTA FACt_3 ; clear remainderSTA FACt_2 ; ..STA FACt_1 ; ..STA TempB ; ..STA FAC1_3 ; clear rootSTA FAC1_2 ; ..STA FAC1_1 ; ..LDX #$18 ; 24 pairs of bits to doLDA FAC2_e ; get exponentLSR ; check odd/evenBCS LAB_SQE2 ; if odd only 1 shift first timeLAB_SQE1ASL FAC2_3 ; shift highest bit of number ..ROL FAC2_2 ; ..ROL FAC2_1 ; ..ROL FACt_3 ; .. into remainderROL FACt_2 ; ..ROL FACt_1 ; ..ROL TempB ; .. never overflowsLAB_SQE2ASL FAC2_3 ; shift highest bit of number ..ROL FAC2_2 ; ..ROL FAC2_1 ; ..ROL FACt_3 ; .. into remainderROL FACt_2 ; ..ROL FACt_1 ; ..ROL TempB ; .. never overflowsASL FAC1_3 ; root = root * 2ROL FAC1_2 ; ..ROL FAC1_1 ; .. never overflowsLDA FAC1_3 ; get root low byteROL ; *2STA Temp3 ; save partial low byteLDA FAC1_2 ; get root low mid byteROL ; *2STA Temp3+1 ; save partial low mid byteLDA FAC1_1 ; get root high mid byteROL ; *2STA Temp3+2 ; save partial high mid byteLDA #$00 ; get root high byte (always $00)ROL ; *2STA Temp3+3 ; save partial high byte; carry clear for subtract +1LDA FACt_3 ; get remainder low byteSBC Temp3 ; subtract partial low byteSTA Temp3 ; save partial low byteLDA FACt_2 ; get remainder low mid byteSBC Temp3+1 ; subtract partial low mid byteSTA Temp3+1 ; save partial low mid byteLDA FACt_1 ; get remainder high mid byteSBC Temp3+2 ; subtract partial high mid byteTAY ; copy partial high mid byteLDA TempB ; get remainder high byteSBC Temp3+3 ; subtract partial high byteBCC LAB_SQNS ; skip sub if remainder smallerSTA TempB ; save remainder high byteSTY FACt_1 ; save remainder high mid byteLDA Temp3+1 ; get remainder low mid byteSTA FACt_2 ; save remainder low mid byteLDA Temp3 ; get partial low byteSTA FACt_3 ; save remainder low byteINC FAC1_3 ; increment root low byte (never any rollover)LAB_SQNSDEX ; decrement bit pair countBNE LAB_SQE1 ; loop if not all doneSEC ; set carry for subtractLDA FAC2_e ; get exponentSBC #$80 ; normaliseROR ; /2 and re-bias to $80ADC #$00 ; add bit zero back in (allow for half shift)STA FAC1_e ; save itJMP LAB_24D5 ; normalise FAC1 and return; perform VARPTR()LAB_VARPTRJSR LAB_IGBY ; increment and scan memoryJSR LAB_GVAR ; get var addressJSR LAB_1BFB ; scan for ")" , else do syntax error then warm startLDY Cvaral ; get var address low byteLDA Cvarah ; get var address high byteJMP LAB_AYFC ; save and convert integer AY to FAC1 and return; perform PILAB_PILDA #<LAB_2C7C ; set (2*pi) pointer low byteLDY #>LAB_2C7C ; set (2*pi) pointer high byteJSR LAB_UFAC ; unpack memory (AY) into FAC1DEC FAC1_e ; make result = PIRTS; perform TWOPILAB_TWOPILDA #<LAB_2C7C ; set (2*pi) pointer low byteLDY #>LAB_2C7C ; set (2*pi) pointer high byteJMP LAB_UFAC ; unpack memory (AY) into FAC1 and return; system dependant i/o vectors; these are in RAM and are set by the monitor at start-upV_INPTJMP (VEC_IN) ; non halting scan input deviceV_OUTPJMP (VEC_OUT) ; send byte to output deviceV_LOADJMP (VEC_LD) ; load BASIC programV_SAVEJMP (VEC_SV) ; save BASIC programLAB_BYE:; nat.byte $42 ; WDMxcecpu rtf65002jmp (ExitTask>>2)cpu W65C02; The rest are tables messages and code for RAM; the rest of the code is tables and BASIC start-up codePG2_TABS.byte $00 ; ctrl-c flag - $00 = enabled.byte $00 ; ctrl-c byte - GET needs this.byte $00 ; ctrl-c byte timeout - GET needs this.word CTRLC ; ctrl c check vector; .word xxxx ; non halting key input - monitor to set this; .word xxxx ; output vector - monitor to set this; .word xxxx ; load vector - monitor to set this; .word xxxx ; save vector - monitor to set thisPG2_TABE; character get subroutine for zero page; For a 1.8432MHz 6502 including the JSR and RTS; fastest (>=":") = 29 cycles = 15.7uS; slowest (<":") = 40 cycles = 21.7uS; space skip = +21 cycles = +11.4uS; inc across page = +4 cycles = +2.2uS; the target address for the LDA at LAB_2CF4 becomes the BASIC execute pointer once the; block is copied to it's destination, any non zero page address will do at assembly; time, to assemble a three byte instruction.; page 0 initialisation table from $BC; increment and scan memoryLAB_2CEEINC Bpntrl ; increment BASIC execute pointer low byteBNE LAB_2CF4 ; branch if no carry; elseINC Bpntrh ; increment BASIC execute pointer high byte; page 0 initialisation table from $C2; scan memoryLAB_2CF4LDA $FFFF ; get byte to scan (addr set by call routine)CMP #TK_ELSE ; compare with the token for ELSEBEQ LAB_2D05 ; exit if ELSE, not numeric, carry setCMP #':' ; compare with ":"BCS LAB_2D05 ; exit if >= ":", not numeric, carry setCMP #' ' ; compare with " "BEQ LAB_2CEE ; if " " go do nextSEC ; set carry for SBCSBC #'0' ; subtract "0"SEC ; set carry for SBCSBC #$D0 ; subtract -"0"; clear carry if byte = "0"-"9"LAB_2D05RTS; page zero initialisation table $00-$12 inclusiveStrTab.byte $4C ; JMP opcode.word LAB_COLD ; initial warm start vector (cold start).byte $00 ; these bytes are not used by BASIC.word $0000 ;.word $0000 ;.word $0000 ;.byte $4C ; JMP opcode.word LAB_FCER ; initial user function vector ("Function call" error).byte $00 ; default NULL count.byte $00 ; clear terminal position.byte $00 ; default terminal width byte.byte $F2 ; default limit for TAB = 14.word Ram_base ; start of user RAMEndTabLAB_MSZM.byte $0D,$0A,"Memory size ",$00LAB_SMSG.byte " Bytes free",$0D,$0A,$0A.byte "Enhanced BASIC 2.22",$0A,$00; numeric constants and series; constants and series for LOG(n)LAB_25A0.byte $02 ; counter.byte $80,$19,$56,$62 ; 0.59898.byte $80,$76,$22,$F3 ; 0.96147;## .byte $80,$76,$22,$F1 ; 0.96147.byte $82,$38,$AA,$40 ; 2.88539;## .byte $82,$38,$AA,$45 ; 2.88539LAB_25AD.byte $80,$35,$04,$F3 ; 0.70711 1/root 2LAB_25B1.byte $81,$35,$04,$F3 ; 1.41421 root 2LAB_25B5.byte $80,$80,$00,$00 ; -0.5LAB_25B9.byte $80,$31,$72,$18 ; 0.69315 LOG(2); numeric PRINT constantsLAB_2947.byte $91,$43,$4F,$F8 ; 99999.9375 (max value with at least one decimal)LAB_294B.byte $94,$74,$23,$F7 ; 999999.4375 (max value before scientific notation)LAB_294F.byte $94,$74,$24,$00 ; 1000000; EXP(n) constants and seriesLAB_2AFA.byte $81,$38,$AA,$3B ; 1.4427 (1/LOG base 2 e)LAB_2AFE.byte $06 ; counter.byte $74,$63,$90,$8C ; 2.17023e-4.byte $77,$23,$0C,$AB ; 0.00124.byte $7A,$1E,$94,$00 ; 0.00968.byte $7C,$63,$42,$80 ; 0.05548.byte $7E,$75,$FE,$D0 ; 0.24023.byte $80,$31,$72,$15 ; 0.69315.byte $81,$00,$00,$00 ; 1.00000;## .byte $07 ; counter;## .byte $74,$94,$2E,$40 ; -1/7! (-1/5040);## .byte $77,$2E,$4F,$70 ; 1/6! ( 1/720);## .byte $7A,$88,$02,$6E ; -1/5! (-1/120);## .byte $7C,$2A,$A0,$E6 ; 1/4! ( 1/24);## .byte $7E,$AA,$AA,$50 ; -1/3! (-1/6);## .byte $7F,$7F,$FF,$FF ; 1/2! ( 1/2);## .byte $81,$80,$00,$00 ; -1/1! (-1/1);## .byte $81,$00,$00,$00 ; 1/0! ( 1/1); trigonometric constants and seriesLAB_2C78.byte $81,$49,$0F,$DB ; 1.570796371 (pi/2) as floating #LAB_2C84.byte $04 ; counter.byte $86,$1E,$D7,$FB ; 39.7109;## .byte $86,$1E,$D7,$BA ; 39.7109.byte $87,$99,$26,$65 ;-76.575;## .byte $87,$99,$26,$64 ;-76.575.byte $87,$23,$34,$58 ; 81.6022.byte $86,$A5,$5D,$E1 ;-41.3417;## .byte $86,$A5,$5D,$E0 ;-41.3417LAB_2C7C.byte $83,$49,$0F,$DB ; 6.28319 (2*pi) as floating #;## .byte $83,$49,$0F,$DA ; 6.28319 (2*pi) as floating #LAB_2CC9.byte $08 ; counter.byte $78,$3A,$C5,$37 ; 0.00285.byte $7B,$83,$A2,$5C ;-0.0160686.byte $7C,$2E,$DD,$4D ; 0.0426915.byte $7D,$99,$B0,$1E ;-0.0750429.byte $7D,$59,$ED,$24 ; 0.106409.byte $7E,$91,$72,$00 ;-0.142036.byte $7E,$4C,$B9,$73 ; 0.199926.byte $7F,$AA,$AA,$53 ;-0.333331;## .byte $08 ; counter;## .byte $78,$3B,$D7,$4A ; 1/17;## .byte $7B,$84,$6E,$02 ;-1/15;## .byte $7C,$2F,$C1,$FE ; 1/13;## .byte $7D,$9A,$31,$74 ;-1/11;## .byte $7D,$5A,$3D,$84 ; 1/9;## .byte $7E,$91,$7F,$C8 ;-1/7;## .byte $7E,$4C,$BB,$E4 ; 1/5;## .byte $7F,$AA,$AA,$6C ;-1/3LAB_1D96 = *+1 ; $00,$00 used for undefined variablesLAB_259C.byte $81,$00,$00,$00 ; 1.000000, used for INCLAB_2AFD.byte $81,$80,$00,$00 ; -1.00000, used for DEC. must be on the same page as +1.00; misc constantsLAB_1DF7.byte $90 ;-32768 (uses first three bytes from 0.5)LAB_2A96.byte $80,$00,$00,$00 ; 0.5LAB_2C80.byte $7F,$00,$00,$00 ; 0.25LAB_26B5.byte $84,$20,$00,$00 ; 10.0000 divide by 10 constant; This table is used in converting numbers to ASCII.LAB_2A9ALAB_2A9B = LAB_2A9A+1LAB_2A9C = LAB_2A9B+1.byte $FE,$79,$60 ; -100000.byte $00,$27,$10 ; 10000.byte $FF,$FC,$18 ; -1000.byte $00,$00,$64 ; 100.byte $FF,$FF,$F6 ; -10.byte $00,$00,$01 ; 1LAB_CTBL.word LAB_END-1 ; END.word LAB_FOR-1 ; FOR.word LAB_NEXT-1 ; NEXT.word LAB_DATA-1 ; DATA.word LAB_INPUT-1 ; INPUT.word LAB_DIM-1 ; DIM.word LAB_READ-1 ; READ.word LAB_LET-1 ; LET.word LAB_DEC-1 ; DEC new command.word LAB_GOTO-1 ; GOTO.word LAB_RUN-1 ; RUN.word LAB_IF-1 ; IF.word LAB_RESTORE-1 ; RESTORE modified command.word LAB_GOSUB-1 ; GOSUB.word LAB_RETIRQ-1 ; RETIRQ new command.word LAB_RETNMI-1 ; RETNMI new command.word LAB_RETURN-1 ; RETURN.word LAB_REM-1 ; REM.word LAB_STOP-1 ; STOP.word LAB_ON-1 ; ON modified command.word LAB_NULL-1 ; NULL modified command.word LAB_INC-1 ; INC new command.word LAB_WAIT-1 ; WAIT.word V_LOAD-1 ; LOAD.word V_SAVE-1 ; SAVE.word LAB_DEF-1 ; DEF.word LAB_POKE-1 ; POKE.word LAB_DOKE-1 ; DOKE new command.word LAB_CALL-1 ; CALL new command.word LAB_DO-1 ; DO new command.word LAB_LOOP-1 ; LOOP new command.word LAB_PRINT-1 ; PRINT.word LAB_CONT-1 ; CONT.word LAB_LIST-1 ; LIST.word LAB_CLEAR-1 ; CLEAR.word LAB_NEW-1 ; NEW.word LAB_WDTH-1 ; WIDTH new command.word LAB_GET-1 ; GET new command.word LAB_SWAP-1 ; SWAP new command.word LAB_BITSET-1 ; BITSET new command.word LAB_BITCLR-1 ; BITCLR new command.word LAB_IRQ-1 ; IRQ new command.word LAB_NMI-1 ; NMI new command.word LAB_BYE-1 ; BYE new command; function pre process routine tableLAB_FTPLLAB_FTPM = LAB_FTPL+$01.word LAB_PPFN-1 ; SGN(n) process numeric expression in ().word LAB_PPFN-1 ; INT(n) ".word LAB_PPFN-1 ; ABS(n) ".word LAB_EVEZ-1 ; USR(x) process any expression.word LAB_1BF7-1 ; FRE(x) ".word LAB_1BF7-1 ; POS(x) ".word LAB_PPFN-1 ; SQR(n) process numeric expression in ().word LAB_PPFN-1 ; RND(n) ".word LAB_PPFN-1 ; LOG(n) ".word LAB_PPFN-1 ; EXP(n) ".word LAB_PPFN-1 ; COS(n) ".word LAB_PPFN-1 ; SIN(n) ".word LAB_PPFN-1 ; TAN(n) ".word LAB_PPFN-1 ; ATN(n) ".word LAB_PPFN-1 ; PEEK(n) ".word LAB_PPFN-1 ; DEEK(n) ".word $0000 ; SADD() none.word LAB_PPFS-1 ; LEN($) process string expression in ().word LAB_PPFN-1 ; STR$(n) process numeric expression in ().word LAB_PPFS-1 ; VAL($) process string expression in ().word LAB_PPFS-1 ; ASC($) ".word LAB_PPFS-1 ; UCASE$($) ".word LAB_PPFS-1 ; LCASE$($) ".word LAB_PPFN-1 ; CHR$(n) process numeric expression in ().word LAB_BHSS-1 ; HEX$(n) ".word LAB_BHSS-1 ; BIN$(n) ".word $0000 ; BITTST() none.word LAB_MMPP-1 ; MAX() process numeric expression.word LAB_MMPP-1 ; MIN() ".word LAB_PPBI-1 ; PI advance pointer.word LAB_PPBI-1 ; TWOPI ".word $0000 ; VARPTR() none.word LAB_LRMS-1 ; LEFT$() process string expression.word LAB_LRMS-1 ; RIGHT$() ".word LAB_LRMS-1 ; MID$() "; action addresses for functionsLAB_FTBLLAB_FTBM = LAB_FTBL+$01.word LAB_SGN-1 ; SGN().word LAB_INT-1 ; INT().word LAB_ABS-1 ; ABS().word LAB_USR-1 ; USR().word LAB_FRE-1 ; FRE().word LAB_POS-1 ; POS().word LAB_SQR-1 ; SQR().word LAB_RND-1 ; RND() modified function.word LAB_LOG-1 ; LOG().word LAB_EXP-1 ; EXP().word LAB_COS-1 ; COS().word LAB_SIN-1 ; SIN().word LAB_TAN-1 ; TAN().word LAB_ATN-1 ; ATN().word LAB_PEEK-1 ; PEEK().word LAB_DEEK-1 ; DEEK() new function.word LAB_SADD-1 ; SADD() new function.word LAB_LENS-1 ; LEN().word LAB_STRS-1 ; STR$().word LAB_VAL-1 ; VAL().word LAB_ASC-1 ; ASC().word LAB_UCASE-1 ; UCASE$() new function.word LAB_LCASE-1 ; LCASE$() new function.word LAB_CHRS-1 ; CHR$().word LAB_HEXS-1 ; HEX$() new function.word LAB_BINS-1 ; BIN$() new function.word LAB_BTST-1 ; BITTST() new function.word LAB_MAX-1 ; MAX() new function.word LAB_MIN-1 ; MIN() new function.word LAB_PI-1 ; PI new function.word LAB_TWOPI-1 ; TWOPI new function.word LAB_VARPTR-1 ; VARPTR() new function.word LAB_LEFT-1 ; LEFT$().word LAB_RIGHT-1 ; RIGHT$().word LAB_MIDS-1 ; MID$(); hierarchy and action addresses for operatorLAB_OPPT.byte $79 ; +.word LAB_ADD-1.byte $79 ; -.word LAB_SUBTRACT-1.byte $7B ; *.word LAB_MULTIPLY-1.byte $7B ; /.word LAB_DIVIDE-1.byte $7F ; ^.word LAB_POWER-1.byte $50 ; AND.word LAB_AND-1.byte $46 ; EOR new operator.word LAB_EOR-1.byte $46 ; OR.word LAB_OR-1.byte $56 ; >> new operator.word LAB_RSHIFT-1.byte $56 ; << new operator.word LAB_LSHIFT-1.byte $7D ; >.word LAB_GTHAN-1.byte $5A ; =.word LAB_EQUAL-1.byte $64 ; <.word LAB_LTHAN-1; keywords start with ..; this is the first character table and must be in alphabetic orderTAB_1STC.byte "*".byte "+".byte "-".byte "/".byte "<".byte "=".byte ">".byte "?".byte "A".byte "B".byte "C".byte "D".byte "E".byte "F".byte "G".byte "H".byte "I".byte "L".byte "M".byte "N".byte "O".byte "P".byte "R".byte "S".byte "T".byte "U".byte "V".byte "W".byte "^".byte $00 ; table terminator; pointers to keyword tablesTAB_CHRT.word TAB_STAR ; table for "*".word TAB_PLUS ; table for "+".word TAB_MNUS ; table for "-".word TAB_SLAS ; table for "/".word TAB_LESS ; table for "<".word TAB_EQUL ; table for "=".word TAB_MORE ; table for ">".word TAB_QEST ; table for "?".word TAB_ASCA ; table for "A".word TAB_ASCB ; table for "B".word TAB_ASCC ; table for "C".word TAB_ASCD ; table for "D".word TAB_ASCE ; table for "E".word TAB_ASCF ; table for "F".word TAB_ASCG ; table for "G".word TAB_ASCH ; table for "H".word TAB_ASCI ; table for "I".word TAB_ASCL ; table for "L".word TAB_ASCM ; table for "M".word TAB_ASCN ; table for "N".word TAB_ASCO ; table for "O".word TAB_ASCP ; table for "P".word TAB_ASCR ; table for "R".word TAB_ASCS ; table for "S".word TAB_ASCT ; table for "T".word TAB_ASCU ; table for "U".word TAB_ASCV ; table for "V".word TAB_ASCW ; table for "W".word TAB_POWR ; table for "^"; tables for each start character, note if a longer keyword with the same start; letters as a shorter one exists then it must come first, else the list is in; alphabetical order as follows ..; [keyword,token; [keyword,token]]; end marker (#$00)TAB_STAR.byte TK_MUL,$00 ; *TAB_PLUS.byte TK_PLUS,$00 ; +TAB_MNUS.byte TK_MINUS,$00 ; -TAB_SLAS.byte TK_DIV,$00 ; /TAB_LESSLBB_LSHIFT.byte "<",TK_LSHIFT ; << note - "<<" must come before "<".byte TK_LT ; <.byte $00TAB_EQUL.byte TK_EQUAL,$00 ; =TAB_MORELBB_RSHIFT.byte ">",TK_RSHIFT ; >> note - ">>" must come before ">".byte TK_GT ; >.byte $00TAB_QEST.byte TK_PRINT,$00 ; ?TAB_ASCALBB_ABS.byte "BS(",TK_ABS ; ABS(LBB_AND.byte "ND",TK_AND ; ANDLBB_ASC.byte "SC(",TK_ASC ; ASC(LBB_ATN.byte "TN(",TK_ATN ; ATN(.byte $00TAB_ASCBLBB_BINS.byte "IN$(",TK_BINS ; BIN$(LBB_BITCLR.byte "ITCLR",TK_BITCLR ; BITCLRLBB_BITSET.byte "ITSET",TK_BITSET ; BITSETLBB_BITTST.byte "ITTST(",TK_BITTST; BITTST(LBB_BYE.byte "YE", TK_BYE ; BYE.byte $00TAB_ASCCLBB_CALL.byte "ALL",TK_CALL ; CALLLBB_CHRS.byte "HR$(",TK_CHRS ; CHR$(LBB_CLEAR.byte "LEAR",TK_CLEAR ; CLEARLBB_CONT.byte "ONT",TK_CONT ; CONTLBB_COS.byte "OS(",TK_COS ; COS(.byte $00TAB_ASCDLBB_DATA.byte "ATA",TK_DATA ; DATALBB_DEC.byte "EC",TK_DEC ; DECLBB_DEEK.byte "EEK(",TK_DEEK ; DEEK(LBB_DEF.byte "EF",TK_DEF ; DEFLBB_DIM.byte "IM",TK_DIM ; DIMLBB_DOKE.byte "OKE",TK_DOKE ; DOKE note - "DOKE" must come before "DO"LBB_DO.byte "O",TK_DO ; DO.byte $00TAB_ASCELBB_ELSE.byte "LSE",TK_ELSE ; ELSELBB_END.byte "ND",TK_END ; ENDLBB_EOR.byte "OR",TK_EOR ; EORLBB_EXP.byte "XP(",TK_EXP ; EXP(.byte $00TAB_ASCFLBB_FN.byte "N",TK_FN ; FNLBB_FOR.byte "OR",TK_FOR ; FORLBB_FRE.byte "RE(",TK_FRE ; FRE(.byte $00TAB_ASCGLBB_GET.byte "ET",TK_GET ; GETLBB_GOSUB.byte "OSUB",TK_GOSUB ; GOSUBLBB_GOTO.byte "OTO",TK_GOTO ; GOTO.byte $00TAB_ASCHLBB_HEXS.byte "EX$(",TK_HEXS ; HEX$(.byte $00TAB_ASCILBB_IF.byte "F",TK_IF ; IFLBB_INC.byte "NC",TK_INC ; INCLBB_INPUT.byte "NPUT",TK_INPUT ; INPUTLBB_INT.byte "NT(",TK_INT ; INT(LBB_IRQ.byte "RQ",TK_IRQ ; IRQ.byte $00TAB_ASCLLBB_LCASES.byte "CASE$(",TK_LCASES; LCASE$(LBB_LEFTS.byte "EFT$(",TK_LEFTS ; LEFT$(LBB_LEN.byte "EN(",TK_LEN ; LEN(LBB_LET.byte "ET",TK_LET ; LETLBB_LIST.byte "IST",TK_LIST ; LISTLBB_LOAD.byte "OAD",TK_LOAD ; LOADLBB_LOG.byte "OG(",TK_LOG ; LOG(LBB_LOOP.byte "OOP",TK_LOOP ; LOOP.byte $00TAB_ASCMLBB_MAX.byte "AX(",TK_MAX ; MAX(LBB_MIDS.byte "ID$(",TK_MIDS ; MID$(LBB_MIN.byte "IN(",TK_MIN ; MIN(.byte $00TAB_ASCNLBB_NEW.byte "EW",TK_NEW ; NEWLBB_NEXT.byte "EXT",TK_NEXT ; NEXTLBB_NMI.byte "MI",TK_NMI ; NMILBB_NOT.byte "OT",TK_NOT ; NOTLBB_NULL.byte "ULL",TK_NULL ; NULL.byte $00TAB_ASCOLBB_OFF.byte "FF",TK_OFF ; OFFLBB_ON.byte "N",TK_ON ; ONLBB_OR.byte "R",TK_OR ; OR.byte $00TAB_ASCPLBB_PEEK.byte "EEK(",TK_PEEK ; PEEK(LBB_PI.byte "I",TK_PI ; PILBB_POKE.byte "OKE",TK_POKE ; POKELBB_POS.byte "OS(",TK_POS ; POS(LBB_PRINT.byte "RINT",TK_PRINT ; PRINT.byte $00TAB_ASCRLBB_READ.byte "EAD",TK_READ ; READLBB_REM.byte "EM",TK_REM ; REMLBB_RESTORE.byte "ESTORE",TK_RESTORE; RESTORELBB_RETIRQ.byte "ETIRQ",TK_RETIRQ ; RETIRQLBB_RETNMI.byte "ETNMI",TK_RETNMI ; RETNMILBB_RETURN.byte "ETURN",TK_RETURN ; RETURNLBB_RIGHTS.byte "IGHT$(",TK_RIGHTS; RIGHT$(LBB_RND.byte "ND(",TK_RND ; RND(LBB_RUN.byte "UN",TK_RUN ; RUN.byte $00TAB_ASCSLBB_SADD.byte "ADD(",TK_SADD ; SADD(LBB_SAVE.byte "AVE",TK_SAVE ; SAVELBB_SGN.byte "GN(",TK_SGN ; SGN(LBB_SIN.byte "IN(",TK_SIN ; SIN(LBB_SPC.byte "PC(",TK_SPC ; SPC(LBB_SQR.byte "QR(",TK_SQR ; SQR(LBB_STEP.byte "TEP",TK_STEP ; STEPLBB_STOP.byte "TOP",TK_STOP ; STOPLBB_STRS.byte "TR$(",TK_STRS ; STR$(LBB_SWAP.byte "WAP",TK_SWAP ; SWAP.byte $00TAB_ASCTLBB_TAB.byte "AB(",TK_TAB ; TAB(LBB_TAN.byte "AN(",TK_TAN ; TAN(LBB_THEN.byte "HEN",TK_THEN ; THENLBB_TO.byte "O",TK_TO ; TOLBB_TWOPI.byte "WOPI",TK_TWOPI ; TWOPI.byte $00TAB_ASCULBB_UCASES.byte "CASE$(",TK_UCASES; UCASE$(LBB_UNTIL.byte "NTIL",TK_UNTIL ; UNTILLBB_USR.byte "SR(",TK_USR ; USR(.byte $00TAB_ASCVLBB_VAL.byte "AL(",TK_VAL ; VAL(LBB_VPTR.byte "ARPTR(",TK_VPTR ; VARPTR(.byte $00TAB_ASCWLBB_WAIT.byte "AIT",TK_WAIT ; WAITLBB_WHILE.byte "HILE",TK_WHILE ; WHILELBB_WIDTH.byte "IDTH",TK_WIDTH ; WIDTH.byte $00TAB_POWR.byte TK_POWER,$00 ; ^; new decode table for LIST; Table is ..; byte - keyword length, keyword first character; word - pointer to rest of keyword from dictionary; note if length is 1 then the pointer is ignoredLAB_KEYT.byte 3,'E'.word LBB_END ; END.byte 3,'F'.word LBB_FOR ; FOR.byte 4,'N'.word LBB_NEXT ; NEXT.byte 4,'D'.word LBB_DATA ; DATA.byte 5,'I'.word LBB_INPUT ; INPUT.byte 3,'D'.word LBB_DIM ; DIM.byte 4,'R'.word LBB_READ ; READ.byte 3,'L'.word LBB_LET ; LET.byte 3,'D'.word LBB_DEC ; DEC.byte 4,'G'.word LBB_GOTO ; GOTO.byte 3,'R'.word LBB_RUN ; RUN.byte 2,'I'.word LBB_IF ; IF.byte 7,'R'.word LBB_RESTORE ; RESTORE.byte 5,'G'.word LBB_GOSUB ; GOSUB.byte 6,'R'.word LBB_RETIRQ ; RETIRQ.byte 6,'R'.word LBB_RETNMI ; RETNMI.byte 6,'R'.word LBB_RETURN ; RETURN.byte 3,'R'.word LBB_REM ; REM.byte 4,'S'.word LBB_STOP ; STOP.byte 2,'O'.word LBB_ON ; ON.byte 4,'N'.word LBB_NULL ; NULL.byte 3,'I'.word LBB_INC ; INC.byte 4,'W'.word LBB_WAIT ; WAIT.byte 4,'L'.word LBB_LOAD ; LOAD.byte 4,'S'.word LBB_SAVE ; SAVE.byte 3,'D'.word LBB_DEF ; DEF.byte 4,'P'.word LBB_POKE ; POKE.byte 4,'D'.word LBB_DOKE ; DOKE.byte 4,'C'.word LBB_CALL ; CALL.byte 2,'D'.word LBB_DO ; DO.byte 4,'L'.word LBB_LOOP ; LOOP.byte 5,'P'.word LBB_PRINT ; PRINT.byte 4,'C'.word LBB_CONT ; CONT.byte 4,'L'.word LBB_LIST ; LIST.byte 5,'C'.word LBB_CLEAR ; CLEAR.byte 3,'N'.word LBB_NEW ; NEW.byte 5,'W'.word LBB_WIDTH ; WIDTH.byte 3,'G'.word LBB_GET ; GET.byte 4,'S'.word LBB_SWAP ; SWAP.byte 6,'B'.word LBB_BITSET ; BITSET.byte 6,'B'.word LBB_BITCLR ; BITCLR.byte 3,'I'.word LBB_IRQ ; IRQ.byte 3,'N'.word LBB_NMI ; NMI.byte 3,'B'.word LBB_BYE ; BYE; secondary commands (can't start a statement).byte 4,'T'.word LBB_TAB ; TAB.byte 4,'E'.word LBB_ELSE ; ELSE.byte 2,'T'.word LBB_TO ; TO.byte 2,'F'.word LBB_FN ; FN.byte 4,'S'.word LBB_SPC ; SPC.byte 4,'T'.word LBB_THEN ; THEN.byte 3,'N'.word LBB_NOT ; NOT.byte 4,'S'.word LBB_STEP ; STEP.byte 5,'U'.word LBB_UNTIL ; UNTIL.byte 5,'W'.word LBB_WHILE ; WHILE.byte 3,'O'.word LBB_OFF ; OFF; opperators.byte 1,'+'.word $0000 ; +.byte 1,'-'.word $0000 ; -.byte 1,'*'.word $0000 ; *.byte 1,'/'.word $0000 ; /.byte 1,'^'.word $0000 ; ^.byte 3,'A'.word LBB_AND ; AND.byte 3,'E'.word LBB_EOR ; EOR.byte 2,'O'.word LBB_OR ; OR.byte 2,'>'.word LBB_RSHIFT ; >>.byte 2,'<'.word LBB_LSHIFT ; <<.byte 1,'>'.word $0000 ; >.byte 1,'='.word $0000 ; =.byte 1,'<'.word $0000 ; <; functions.byte 4,'S' ;.word LBB_SGN ; SGN.byte 4,'I' ;.word LBB_INT ; INT.byte 4,'A' ;.word LBB_ABS ; ABS.byte 4,'U' ;.word LBB_USR ; USR.byte 4,'F' ;.word LBB_FRE ; FRE.byte 4,'P' ;.word LBB_POS ; POS.byte 4,'S' ;.word LBB_SQR ; SQR.byte 4,'R' ;.word LBB_RND ; RND.byte 4,'L' ;.word LBB_LOG ; LOG.byte 4,'E' ;.word LBB_EXP ; EXP.byte 4,'C' ;.word LBB_COS ; COS.byte 4,'S' ;.word LBB_SIN ; SIN.byte 4,'T' ;.word LBB_TAN ; TAN.byte 4,'A' ;.word LBB_ATN ; ATN.byte 5,'P' ;.word LBB_PEEK ; PEEK.byte 5,'D' ;.word LBB_DEEK ; DEEK.byte 5,'S' ;.word LBB_SADD ; SADD.byte 4,'L' ;.word LBB_LEN ; LEN.byte 5,'S' ;.word LBB_STRS ; STR$.byte 4,'V' ;.word LBB_VAL ; VAL.byte 4,'A' ;.word LBB_ASC ; ASC.byte 7,'U' ;.word LBB_UCASES ; UCASE$.byte 7,'L' ;.word LBB_LCASES ; LCASE$.byte 5,'C' ;.word LBB_CHRS ; CHR$.byte 5,'H' ;.word LBB_HEXS ; HEX$.byte 5,'B' ;.word LBB_BINS ; BIN$.byte 7,'B' ;.word LBB_BITTST ; BITTST.byte 4,'M' ;.word LBB_MAX ; MAX.byte 4,'M' ;.word LBB_MIN ; MIN.byte 2,'P' ;.word LBB_PI ; PI.byte 5,'T' ;.word LBB_TWOPI ; TWOPI.byte 7,'V' ;.word LBB_VPTR ; VARPTR.byte 6,'L' ;.word LBB_LEFTS ; LEFT$.byte 7,'R' ;.word LBB_RIGHTS ; RIGHT$.byte 5,'M' ;.word LBB_MIDS ; MID$; BASIC messages, mostly error messagesLAB_BAER.word ERR_NF ;$00 NEXT without FOR.word ERR_SN ;$02 syntax.word ERR_RG ;$04 RETURN without GOSUB.word ERR_OD ;$06 out of data.word ERR_FC ;$08 function call.word ERR_OV ;$0A overflow.word ERR_OM ;$0C out of memory.word ERR_US ;$0E undefined statement.word ERR_BS ;$10 array bounds.word ERR_DD ;$12 double dimension array.word ERR_D0 ;$14 divide by 0.word ERR_ID ;$16 illegal direct.word ERR_TM ;$18 type mismatch.word ERR_LS ;$1A long string.word ERR_ST ;$1C string too complex.word ERR_CN ;$1E continue error.word ERR_UF ;$20 undefined function.word ERR_LD ;$22 LOOP without DO; I may implement these two errors to force definition of variables and; dimensioning of arrays before use.; .word ERR_UV ;$24 undefined variable; the above error has been tested and works (see code and comments below LAB_1D8B); .word ERR_UA ;$26 undimensioned arrayERR_NF .byte "NEXT without FOR",$00ERR_SN .byte "Syntax",$00ERR_RG .byte "RETURN without GOSUB",$00ERR_OD .byte "Out of DATA",$00ERR_FC .byte "Function call",$00ERR_OV .byte "Overflow",$00ERR_OM .byte "Out of memory",$00ERR_US .byte "Undefined statement",$00ERR_BS .byte "Array bounds",$00ERR_DD .byte "Double dimension",$00ERR_D0 .byte "Divide by zero",$00ERR_ID .byte "Illegal direct",$00ERR_TM .byte "Type mismatch",$00ERR_LS .byte "String too long",$00ERR_ST .byte "String too complex",$00ERR_CN .byte "Can't continue",$00ERR_UF .byte "Undefined function",$00ERR_LD .byte "LOOP without DO",$00;ERR_UV .byte "Undefined variable",$00; the above error has been tested and works (see code and comments below LAB_1D8B);ERR_UA .byte "Undimensioned array",$00LAB_BMSG .byte $0D,$0A,"Break",$00LAB_EMSG .byte " Error",$00LAB_LMSG .byte " in line ",$00LAB_RMSG .byte $0D,$0A,"Ready",$0D,$0A,$00LAB_IMSG .byte " Extra ignored",$0D,$0A,$00LAB_REDO .byte " Redo from start",$0D,$0A,$00AA_end_basicvecbrki=$0102org $F000cpu rtf65002jsr (RequestIOFocus>>2)jsr (ClearScreen>>2)jsr (HomeCursor>>2)lda #0 ; turn off keyboard echoingjsr (SetKeyboardEcho>>2)emmcpu W65C02LDA #<V__INPTSTA VEC_INLDA #>V__INPTSTA VEC_IN+1LDA #<V__OUTPSTA VEC_OUTLDA #>V__OUTPSTA VEC_OUT+1LDA #<LOAD3STA VEC_LDLDA #>LOAD3STA VEC_LD+1LDA #<SAVE3STA VEC_SVLDA #>SAVE3STA VEC_SV+1JMP LAB_COLD; ===== Output character to the console from register r1; (Preserves all registers.); Does a far indirect subroutine call to native code.;V__OUTP:natcpu rtf65002phajsr (DisplayChar>>2) ; should not trash charplaemmcpu W65C02and #$FF ; set Z, N according to char in accumulatorrts; ===== Output character to the console from register r1; (Preserves all registers.); Does a far indirect subroutine call to native code.;V__OUTP816:natcpu rtf65002phajsr (DisplayChar>>2) ; should not trash charplaclcxcecpu W65C02rts; ===== Input a character from the console into register R1; set C if a char is available; clear C if no char is available;;V__INPT:natcpu rtf65002jsr (KeybdGetChar>>2)cmp #-1beq .0001emmcpu W65C02secrts.0001:cpu rtf65002emmcpu W65C02clcrts; ===== Input a character from the console into register R1; clear C if a char is available; set C if no char is available;;V__INPT816:natcpu rtf65002jsr (KeybdGetChar>>2)cmp #-1beq .001clcxcecpu W65C02clcrts.001:cpu rtf65002clcxcecpu W65C02secrtsResched816:natcpu rtf65002int #2clcxcecpu W65C816Srts;*;* ===== Input a character from the host into register r1 (or;* return Zero status if there's no character available).;*cpu rtf65002AUXIN_INIT:stz INPNDXlda #FILENAMEldx #FILEBUF<<2ldy #$3800 ; max lengthjsr (LoadFile>>2)rtscpu W65C02AUXIN:natcpu RTF65002phxldx INPNDXlb r1,FILEBUF<<2,xcmp #$1A ; end of file ?bne AUXIN1secxcecpu W65C02; restore the regular outputlda $E0sta VEC_INlda $E1sta VEC_IN+1lda #$0Dsecrtscpu RTF65002AUXIN1:inxstx INPNDXplxemmcpu W65C02secrts; ===== Output character to the host (Port 2) from register r1; (Preserves all registers.);AUXOUT_INIT:stz OUTNDXrtsAUXOUT:cpu W65C02natcpu RTF65002phxldx OUTNDXsb r1,FILEBUF<<2,xinxstx OUTNDXplxemmcpu W65C02rtscpu RTF65002AUXOUT_FLUSH:lda #FILENAMEldx #FILEBUF<<2ldy OUTNDXjsr (SaveFile>>2)rtsLOAD3:jsr LAB_EVEZ ; get a string parameterlda Dtypefbpl LOAD4ldy #0lda (des_pl),ysta str_lninylda (des_pl),ysta str_plinylda (des_ph),ysta str_phnatcpu RTF65002lb r4,str_ph ; r4 = pointer to file nameasl r4,r4,#8orb r4,r4,str_pllda #8 ; 8 words to zero outldx #0 ; the value we want to useldy #FILENAME ; the target addressstos ; zap the memorylda str_ln ; number of bytes to moveld r2,r4 ; x = sourceldy #FILENAME ; y = destLOAD2:lb r4,0,r2sb r4,0,r3inxinydeabne LOAD2jsr AUXIN_INIT ; initialize for file input (get the file)emmcpu W65C02; Save off the output vector and switch output to the; auxiallry output routine.seilda VEC_IN ; save off the output vector to $E0sta $E0lda VEC_IN+1sta $E1lda #<AUXIN ; switch to the file output routinesta VEC_INlda #>AUXINsta VEC_IN+1jsr LAB_22B6 ; pop string descriptor from stackLOAD4:rtsSAVE3:JSR LAB_EVEZ ; get string parameterlda Dtypefbpl SAVE4 ; branch if not a stringldy #0lda (des_pl),ysta str_lninylda (des_pl),ysta str_plinylda (des_ph),ysta str_phnatcpu RTF65002jsr AUXOUT_INIT ; initialize for file outputlb r4,str_ph ; r4 = pointer to file nameasl r4,r4,#8orb r4,r4,str_pllda #8 ; 8 words to zero outldx #0 ; the value we want to useldy #FILENAME ; the target addressstos ; zap the memorylda str_ln ; number of bytes to moveld r2,r4 ; x = sourceldy #FILENAME ; y = destSAVE2:lb r4,0,r2sb r4,0,r3inxinydeabne SAVE2emmcpu W65C02; Save off the output vector and switch output to the; auxiallry output routine.seilda VEC_OUT ; save off the output vector to $E0sta $E0lda VEC_OUT+1sta $E1lda #<AUXOUT ; switch to the file output routinesta VEC_OUTlda #>AUXOUTsta VEC_OUT+1; Invoke the LIST commandlda #0jsr LAB_LISTlda #$1A ; spit out end-of-file markerjsr AUXOUT; restore the regular outputlda $E0sta VEC_OUTlda $E1sta VEC_OUT+1natcpu RTF65002jsr AUXOUT_FLUSHemmcpu W65C02jsr LAB_22B6 ; pop string descriptor from stackSAVE4:rtscpu rtf65002outchar:jsr (DisplayChar>>2) ; should not trash charrtscpu rtf65002ICacheIA816:natjsr (ICacheInvalidateAll>>2)emm816rts;------------------------------------------------------------------------------;------------------------------------------------------------------------------ICacheIL816:natjsr (ICacheInvalidateLine>>2)emm816rts;==============================================================================;==============================================================================SPIMASTER EQU 0xFFDC0500SPI_MASTER_VERSION_REG EQU 0x00SPI_MASTER_CONTROL_REG EQU 0x01SPI_TRANS_TYPE_REG EQU 0x02SPI_TRANS_CTRL_REG EQU 0x03SPI_TRANS_STATUS_REG EQU 0x04SPI_TRANS_ERROR_REG EQU 0x05SPI_DIRECT_ACCESS_DATA_REG EQU 0x06SPI_SD_SECT_7_0_REG EQU 0x07SPI_SD_SECT_15_8_REG EQU 0x08SPI_SD_SECT_23_16_REG EQU 0x09SPI_SD_SECT_31_24_REG EQU 0x0aSPI_RX_FIFO_DATA_REG EQU 0x10SPI_RX_FIFO_DATA_COUNT_MSB EQU 0x12SPI_RX_FIFO_DATA_COUNT_LSB EQU 0x13SPI_RX_FIFO_CTRL_REG EQU 0x14SPI_TX_FIFO_DATA_REG EQU 0x20SPI_TX_FIFO_CTRL_REG EQU 0x24SPI_RESP_BYTE1 EQU 0x30SPI_RESP_BYTE2 EQU 0x31SPI_RESP_BYTE3 EQU 0x32SPI_RESP_BYTE4 EQU 0x33SPI_INIT_SD EQU 0x01SPI_TRANS_START EQU 0x01SPI_TRANS_BUSY EQU 0x01SPI_INIT_NO_ERROR EQU 0x00SPI_READ_NO_ERROR EQU 0x00SPI_WRITE_NO_ERROR EQU 0x00RW_READ_SD_BLOCK EQU 0x02RW_WRITE_SD_BLOCK EQU 0x03;; Initialize the SD card; Returns; acc = 0 if successful, 1 otherwise; Z=1 if successful, otherwise Z=0;message "spi_init"spi_initlda #SPI_INIT_SDsta SPIMASTER+SPI_TRANS_TYPE_REGlda #SPI_TRANS_STARTsta SPIMASTER+SPI_TRANS_CTRL_REGnopspi_init1lda SPIMASTER+SPI_TRANS_STATUS_REGnopnopcmp #SPI_TRANS_BUSYbeq spi_init1lda SPIMASTER+SPI_TRANS_ERROR_REGand #3cmp #SPI_INIT_NO_ERRORbne spi_error; lda #spi_init_ok_msg; jsr DisplayStringBlda #0rtsspi_error; jsr DisplayByte; lda #spi_init_error_msg; jsr DisplayStringB; lda SPIMASTER+SPI_RESP_BYTE1; jsr DisplayByte; lda SPIMASTER+SPI_RESP_BYTE2; jsr DisplayByte; lda SPIMASTER+SPI_RESP_BYTE3; jsr DisplayByte; lda SPIMASTER+SPI_RESP_BYTE4; jsr DisplayBytelda #1rtsspi_delay:nopnoprts; SPI read sector;; r1= sector number to read; r2= address to place read data; Returns:; r1 = 0 if successful;spi_read_sector:phxphypush r4sta SPIMASTER+SPI_SD_SECT_7_0_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_15_8_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_23_16_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_31_24_REGld r4,#20 ; retry countspi_read_retry:; Force the reciever fifo to be empty, in case a prior error leaves it; in an unknown state.lda #1sta SPIMASTER+SPI_RX_FIFO_CTRL_REGlda #RW_READ_SD_BLOCKsta SPIMASTER+SPI_TRANS_TYPE_REGlda #SPI_TRANS_STARTsta SPIMASTER+SPI_TRANS_CTRL_REGnopspi_read_sect1:lda SPIMASTER+SPI_TRANS_STATUS_REGjsr spi_delay ; just a delay between consecutive status reg readscmp #SPI_TRANS_BUSYbeq spi_read_sect1lda SPIMASTER+SPI_TRANS_ERROR_REGlsrlsrand #3cmp #SPI_READ_NO_ERRORbne spi_read_errorldy #512 ; read 512 bytes from fifospi_read_sect2:lda SPIMASTER+SPI_RX_FIFO_DATA_REGsb r1,0,xinxdeybne spi_read_sect2lda #0bra spi_read_retspi_read_error:dec r4bne spi_read_retry; jsr DisplayByte; lda #spi_read_error_msg; jsr DisplayStringBlda #1spi_read_ret:pop r4plyplxrts; SPI write sector;; r1= sector number to write; r2= address to get data from; Returns:; r1 = 0 if successful;spi_write_sector:phxphypha; Force the transmitter fifo to be empty, in case a prior error leaves it; in an unknown state.lda #1sta SPIMASTER+SPI_TX_FIFO_CTRL_REGnop ; give I/O time to respondnop; now fill up the transmitter fifoldy #512spi_write_sect1:lb r1,0,xsta SPIMASTER+SPI_TX_FIFO_DATA_REGnop ; give the I/O time to respondnopinxdeybne spi_write_sect1; set the sector number in the spi master address registersplasta SPIMASTER+SPI_SD_SECT_7_0_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_15_8_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_23_16_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_31_24_REG; issue the write commandlda #RW_WRITE_SD_BLOCKsta SPIMASTER+SPI_TRANS_TYPE_REGlda #SPI_TRANS_STARTsta SPIMASTER+SPI_TRANS_CTRL_REGnopspi_write_sect2:lda SPIMASTER+SPI_TRANS_STATUS_REGnop ; just a delay between consecutive status reg readsnopcmp #SPI_TRANS_BUSYbeq spi_write_sect2lda SPIMASTER+SPI_TRANS_ERROR_REGlsr r1,r1,#4and #3cmp #SPI_WRITE_NO_ERRORbne spi_write_errorlda #0bra spi_write_retspi_write_error:; jsr DisplayByte; lda #spi_write_error_msg; jsr DisplayStringBlda #1spi_write_ret:plyplxrtscpu W65C816Sbrk_rout:phb ;save DBphd ;save DPrep #%00110000 ;16 bit registersphaphxphyjmp (vecbrki) ;indirect vectorbrk1:rep #%00110000 ;16 bit registersplyplxplapldplbrticpu W65C02org $F400jmp V__INPT816jmp LAB_BYEjmp V__OUTP816jmp Resched816cpu RTF65002org $F500jsr (RequestIOFocus>>2)jsr (ClearScreen>>2)jsr (HomeCursor>>2)lda #0 ; turn off keyboard echoingjsr (SetKeyboardEcho>>2); trs r0,cc ; turn caches offclcxcecpu W65C816Srep #%00110000 ;16 bit registersmem 16ndx 16lda #brk1 ; initialize the break routine vectorsta vecbrkijmp $008000org $FFE6dw brk_rout

