diff secb.s @ 0:605ff82c4618

Initial check in with cleaned up sources This is the initial check in the source code in a state where it builds byte accurate copies of all the various ROM versions included.
author William Astle <lost@l-w.ca>
date Sat, 08 Dec 2018 19:57:01 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/secb.s	Sat Dec 08 19:57:01 2018 -0700
@@ -0,0 +1,11797 @@
+                *pragma nolist
+                include defs.s
+DC0DC           equ 0xC0DC                      ; needed for Disk Basic path jump backs
+                *pragma list
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; EXTENDED COLOR BASIC ROM area
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+                org EXBAS
+                fcc 'EX'                        ; magic number that Color Basic uses to identify the presence of Extended Basic
+L8002           ldx #L80DE                      ; point to command interpretation table information
+                ldu #COMVEC+10                  ; point to command interpretation table location
+                ldb #10                         ; 10 bytes to move
+                jsr LA59A                       ; copy command interpretation table
+                ldx #LB277                      ; initialize Disk Basic's entries to error
+                stx 3,u
+                stx 8,u
+                ldx #XIRQSV                     ; set up IRQ service routine
+                stx IRQVEC+1
+                ldx ZERO                        ; reset the TIMER value
+                stx TIMVAL
+                jsr XVEC18                      ; do a bunch of initialization
+                ldd #0x2c05                     ; initialize DLOAD baud rate constant and timeout
+                std DLBAUD
+                ldx #USR0                       ; set up pointer to USR routine addresses
+                stx USRADR
+                ldu #LB44A                      ; set up USR routine addresses to "FC error"
+                ldb #10                         ; there are 10 routines
+L8031           stu ,x++                        ; set a routine to FC error
+                decb                            ; done all?
+                bne L8031                       ; brif not
+                lda #0x7e                       ; op code of JMP extended (for RAM hook intialization)
+                sta RVEC20                      ; command interpretation loop
+                ldx #XVEC20
+                stx RVEC20+1
+                sta RVEC15                      ; expression evaluation
+                ldx #XVEC15
+                stx RVEC15+1
+                sta RVEC19                      ; number parsing
+                ldx #XVEC19
+                stx RVEC19+1
+                sta RVEC9                       ; PRINT
+                ldx #XVEC9
+                stx RVEC9+1
+                sta RVEC17                      ; error handler
+                ldx #XVEC17
+                stx RVEC17+1
+                sta RVEC4                       ; generic input
+                ldx #XVEC4
+                stx RVEC4+1
+                sta RVEC3                       ; generic output
+                ldx #XVEC3
+                stx RVEC3+1
+                sta RVEC8                       ; close file
+                ldx #XVEC8
+                stx RVEC8+1
+                sta RVEC23                      ; tokenize line
+                ldx #XVEC23
+                stx RVEC23+1
+                sta RVEC18                      ; RUN
+                ldx #XVEC18
+                stx RVEC18+1
+                sta EXPJMP                      ; exponentiation
+                ldx #L8489
+                stx EXPJMP+1
+                jsr L96E6                       ; initialize graphics stuff
+                lda PIA0+3                      ; enable 60Hz interrupt
+                ora #1
+                sta PIA0+3
+                ldx #'D*256+'K                  ; magic number for a Disk Basic ROM
+                cmpx DOSBAS                     ; do we have a Disk Basic ROM?
+                lbeq DOSBAS+2                   ; brif so - launch it
+                andcc #0xaf                     ; enable interrupts
+L80B2           ldx #L80E8-1                    ; show sign on message
+                jsr STRINOUT
+L80B8           ldx #XBWMST                     ; install warm start handler
+                stx RSTVEC
+                jmp LA0E2                       ; set up warm start flag and launch immediate mode
+; Extended Basic warm start code
+XBWMST          fcb 0xff                        ; mark routine as invalid so that ROMs are always copied to RAM on RESET
+                clr PLYTMR                      ; cancel any PLAY command in progress
+                clr PLYTMR+1
+                lda PIA0+3                      ; enable 60Hz interrupt
+                ora #1
+                sta PIA0+3
+                jmp BAWMST                      ; let Color Basic's warm start process run
+; This code is to fix the famous PCLEAR bug. It replaces dead code in the 1.0 ROM. This patch corrects
+; the input pointer so that it points to the correct place after the program has been relocated by
+; PCLEAR instead of continuing with something that, in the best case, is a syntax error.
+L80D0           lda CURLIN                      ; immediate mode?
+                inca
+                beq L80DD                       ; brif so
+                tfr y,d                         ; save offset to D
+                subd TXTTAB                     ; see how far into the program we are
+                addd CHARAD                     ; now adjust the input pointer based on that
+                std CHARAD                      ; save corrected input pointer
+L80DD           rts
+L80DE           fcb 25                          ; 25 Extended Basic commands
+                fdb L8183                       ; reserved word table (commands)
+                fdb L813C                       ; interpretation handler (commands)
+                fcb 14                          ; 14 Extended Basic functions
+                fdb L821E                       ; reserved word table (functions)
+                fdb L8168                       ; function handler
+L80E8           fcc 'EXTENDED COLOR BASIC 2.0'
+                fcb 0x0d
+                fcc 'COPR. 1982, 1986 BY TANDY  '
+                fcb 0x0d
+                fcc 'UNDER LICENSE FROM MICROSOFT'
+                fcb 0x0d,0x0d,0x00
+; Extended Basic command interpretation loop
+L813C           cmpa #0xcb                      ; is it an Extended Basic command?
+                bhi L8148                       ; brif not
+                ldx #L81F0                      ; point to dispatch table
+                suba #0xb5                      ; normalize the token number so 0 is the first entry
+                jmp LADD4                       ; go transfer control to the command
+L8148           cmpa #0xff                      ; is it a function token?
+                beq L8154                       ; brif so - for MID$()=, TIMER=
+                cmpa #0xcd                      ; is it a token for a keyword that isn't a command?
+                bls L8165                       ; brif so - error for USING and FN
+L8150           jmp [COMVEC+23]                 ; transfer control to Disk Basic if it is present
+L8154           jsr GETNCH                      ; get token after the function flag
+                cmpa #0x90                      ; MID$?
+                lbeq L86D6                      ; brif so (substring replacement)
+                cmpa #0x9f                      ; TIMER?
+                lbeq L8960                      ; brif so - TIMER setting
+                jsr RVEC22                      ; do a RAM hook in case something wants to extend this
+L8165           jmp LB277                       ; we have nothing valid here
+; Function handler
+L8168           cmpb #2*33                      ; is it a valid Extended Basic function?
+                bls L8170                       ; brif so
+L816C           jmp [COMVEC+28]                 ; transfer control to Disk Basic if it is present
+L8170           subb #2*20                      ; normalize Extended Basic functions to 0
+                cmpb #2*8                       ; Above HEX$?
+                bhi L817D                       ; brif so - we don't pre-evaluate an argument
+                pshs b                          ; save token value
+                jsr LB262                       ; evaluate the function parameter
+                puls b                          ; get back token value
+L817D           ldx #L8257                      ; point to dispatch table
+                jmp LB2CE                       ; go transfer control to the function
+; Reserved words (commands)
+L8183           fcs 'DEL'                       ; 0xb5
+                fcs 'EDIT'                      ; 0xb6
+                fcs 'TRON'                      ; 0xb7
+                fcs 'TROFF'                     ; 0xb8
+                fcs 'DEF'                       ; 0xb9
+                fcs 'LET'                       ; 0xba
+                fcs 'LINE'                      ; 0xbb
+                fcs 'PCLS'                      ; 0xbc
+                fcs 'PSET'                      ; 0xbd
+                fcs 'PRESET'                    ; 0xbe
+                fcs 'SCREEN'                    ; 0xbf
+                fcs 'PCLEAR'                    ; 0xc0
+                fcs 'COLOR'                     ; 0xc1
+                fcs 'CIRCLE'                    ; 0xc2
+                fcs 'PAINT'                     ; 0xc3
+                fcs 'GET'                       ; 0xc4
+                fcs 'PUT'                       ; 0xc5
+                fcs 'DRAW'                      ; 0xc6
+                fcs 'PCOPY'                     ; 0xc7
+                fcs 'PMODE'                     ; 0xc8
+                fcs 'PLAY'                      ; 0xc9
+                fcs 'DLOAD'                     ; 0xca
+                fcs 'RENUM'                     ; 0xcb
+                fcs 'FN'                        ; 0xcc
+                fcs 'USING'                     ; 0xcd
+; Dispatch table (commands)
+L81F0           fdb DEL                         ; 0xb5 DEL
+                fdb EDIT                        ; 0xb6 EDIT
+                fdb TRON                        ; 0xb7 TRON
+                fdb TROFF                       ; 0xb8 TROFF
+                fdb DEF                         ; 0xb9 DEF
+                fdb LET                         ; 0xba LET (note: implemented by Color Basic!)
+                fdb LINE                        ; 0xbb LINE
+                fdb PCLS                        ; 0xbc PCLS
+                fdb PSET                        ; 0xbd PSET
+                fdb PRESET                      ; 0xbe PRESET
+                fdb SCREEN                      ; 0xbf SCREEN
+                fdb PCLEAR                      ; 0xc0 PCLEAR
+                fdb COLOR                       ; 0xc1 COLOR
+                fdb CIRCLE                      ; 0xc2 CIRCLE
+                fdb PAINT                       ; 0xc3 PAINT
+                fdb GET                         ; 0xc4 GET
+                fdb PUT                         ; 0xc5 PUT
+                fdb DRAW                        ; 0xc6 DRAW
+                fdb PCOPY                       ; 0xc7 PCOPY
+                fdb PMODETOK                    ; 0xc8 PMODE
+                fdb PLAY                        ; 0xc9 PLAY
+                fdb DLOAD                       ; 0xca DLOAD
+                fdb RENUM                       ; 0xcb RENUM
+; Reserved words (functions)
+L821E           fcs 'ATN'                       ; 0x94
+                fcs 'COS'                       ; 0x95
+                fcs 'TAN'                       ; 0x96
+                fcs 'EXP'                       ; 0x97
+                fcs 'FIX'                       ; 0x98
+                fcs 'LOG'                       ; 0x99
+                fcs 'POS'                       ; 0x9a
+                fcs 'SQR'                       ; 0x9b
+                fcs 'HEX$'                      ; 0x9c
+                fcs 'VARPTR'                    ; 0x9d
+                fcs 'INSTR'                     ; 0x9e
+                fcs 'TIMER'                     ; 0x9f
+                fcs 'PPOINT'                    ; 0xa0
+                fcs 'STRING$'                   ; 0xa1
+; Dispatch table (functions)
+L8257           fdb ATN                         ; 0x94 ATN
+                fdb COS                         ; 0x95 COS
+                fdb TAN                         ; 0x96 TAN
+                fdb EXP                         ; 0x97 EXP
+                fdb FIX                         ; 0x98 FIX
+                fdb LOG                         ; 0x99 LOG
+                fdb POS                         ; 0x9a POS
+                fdb SQR                         ; 0x9b SQR
+                fdb HEXDOL                      ; 0x9c HEX$
+                fdb VARPTRTOK                   ; 0x9d VARPTR
+                fdb INSTR                       ; 0x9e INSTR
+                fdb TIMER                       ; 0x9f TIMER
+                fdb PPOINT                      ; 0xa0 PPOINT
+                fdb STRING                      ; 0xa1 STRING$
+; Generic output handler
+XVEC3           tst DEVNUM                      ; screen?
+                lbeq L95AC                      ; brif so - force text screen active
+                pshs b                          ; save register
+                ldb DEVNUM                      ; get output device
+                cmpb #-3                        ; check for DLOAD
+                puls b                          ; restore register
+                bne L8285                       ; brif not DLOAD
+                leas 2,s                        ; bail out of output handler if DLOAD
+L8285           rts
+; Close file handler. This corrects a bug in Color Basic 1.0 which didn't handle writing the
+; end of file block correctly. That bug is fixed in Color Basic 1.1 so this isn't required
+; if a recent enough version of Color Basic is installed.
+XVEC8           lda DEVNUM                      ; get device number
+                inca                            ; is it tape?
+                bne L8285                       ; brif not - we aren't going to mess with it
+                lda FILSTA                      ; get tape file status
+                cmpa #2                         ; output file?
+                bne L8285                       ; brif not
+                lda CINCTR                      ; is there anything waiting to be written out?
+                bne L8285                       ; brif so - mainline code will handle it properly
+                clr DEVNUM                      ; reset output to screen
+                leas 2,s                        ; don't return to mainline code
+                jmp LA444                       ; write EOF block
+; RUN handler - sets up some Extended Basic stuff to defaults at program start
+XVEC18          ldd #0xba42                     ; initialize PLAY volume
+                std VOLHI
+                lda #2                          ; set PLAY tempo to 2, PLAY octave to 3
+                sta TEMPO
+                sta OCTAVE
+                asla                            ; set default note length to 5
+                sta NOTELN
+                clr DOTVAL                      ; don't do any note length extension
+                ldd ZERO                        ; initialize DRAW angle and scale to default 1
+                std ANGLE
+                ldb #128                        ; initialize horizontal and vertical default coordinates to the middle of the screen
+                std HORDEF
+                ldb #96
+                std VERDEF
+                rts
+; Command interpretation loop handler; we need to intercept this to implement TRON/TROFF
+XVEC20          leas 2,s                        ; don't return to the mainline code
+L82BB           andcc #0xaf                     ; make sure interrupts are running
+                jsr LADEB                       ; do a BREAK/pause check
+                ldx CHARAD                      ; save input pointer
+                stx TINPTR
+                lda ,x+                         ; get current input character
+                beq L82CF                       ; brif end of line
+                cmpa #':                        ; statement separator?
+                beq L82F1                       ; brif so
+                jmp LB277                       ; raise error we got here with extra junk
+L82CF           lda ,x++                        ; get first byte of next line address
+                sta ENDFLG                      ; use it to set "END" flag to "END"
+                bne L82D8                       ; brif not end of program
+                jmp LAE15                       ; go do the "END"
+L82D8           ldd ,x+                         ; get line number of next line (and leave pointer one before line text)
+                std CURLIN                      ; set current line number
+                stx CHARAD                      ; save input pointer
+                lda TRCFLG                      ; are we tracing?
+                beq L82F1                       ; brif not
+                lda #'[                         ; show opening marker for TRON line number
+                jsr PUTCHR
+                lda CURLIN                      ; restore MSB of line number
+                jsr LBDCC                       ; show line number
+                lda #']                         ; show closing marker for TRON line number
+                jsr PUTCHR
+L82F1           jsr GETNCH                      ; get the start of the statement
+                tfr cc,b                        ; save status flags
+                cmpa #0x98                      ; is it CSAVE?
+                beq L8316                       ; brif so - go to Extended Basic patch (adds CSAVEM)
+                cmpa #0x97                      ; is it CLOAD?
+                beq L8311                       ; brif so - go to Extended Basic patch (adds multi-origin binaries)
+                tfr b,cc                        ; restore character status
+                jsr LADC6                       ; go process command
+                bra L82BB                       ; restart interpretation loop
+; Tokenizaton handler. This is actually a hack to intercept CLOAD and CSAVE during immediate mode by causing the
+; tokenization routine to return to the interpretation loop above instead of the mainline interpretation loop. This
+; is necessary because the first command encountered on a line in immediate mode is executed BEFORE the interpretation
+; loop RAM hook is called. This patch doesn't actually affect tokenization itself at all.
+XVEC23          ldx 2,s                         ; get return address of caller to the tokenizer
+                cmpx #LAC9D                     ; is it coming from immediate mode prior to executing the line?
+                bne L8310                       ; brif not
+                ldx #L82F1                      ; force return to Extended Basic's main loop patch above
+                stx 2,s
+L8310           rts
+; These two patches are set up this way so that control can be transferred back to the original Color Basic
+; implementations if the Extended Basic addons are not triggered.
+L8311           jsr L8C62                       ; transfer control to Extended Basic's CLOAD handler
+                bra L82BB                       ; go do another command
+L8316           bsr L831A                       ; go do Extended Basic's CSAVE handler
+                bra L82BB                       ; go do another command
+; Extended Basic's CSAVE handler which implements CSAVEM (which Color Basic does not have)
+L831A           jsr GETNCH                      ; get character after CSAVE
+                cmpa #'M                        ; is it CSAVEM?
+                lbne CSAVE                      ; brif not - Color Basic can handle this
+                jsr GETNCH                      ; eat the "M"
+                jsr LA578                       ; parse file name
+                bsr L836C                       ; get start address
+                stx CASBUF+13                   ; save it in file header
+                bsr L836C                       ; get end address
+                cmpx 2,s                        ; compare to start address
+                lblo LB44A                      ; brif end address is before the start address
+                bsr L836C                       ; get execution address
+                stx CASBUF+11                   ; put in file header
+                jsr GETCCH                      ; are we at the end of the commmand?
+                bne L8310                       ; brif not
+                lda #2                          ; file type to machine language
+                ldx ZERO                        ; set to binary and single block
+                jsr LA65F                       ; write header
+                clr FILSTA                      ; mark any open tape file closed
+                inc BLKTYP                      ; set block type to data
+                jsr WRLDR                       ; write a data leader
+                ldx 4,s                         ; get starting address
+L834D           stx CBUFAD                      ; set start of data address
+                lda #255                        ; try a full length block by default
+                sta BLKLEN
+                ldd 2,s                         ; get ending address
+                subd CBUFAD                     ; see how much is left
+                bhs L835E                       ; brif we have more to write
+                leas 6,s                        ; clean up stack
+                jmp LA491                       ; write EOF block
+L835E           cmpd #255                       ; do we have a full block left?
+                bhs L8367                       ; brif so
+                incb                            ; set block size to remainder
+                stb BLKLEN
+L8367           jsr SNDBLK                      ; write a data block
+                bra L834D                       ; go see if we have more to write
+L836C           jsr SYNCOMMA                    ; make sure we have a comma
+                jsr LB73D                       ; evaluate unsigned expression to X
+                ldu ,s                          ; get return address
+                stx ,s                          ; save result on stack
+                tfr u,pc                        ; return to caller
+; COS function
+COS             ldx #L83AB                      ; point to PI/2 constant
+                jsr LB9C2                       ; add to argument ( cos(x) = sin((pi/2)+x) )
+L837E           jmp SIN                         ; now calculate sin((pi/2)+x)
+; TAN function. This is determined by the identity TAN(X) = SIN(X)/COS(X)
+TAN             jsr LBC2F                       ; save FPA0 in FPA3
+                clr RELFLG                      ; reset quadrant flag
+                bsr L837E                       ; calculate SIN(x)
+                ldx #V4A                        ; save result in FPA5
+                jsr LBC35
+                ldx #V40                        ; get back original argument
+                jsr LBC14
+                clr FP0SGN                      ; force result positive
+                lda RELFLG                      ; get quadrant flag
+                bsr L83A6                       ; calculate COS(x)
+                tst FP0EXP                      ; did we get 0 for COS(x)
+                lbeq LBA92                      ; brif so - overflow
+                ldx #V4A                        ; point to sin(x)
+L83A3           jmp LBB8F                       ; divide the sin(x) value by the cos(x) value
+L83A6           pshs a                          ; save sign flag
+                jmp LBFA6                       ; expand polynomial
+L83AB           fcb 0x81,0x49,0x0f,0xda,0xa2    ; pi/2 constant
+; ATN function (inverse tangent). There are two calculation streams used to improve precision.
+; One if the parameter is >= 1.0 and the other if it is < 1.0
+ATN             lda FP0SGN                      ; get sign of argument
+                pshs a                          ; save it
+                bpl L83B8                       ; brif positive
+                bsr L83DC                       ; flip sign of argument
+L83B8           lda FP0EXP                      ; get exponent
+                pshs a                          ; save it
+                cmpa #0x81                      ; exponent for 1.0
+                blo L83C5                       ; brif less - value is less than 1.0
+                ldx #LBAC5                      ; point to FP constant 1.0
+                bsr L83A3                       ; calculate reciprocal
+L83C5           ldx #L83E0                      ; point to polynomical coefficients
+                jsr LBEF0                       ; expand polynomial
+                puls a                          ; get exponent of argument
+                cmpa #0x81                      ; did we do a reciprocal calculation?
+                blo L83D7                       ; brif not
+                ldx #L83AB                      ; subtract result from pi/2 if we did
+                jsr LB9B9
+L83D7           puls a                          ; get sign of original
+                tsta                            ; was it positive?
+                bpl L83DF                       ; brif so
+L83DC           jmp LBEE9                       ; flip sign of result
+L83DF           rts
+; Chebyshev modified taylor series coefficients for inverse tangent. Note that these diverge quite significantly
+; from the standard taylor series after 1/9. The standard coefficients are 1/1,-1/3, 1/5, -1/7, 1/9, -1/11, and
+; so on. These modified coefficients yield reasonable accuracy for the precision available, presumably with
+; fewer coefficients.
+L83E0           fcb 11                          ; 12 coefficients
+                fcb 0x76,0xb3,0x83,0xbd,0xd3    ; -0.000684793912
+                fcb 0x79,0x1e,0xf4,0xa6,0xf5    ; 0.00485094216
+                fcb 0x7b,0x83,0xfc,0xb0,0x10    ; -0.0161117018
+                fcb 0x7c,0x0c,0x1f,0x67,0xca    ; 0.0342096381
+                fcb 0x7c,0xde,0x53,0xcb,0xc1    ; -0.0542791328
+                fcb 0x7d,0x14,0x64,0x70,0x4c    ; 0.0724571965 
+                fcb 0x7d,0xb7,0xea,0x51,0x7a    ; -0.0898023954
+                fcb 0x7d,0x63,0x30,0x88,0x7e    ; 0.110932413
+                fcb 0x7e,0x92,0x44,0x99,0x3a    ; -0.142839808
+                fcb 0x7e,0x4c,0xcc,0x91,0xc7    ; 0.199999121
+                fcb 0x7f,0xaa,0xaa,0xaa,0x13    ; -0.333333316
+                fcb 0x81,0x00,0x00,0x00,0x00    ; 1.0
+; Chebyshev modified taylor series coefficients for the ln(x)/ln(2) (base 2 log of x)
+L841D           fcb 3                           ; four coefficients
+                fcb 0x7f,0x5e,0x56,0xcb,0x79    ; 0.434255942 from (2/7)/ln(2)
+                fcb 0x80,0x13,0x9b,0x0b,0x64    ; 0.576584541 from (2/5)/ln(2)
+                fcb 0x80,0x76,0x38,0x93,0x16    ; 0.961800759 from (2/3)/ln(2) 
+                fcb 0x82,0x38,0xaa,0x3b,0x20    ; 2.88539007 from 2/ln(2)
+L8432           fcb 0x80,0x35,0x04,0xf3,0x34    ; 1/sqrt(2)
+L8437           fcb 0x81,0x35,0x04,0xf3,0x34    ; sqrt(2)
+L843C           fcb 0x80,0x80,0x00,0x00,0x00    ; -0.5
+L8441           fcb 0x80,0x31,0x72,0x17,0xf8    ; ln(2)
+; LOG function (natural log, ln)
+; FP representation is of the form A*2^B. Thus, the log routine determines the value of
+; ln(A*2^B).
+;
+; ln(A*2^B) = ln(A) + ln(2^B) = ln(A) + B*ln(2) = (ln(A)/ln(2) + B)*ln(2), OR:
+; (log2(A) + B)*ln(2)
+; Now if we write A as A*(sqrt(2)/sqrt(2)), we haven't changed anything so:
+; (log2(A*sqrt(2)/sqrt(2)) + B)*ln(2) = (log2(A*sqrt(2)) - log2(sqrt(2)) + B) * ln(2)
+; which gives: (-1/2 + log2(A*sqrt(2)) + B) * ln(2)
+;
+; Everything except log2(A*sqrt(2)) is either constant or trivial.
+;
+; What the actual code below feeds into the modified taylor series is actually:
+; 1 - (sqrt(2)/(A + sqrt(2)) which algebra reveals to be (A*sqrt(2)-1)/(A*sqrt(2)+1)
+;
+; Thus, the code is using (A*sqrt(2)-1)/(A*sqrt(2)+1) instead of A*sqrt(2) as one would
+; expect from the identities. However, the modified coefficients in the series above
+; could be correcting for that or the introduced error was deemed acceptable.
+; NOTE: this routine does NOT return 0 for LOG(1)
+LOG             jsr LBC6D                       ; get status of FPA0
+                lble LB44A                      ; brif <= 0 - logarithms don't exist in that case
+                ldx #L8432                      ; point to 1/sqrt(2)
+                lda FP0EXP                      ; get exponent of argument
+                suba #0x80                      ; remove bias
+                pshs a                          ; save it for later
+                lda #0x80                       ; force exponent to 0 (this turns FPA0 into A in the above description)
+                sta FP0EXP
+                jsr LB9C2                       ; add 1/sqrt(2) to A
+                ldx #L8437                      ; point to sqrt(2)
+                jsr LBB8F                       ; divide that by FPA0
+                ldx #LBAC5                      ; point to 1.0
+                jsr LB9B9                       ; subtract result from 1.0: Now FPA0 is 1-(sqrt(2)/(A+1/sqrt(2)))
+                ldx #L841D                      ; point to coefficients
+                jsr LBEF0                       ; expand polynomial (calculate base 2 log of modified argument)
+                ldx #L843C                      ; point to -0.5
+                jsr LB9C2                       ; add result
+                puls b                          ; get original exponent back
+                jsr LBD99                       ; add B to FPA0
+                ldx #L8441                      ; point to ln(2)
+                jmp LBACA                       ; multiply by ln(2) which gives us the result in base e
+; SQR function (square root) - returns the principle root (positive)
+SQR             jsr LBC5F                       ; move argument to FPA1 (first argument for exponentiation)
+                ldx #LBEC0                      ; point to 0.5 (exponent for square root)
+                jsr LBC14                       ; set up second argument to exponentiation (the exponent)
+; Exponentiation operator
+; This is calculated as A^x = e^(x*ln(A)) where A is in FPA1 and x is in FPA0
+L8489           beq EXP                         ; do "EXP" if exponent is 0 (this will catch 0^0)
+                tsta                            ; check that the base is not 0
+                bne L8491                       ; brif base is not 0
+                jmp LBA3A                       ; 0^(nonzero) is 0
+L8491           ldx #V4A                        ; save exponent (to FPA5)
+                jsr LBC35
+                clrb                            ; result sign will default to positive
+                lda FP1SGN                      ; check if base is positive
+                bpl L84AC                       ; brif so
+                jsr INT                         ; convert exponent to integer
+                ldx #V4A                        ; point to original expoent
+                lda FP1SGN                      ; get sign of FPA1
+                jsr LBCA0                       ; compare original exponent with truncated one
+                bne L84AC                       ; brif not equal
+                coma                            ; flip sign
+                ldb CHARAC                      ; get LS byte of integer exponent (result sign flag)
+L84AC           jsr LBC4C                       ; copy FPA1 (base) to FPA0 (A = sign)
+                pshs b                          ; save result sign
+                jsr LOG                         ; get natural log of the base
+                ldx #V4A                        ; multiply the log by the exponent
+                jsr LBACA
+                bsr EXP                         ; now raise e to the resulting power
+                puls a                          ; get result sign
+                rora                            ; brif it was negative
+                lbcs LBEE9                      ; brif negative - flip sign
+                rts
+L84C4           fcb 0x81,0x38,0xaa,0x3b,0x29    ; 1.44269504 (correction factor for exponential function)
+; Chebyshev modified taylor series coefficients for e^x
+L84C9           fcb 7                           ; eight coefficients
+                fcb 0x71,0x34,0x58,0x3e,0x56    ; 1/(7!*(CF^7))
+                fcb 0x74,0x16,0x7e,0xb3,0x1b    ; 1/(6!*(CF^6))
+                fcb 0x77,0x2f,0xee,0xe3,0x85    ; 1/(5!*(CF^5))
+                fcb 0x7a,0x1d,0x84,0x1c,0x2a    ; 1/(4!*(CF^4))
+                fcb 0x7c,0x63,0x59,0x58,0x0a    ; 1/(3!*(CF^3))
+                fcb 0x7e,0x75,0xfd,0xe7,0xc6    ; 1/(2!*(CF^2))
+                fcb 0x80,0x31,0x72,0x18,0x10    ; 1/(1!*(CF^1))
+                fcb 0x81,0x00,0x00,0x00,0x00    ; 1
+; EXP function (e^x)
+EXP             ldx #L84C4                      ; point to correction factor
+                jsr LBACA                       ; multiply it
+                jsr LBC2F                       ; save corrected argument to FPA3
+                lda FP0EXP                      ; get exponent of FPA0
+                cmpa #0x88                      ; is it too big?
+                blo L8504                       ; brif not
+L8501           jmp LBB5C                       ; to 0 (underflow) or overflow error
+L8504           jsr INT                         ; convert argument to an integer
+                lda CHARAC                      ; get ls byte of integer
+                adda #0x81                      ; was argument 127? if so, the OV error; adds bias
+                beq L8501
+                deca                            ; adjust for the extra +1 above
+                pshs a                          ; save integer exponent
+                ldx #V40                        ; get fractional part of argument
+                jsr LB9B9
+                ldx #L84C9                      ; point to coefficients
+                jsr LBEFF                       ; evaluate polynomial on the fractional part
+                clr RESSGN                      ; force result to be positive
+                puls a                          ; get back original exponent
+                jsr LBB48                       ; add original exponent to the fractional result
+                rts
+; FIX function (truncate/round toward 0) (NOTE: INT() always rounds down so INT(-0.5) gives -1 but FIX(-0.5) gives 0)
+FIX             jsr LBC6D                       ; get status of argument
+                bmi L852C                       ; brif negative
+L8529           jmp INT                         ; do regular "int" if positive
+L852C           com FP0SGN                      ; flip the sign
+                bsr L8529                       ; do "INT" on this
+                jmp LBEE9                       ; flip the sign back
+; EDIT command
+EDIT            jsr L89AE                       ; get line number
+                leas 2,s                        ; we're not going to return to the main loop
+L8538           lda #1                          ; "LIST" flag
+                sta VD8                         ; set to list the line
+                jsr LAD01                       ; find line number
+                lbcs LAED2                      ; brif line wasn't found
+                jsr LB7C2                       ; go unpack the line into the buffer
+                tfr y,d                         ; calculate the actual length of the line
+                subd #LINBUF+2
+                stb VD7                         ; save line length (it will only be 8 bits)
+L854D           ldd BINVAL                      ; get the line number
+                jsr LBDCC                       ; display it
+                jsr LB9AC                       ; put a space after it
+                ldx #LINBUF+1                   ; point to iput uffer
+                ldb VD8                         ; are we listing?
+                bne L8581                       ; brif so
+L855C           clrb                            ; reset digit accumulator
+L855D           jsr L8687                       ; get a keypress
+                jsr L90AA                       ; set carry if not numeric
+                bcs L8570                       ; brif not a number
+                suba #'0                        ; remove ASCII bias
+                pshs a                          ; save digit value
+                lda #10                         ; multiply accumulator by 10
+                mul
+                addb ,s+                        ; add in new digit
+                bra L855D                       ; go check for another digit
+L8570           subb #1                         ; this converts 0 to 1, but *only* 0 to 1
+                adcb #1
+                cmpa #'A                        ; abort?
+                bne L857D                       ; brif not
+                jsr LB958                       ; to a CR
+                bra L8538                       ; restart EDIT process
+L857D           cmpa #'L                        ; list?
+                bne L858C                       ; brif not
+L8581           bsr L85B4                       ; list the line
+                clr VD8                         ; reset to "not listing"
+                jsr LB958                       ; do a CR
+                bra L854D                       ; start editing
+L858A           leas 2,s                        ; lose return address
+L858C           cmpa #0x0d                      ; ENTER?
+                bne L859D                       ; brif not
+                bsr L85B4                       ; echo out the line
+L8592           jsr LB958                       ; do a CR
+                ldx #LINBUF+1                   ; reset input pointer to start of buffer
+                stx CHARAD
+                jmp LACA8                       ; join immediate mode to replace the line in the program
+L859D           cmpa #'E                        ; exit?
+                beq L8592                       ; brif so - end edit with no echo
+                cmpa #'Q                        ; quit?
+                bne L85AB                       ; brif not
+                jsr LB958                       ; do a CR
+                jmp LAC73                       ; go to immediate mode with no fanfare - no changes saved
+L85AB           bsr L85AF                       ; go do commands
+                bra L855C                       ; go handle another command
+L85AF           cmpa #0x20                      ; space?
+                bne L85C3                       ; brif not
+                skip2
+L85B4           ldb #LBUFMX-1                   ; display up to a whole line
+L85B6           lda ,x                          ; get buffer chracter
+                beq L85C2                       ; brif end of line
+                jsr PUTCHR                      ; output character
+                leax 1,x                        ; move to next character
+                decb                            ; done?
+                bne L85B6                       ; brif not
+L85C2           rts
+L85C3           cmpa #'D                        ; delete?
+                bne L860F                       ; brif not
+L85C7           tst ,x                          ; end of line?
+                beq L85C2                       ; brif so - can't delete
+                bsr L85D1                       ; remove a character
+                decb                            ; done all requested?
+                bne L85C7                       ; brif not
+                rts
+L85D1           dec VD7                         ; account for character being removed
+                leay -1,x                       ; set pointer and compensate for increment below
+L85D5           leay 1,y                        ; move to next character
+                lda 1,y                         ; get next character
+                sta ,y                          ; move it forward
+                bne L85D5                       ; brif we didn't hit the end of the buffer
+                rts
+L85DE           cmpa #'I                        ; insert?
+                beq L85F5                       ; brif so
+                cmpa #'X                        ; extend?
+                beq L85F3                       ; brif so
+                cmpa #'H                        ; "hack"?
+                bne L8646                       ; brif not
+                clr ,x                          ; mark current location as end of line
+                tfr x,d                         ; calculate new line length
+                subd #LINBUF+2
+                stb VD7                         ; save new length
+L85F3           bsr L85B4                       ; display the line
+L85F5           jsr L8687                       ; read a character
+                cmpa #0x0d                      ; ENTER?
+                beq L858A                       ; brif so - terminate entry
+                cmpa #0x1b                      ; ESC?
+                beq L8625                       ; brif so - back to command mode
+                cmpa #0x08                      ; backspace?
+                bne L8626                       ; brif no
+                cmpx #LINBUF+1                  ; are we at the start of the buffer?
+                beq L85F5                       ; brif so - it's a no-op
+                bsr L8650                       ; move pointer back one, do a BS
+                bsr L85D1                       ; remove character from the buffer
+                bra L85F5                       ; go handle more input
+L860F           cmpa #'C                        ; change?
+                bne L85DE                       ; brif not
+L8613           tst ,x                          ; is there something to change?
+                beq L8625                       ; brif not
+                jsr L8687                       ; get a key stroke
+                bcs L861E                       ; brif valid key
+                bra L8613                       ; try again if invalid key
+L861E           sta ,x+                         ; put new character in the buffer
+                bsr L8659                       ; echo it
+                decb                            ; changed number requested?
+                bne L8613                       ; brif not
+L8625           rts
+L8626           ldb VD7                         ; get length of line
+                cmpb #LBUFMX-1                  ; at maximum line length?
+                bne L862E                       ; brif not
+                bra L85F5                       ; process another input character
+L862E           pshs x                          ; save input pointer
+L8630           tst ,x+                         ; are we at the end of the line?
+                bne L8630                       ; brif not
+L8634           ldb ,-x                         ; get character before current pointer, move back
+                stb 1,x                         ; move it forward
+                cmpx ,s                         ; at the original buffer pointer?
+                bne L8634                       ; brif not
+                leas 2,s                        ; remove saved buffer pointer
+                sta ,x+                         ; save input character in newly made hole
+                bsr L8659                       ; echo it
+                inc VD7                         ; bump line length counter
+                bra L85F5                       ; go handle more stuff
+L8646           cmpa #0x08                      ; backspace?
+                bne L865C                       ; brif not
+L864A           bsr L8650                       ; move pointer back, echo BS
+                decb                            ; done enough of them?
+                bne L864A                       ; brif not
+                rts
+L8650           cmpx #LINBUF+1                  ; at start of buffer?
+                beq L8625                       ; brif so
+                leax -1,x                       ; move pointer back
+                lda #0x08                       ; character to echo - BS
+L8659           jmp PUTCHR                      ; echo character to screen
+L865C           cmpa #'K                        ; "kill"?
+                beq L8665                       ; brif so
+                suba #'S                        ; search?
+                beq L8665                       ; brif so
+                rts
+L8665           pshs a                          ; save kill/search flag
+                bsr L8687                       ; read target
+                pshs a                          ; save search character
+L866B           lda ,x                          ; get current character in buffer
+                beq L8685                       ; brif end of line - nothing more to search
+                tst 1,s                         ; is it KILL?
+                bne L8679                       ; brif so
+                bsr L8659                       ; echo the character
+                leax 1,x                        ; move ahead
+                bra L867C                       ; check next character
+L8679           jsr L85D1                       ; remove character from buffer
+L867C           lda ,x                          ; get character in buffer
+                cmpa ,s                         ; are we at the target?
+                bne L866B                       ; brif not
+                decb                            ; have we found enough of them?
+                bne L866B                       ; brif not
+L8685           puls y,pc                       ; clean up stack and return to main EDIT routine
+L8687           jsr LA171                       ; get input from the generic input handler (will show the cursor)
+                cmpa #0x7f                      ; graphics (or DEL)?
+                bhs L8687                       ; brif so - ignore it
+                cmpa #0x5f                      ; SHIFT-UP?
+                bne L8694                       ; brif not
+                lda #0x1b                       ; replace with ESC
+L8694           cmpa #0x0d                      ; carriage return?
+                beq L86A6                       ; brif so (C=0)
+                cmpa #0x1b                      ; ESC
+                beq L86A6                       ; brif so (C=0)
+                cmpa #0x08                      ; backspace?
+                beq L86A6                       ; brif so (C=0)
+                cmpa #32                        ; control code?
+                blo L8687                       ; brif control code - try again
+                orcc #1                         ; set C for "valid" (printable) character
+L86A6           rts
+; TRON and TROFF commands
+TRON            skip1lda                        ; load flag with nonzero for trace enabled (and skip next)
+TROFF           clra                            ; clear flag for trace disabled
+                sta TRCFLG                      ; save trace status
+                rts
+; POS function
+POS             lda DEVNUM                      ; get original device number
+                pshs a                          ; save it for later
+                jsr LA5AE                       ; fetch device number
+                jsr LA406                       ; check for open file
+                jsr LA35F                       ; set up print parameters
+                ldb DEVPOS                      ; get current line position for the device
+                jmp LA5E4                       ; return position in B as unsigned
+; VARPTR function
+VARPTRTOK       jsr LB26A                       ; make sure we have (
+                ldd ARYEND                      ; get address of end of arrays
+                pshs d                          ; save it
+                jsr LB357                       ; parse variable descriptor
+                jsr LB267                       ; make sure there is a )
+                puls d                          ; get original end of arrays
+                exg x,d                         ; swap original end of arrays and the discovered variable pointer
+                cmpx ARYEND                     ; did array end move (variable created?)
+                bne L8724                       ; brif so (FC error)
+                jmp GIVABF                      ; return the pointer (NOTE: as signed)
+; MID$() assignment; note that this cannot make the string longer or shorter and if the replacement is shorter
+; than the specified size, only the number of characters actually in the replacement will be used.
+L86D6           jsr GETNCH                      ; eat the MID$ token
+                jsr LB26A                       ; force (
+                jsr LB357                       ; evaluate the variable
+                pshs x                          ; save variable descriptor
+                ldd 2,x                         ; point to start of original string
+                cmpd FRETOP                     ; is it in string space?
+                bls L86EB                       ; brif not
+                subd MEMSIZ                     ; is it still in string space (top end)?
+                bls L86FD                       ; brif so
+L86EB           ldb ,x                          ; get length of original string
+                jsr LB56D                       ; allocate space in string space
+                pshs x                          ; save pointer to string space
+                ldx 2,s                         ; get to original string descriptor
+                jsr LB643                       ; move the string into string space
+                puls x,u                        ; get new string address and string descriptor
+                stx 2,u                         ; save new data address for the string
+                pshs u                          ; save descriptor address again
+L86FD           jsr LB738                       ; evaluate ",start"
+                pshs b                          ; save start offset
+                tstb                            ; is start 0?
+                beq L8724                       ; brif so - strings offsets are 1-based
+                ldb #255                        ; default use the entire string
+                cmpa #')                        ; end of parameters?
+                beq L870E                       ; brif so
+                jsr LB738                       ; evaluate ",length"
+L870E           pshs b                          ; save length
+                jsr LB267                       ; make sure we have a )
+                ldb #0xb3                       ; make sure we have =
+                jsr LB26F
+                bsr L8748                       ; evaluate replacement string
+                tfr x,u                         ; save replacement string address
+                ldx 2,s                         ; get original string descriptor
+                lda ,x                          ; get length of original string
+                suba 1,s                        ; subtract start position
+                bhs L8727                       ; brif within the string - insert replacement
+L8724           jmp LB44A                       ; raise illegal function call
+L8727           inca                            ; A is now number of characters to the right of the position parameter
+                cmpa ,s                         ; compare to length desired
+                bhs L872E                       ; brif new length fits
+                sta ,s                          ; only use as much of the length as will fit
+L872E           lda 1,s                         ; get position offset
+                exg a,b                         ; swap replacement length and position
+                ldx 2,x                         ; point to original string address
+                decb                            ; we work with 0-based offsets
+                abx                             ; now X points to start of replacement
+                tsta                            ; replacing 0?
+                beq L8746                       ; brif so - done
+                cmpa ,s                         ; is replacement shorter than the hole?
+                bls L873F                       ; brif so
+                lda ,s                          ; use copy the maximum number specified
+L873F           tfr a,b                         ; save number to move in B
+                exg u,x                         ; swap pointers so they are right for the routine
+                jsr LA59A                       ; copy string data
+L8746           puls a,b,x,pc                   ; clean up stack and return
+L8748           jsr LB156                       ; evaluate expression
+                jmp LB654                       ; make sure it's a string and return string details
+; STRING$ function
+STRING          jsr LB26A                       ; make sure we have (
+                jsr EVALEXPB                    ; evaluate repeat count (error if > 255)
+                pshs b                          ; save repeat count
+                jsr SYNCOMMA                    ; make sure there's a comma
+                jsr LB156                       ; evaluate the thing to repeat
+                jsr LB267                       ; make sure we have a )
+                lda VALTYP                      ; is it string?
+                bne L8768                       ; brif so
+                jsr LB70E                       ; get 8 bit character code
+                bra L876B                       ; use that
+L8768           jsr LB6A4                       ; get first character of string
+L876B           pshs b                          ; save repeat character
+                ldb 1,s                         ; get repeat count
+                jsr LB50F                       ; reserve space for the string
+                puls a,b                        ; get character and repeat count
+                beq L877B                       ; brif NULL string
+L8776           sta ,x+                         ; put character into string
+                decb                            ; put enough?
+                bne L8776                       ; brif not
+L877B           jmp LB69B                       ; return the newly created string
+; INSTR function
+INSTR           jsr LB26A                       ; evaluate (
+                jsr LB156                       ; evaluate first argument
+                ldb #1                          ; default start position is 1 (start of string)
+                pshs b                          ; save start position
+                lda VALTYP                      ; get type of first argument
+                bne L879C                       ; brif string - use default starting position
+                jsr LB70E                       ; convert first argument into string offset
+                stb ,s                          ; save offset
+                beq L8724                       ; brif starting at 0 - not allowed
+                jsr SYNCOMMA                    ; make sure there's a comma
+                jsr LB156                       ; evaluate the search string
+                jsr LB146                       ; make sure it *is* a string
+L879C           ldx FPA0+2                      ; get search string descriptor
+                pshs x                          ; save it
+                jsr SYNCOMMA                    ; make sure we have a comma
+                jsr L8748                       ; evalute the target string
+                pshs x,b                        ; save address and length of target string
+                jsr LB267                       ; make sure we have a )
+                ldx 3,s                         ; get search string address
+                jsr LB659                       ; get string details
+                pshs b                          ; save search string length
+                cmpb 6,s                        ; compare length of search string to the start
+                blo L87D9                       ; brif start position is beyond the search string - return 0
+                lda 1,s                         ; get length of target string
+                beq L87D6                       ; brif targetstring is NULL - match will be immediate
+                ldb 6,s                         ; get start position
+                decb                            ; zero-base it
+                abx                             ; now X points to the start position for the search
+L87BE           leay ,x                         ; point to start of search
+                ldu 2,s                         ; get target string pointer
+                ldb 1,s                         ; get targetlength
+                lda ,s                          ; get length of serach
+                suba 6,s                        ; see how much is left in searh
+                inca                            ; add one for "inclusivity"
+                cmpa 1,s                        ; do we have less than the target string?
+                blo L87D9                       ; brif so - we obviously won't match
+L87CD           lda ,x+                         ; compare a byte
+                cmpa ,u+
+                bne L87DF                       ; brif no match
+                decb                            ; compared all of target?
+                bne L87CD                       ; brif not
+L87D6           ldb 6,s                         ; get position where we matched
+                skip1
+L87D9           clrb                            ; flag no match
+                leas 7,s                        ; clean up stack
+                jmp LB4F3                       ; return unsigned B
+L87DF           inc 6,s                         ; bump start position
+                leax 1,y                        ; move starting pointer
+                bra L87BE                       ; see if we match now
+; Number parsing handler
+XVEC19          cmpa #'&                        ; do we have & (hex or octal)?
+L87E7           bne L8845                       ; brif not
+                leas 2,s                        ; we won't return to the original invoker
+L87EB           clr FPA0+2                      ; clear bottom of FPA0 for 16 bit value
+                clr FPA0+3
+                ldx #FPA0+2                     ; point to accumulator
+                jsr GETNCH                      ; eat the &
+                cmpa #'O                        ; octal?
+                beq L880A                       ; brif so
+                cmpa #'H                        ; hex?
+                beq L881F                       ; brif so
+                jsr GETCCH                      ; reset flags on input
+                bra L880C                       ; go process octal (default)
+L8800           cmpa #'8                        ; is it a valid octal character?
+                lbhi LB277                      ; brif not (BUG: should be LBHS or above be #'7)
+                ldb #3                          ; base 8 multiplier
+                bsr L8834                       ; add digit to accumulator
+L880A           jsr GETNCH                      ; get input character
+L880C           bcs L8800                       ; brif numeric
+L880E           clr FPA0                        ; clear upper bytes of FPA0
+                clr FPA0+1
+                clr VALTYP                      ; result is numeric
+                clr FPSBYT                      ; clear out any extra precision
+                clr FP0SGN                      ; make it positive
+                ldb #0xa0                       ; exponent for integer aligned to right of FPA0
+                stb FP0EXP
+                jmp LBA1C                       ; go normalize the result and return
+L881F           jsr GETNCH                      ; get input character
+                bcs L882E                       ; brif digit
+                jsr LB3A2                       ; set carry if not alpha
+L8826           bcs L880E                       ; brif not alpha
+                cmpa #'G                        ; is it valid HEX digit?
+                bhs L880E                       ; brif not
+                suba #7                         ; normalize A-F to be just above 0-9
+L882E           ldb #4                          ; four bits per digit
+                bsr L8834                       ; add digit to accumlator
+                bra L881F                       ; process another digit
+L8834           asl 1,x                         ; shift accumulator one bit left
+                rol ,x
+                lbcs LBA92                      ; brif too big - overflow
+                decb                            ; done enough bit shifts?
+                bne L8834                       ; brif not
+L883F           suba #'0                        ; remove ASCII bias
+                adda 1,x                        ; merge digit into accumlator (this cannot cause carry)
+                sta 1,x
+L8845           rts
+; Expression evaluation handler
+XVEC15          puls u                          ; get back return address
+                clr VALTYP                      ; set result to numeric
+                ldx CHARAD                      ; save input pointer
+                jsr GETNCH                      ; get the input character
+                cmpa #'&                        ; HEX or OCTAL?
+                beq L87EB                       ; brif so
+                cmpa #0xcc                      ; FN?
+                beq L88B4                       ; brif so - do "FNx()"
+                cmpa #0xff                      ; function token?
+                bne L8862                       ; brif not
+                jsr GETNCH                      ; get function token value
+                cmpa #0x83                      ; USR?
+                lbeq L892C                      ; brif so - short circuit Color Basic's USR handler
+L8862           stx CHARAD                      ; restore input pointer
+                jmp ,u                          ; return to mainline code
+L8866           ldx CURLIN                      ; are we in immediate mode?
+                leax 1,x
+L886A           bne L8845                       ; brif not - we're good
+                ldb #2*11                       ; code for illegal direct statement
+L886E           jmp LAC46                       ; raise error
+; DEF command (DEF FN, DEF USR)
+DEF             ldx [CHARAD]                    ; get two input characters
+                cmpx #0xff83                    ; USR?
+                lbeq L890F                      ; brif so - do DEF USR
+                bsr L88A1                       ; get descriptor address for FN variable
+                bsr L8866                       ; disallow DEF FN in immediate mode
+                jsr LB26A                       ; make sure we have (
+                ldb #0x80                       ; disallow arrays as arguments
+                stb ARYDIS
+                jsr LB357                       ; evaluate variable
+                bsr L88B1                       ; make sure it's numeric
+                jsr LB267                       ; make sure we have )
+                ldb #0xb3                       ; make sure we have =
+                jsr LB26F
+                ldx V4B                         ; get variable descriptor address
+                ldd CHARAD                      ; get input pointer
+                std ,x                          ; save address of the actual function code in variable descriptor
+                ldd VARPTR                      ; get descriptor address of argument
+                std 2,x                         ; save argument descriptor address
+                jmp DATA                        ; move to the end of this statement
+L88A1           ldb #0xcc                       ; make sure we have FN
+                jsr LB26F
+                ldb #0x80                       ; disable array lookup
+                stb ARYDIS
+                ora #0x80                       ; set bit 7 of first character (to indicate FN variable)
+                jsr LB35C                       ; find the variable
+                stx V4B                         ; save descriptor pointer
+L88B1           jmp LB143                       ; make sure we have a numeric variable
+; Evaluate an FN call
+L88B4           bsr L88A1                       ; parse the FNx bit and get the descriptor
+                pshs x                          ; save descriptor
+                jsr LB262                       ; evaluate parameter
+                bsr L88B1                       ; make sure it's a number
+                puls u                          ; get FN descriptor
+                ldb #2*25                       ; code for undefined function
+                ldx 2,u                         ; point to argument variable descriptor
+                beq L886E                       ; brif nothing doing there (if it was just created, this will be NULL)
+                ldy CHARAD                      ; save current input pointer
+                ldu ,u                          ; point to start of FN definition
+                stu CHARAD                      ; put input pointer there
+                lda 4,x                         ; save original value of argument and save it with current input, and variable pointers
+                pshs a
+                ldd ,x
+                ldu 2,x
+                pshs u,y,x,d
+                jsr LBC35                       ; set argument variable to the argument
+L88D9           jsr LB141                       ; go evaluate the FN expression
+                puls d,x,y,u                    ; get back variable pointers, input pointer, and original variable value
+                std ,x
+                stu 2,x
+                puls a
+                sta 4,x
+                jsr GETCCH                      ; test end of FN formula
+                lbne LB277                      ; brif not end of statement - problem with the function
+                sty CHARAD                      ; restore input pointer
+L88EF           rts
+; Error handler
+XVEC17          cmpb #2*25                      ; is it a valid Extended Basic error code?
+                blo L88EF                       ; brif not - return to mainline
+                jsr LA7E9                       ; turn off tape
+                jsr LA974                       ; turn off sound
+                jsr LAD33                       ; clean up stack and other bits
+                clr DEVNUM                      ; reset output to screen
+                jsr LB95C                       ; do a newline if needed
+                jsr LB9AF                       ; do a ?
+                ldx #L890B-25*2                 ; point to error message table
+                jmp LAC60                       ; go display error message
+; Extended Basic error codes. Yes, NE is defined here even though it is only actually documented in the
+; Disk Basic documentation. It is here for the use of DLOAD.
+L890B           fcc 'UF'                        ; 25 undefined function call
+                fcc 'NE'                        ; 26 File not found
+; DEF USR
+L890F           jsr GETNCH                      ; eat the USR token
+                bsr L891C                       ; get pointer to USR call
+                pshs x                          ; save FN exec address location
+                bsr L8944                       ; calculate execution address
+                puls u                          ; get FN address pointer
+                stx ,u                          ; save new address
+                rts
+L891C           clrb                            ; default routine number is 0
+                jsr GETNCH                      ; fetch the call number
+                bcc L8927                       ; brif not a number
+                suba #'0                        ; remove ASCII bias
+                tfr a,b                         ; save it in the right place
+                jsr GETNCH                      ; eat the call number
+L8927           ldx USRADR                      ; get start address of USR jump table
+                aslb                            ; two bytes per address
+                abx                             ; now X points to the right entry
+                rts
+; Evaluate a USR call
+L892C           bsr L891C                       ; find the correct routine address location
+                ldx ,x                          ; get routine address
+                pshs x                          ; save it
+                jsr LB262                       ; evaluate argument
+                ldx #FP0EXP                     ; point to FPA0 (argument value)
+                lda VALTYP                      ; is it string?
+                beq L8943                       ; brif not
+                jsr LB657                       ; fetch string details (removes it from the string stack)
+                ldx FPA0+2                      ; get string descriptor pointer
+                lda VALTYP                      ; set flags for the value type
+L8943           rts                             ; call the routine and return to mainline code
+L8944           ldb #0xb3                       ; check for "="
+                jsr LB26F
+                jmp LB73D                       ; evaluate integer expression to X and return
+; Extended Basic IRQ handler
+XIRQSV          lda PIA0+3                      ; is it VSYNC interrupt?
+                bmi L8952                       ; brif so
+                rti                             ; really should clear the HSYNC interrupt here
+L8952           lda PIA0+2                      ; clear VSYNC interrupt
+                ldx TIMVAL                      ; increment the TIMER value
+                leax 1,x
+                stx TIMVAL
+                jmp L9C3E                       ; check for other stuff
+; TIMER=
+L8960           jsr GETNCH                      ; eat the TIMER token
+                bsr L8944                       ; evaluate =nnnn to X
+                stx TIMVAL                      ; set the timer
+                rts
+; TIMER function
+TIMER           ldx TIMVAL                      ; get timer value
+                stx FPA0+2                      ; set it in FPA0
+                jmp L880E                       ; return as positive 16 bit value
+; DEL command
+DEL             lbeq LB44A                      ; raise error if no argument (probably to avoid accidentally deleting line 0)
+                jsr LAF67                       ; parse line number
+                jsr LAD01                       ; find line
+                stx VD3                         ; save address of line
+                jsr GETCCH                      ; is there something more?
+                beq L8990                       ; brif not
+                cmpa #0xac                      ; dash?
+                bne L89BF                       ; brif not - error out
+                jsr GETNCH                      ; each the -
+                beq L898C                       ; brif no ending line - use default line number
+                bsr L89AE                       ; parse second line number and save in BINVAL
+                bra L8990                       ; do the deletion
+L898C           lda #0xff                       ; set to maximum line number
+                sta BINVAL
+L8990           ldu VD3                         ; point end to start
+                skip2
+L8993           ldu ,u                          ; point to start of next line
+                ldd ,u                          ; check for end of program
+                beq L899F                       ; brif end of program
+                ldd 2,u                         ; get line number
+                subd BINVAL                     ; is it in range?
+                bls L8993                       ; brif so
+L899F           ldx VD3                         ; get starting line address
+                bsr L89B8                       ; close up gap
+                jsr LAD21                       ; reset input pointer and erase variables
+                ldx VD3                         ; get start of program after the deletion
+                jsr LACF1                       ; recompute netl ine pointers
+                jmp LAC73                       ; return to immediate mode
+L89AE           jsr LAF67                       ; parse a line number
+                jmp LA5C7                       ; make sure there's nothing more
+L89B4           lda ,u+                         ; copy a byte
+                sta ,x+
+L89B8           cmpu VARTAB                     ; end of program?
+                bne L89B4                       ; brif not
+                stx VARTAB                      ; save new start of variables/end of program
+L89BF           rts
+; LINE INPUT
+L89C0           jsr L8866                       ; raise error if in immediate mode
+                jsr GETNCH                      ; eat the "INPUT" token
+                cmpa #'#                        ; device number?
+                bne L89D2                       ; brif not
+                jsr LA5A5                       ; parse device number
+                jsr LA3ED                       ; make sure it's valid for input
+                jsr SYNCOMMA                    ; make sure there's a comma after the device number
+L89D2           cmpa #'"                        ; is there a prompt?
+                bne L89E1                       ; brif not
+                jsr LB244                       ; parse the string
+                ldb #';                         ; make sure there's a semicolon after the prompt
+                jsr LB26F
+                jsr LB99F                       ; go actually display the prompt
+L89E1           leas -2,s                       ; make a hole on the stack (so number of return adddresses is right)
+                jsr LB035                       ; read an input line from current device
+                leas 2,s                        ; clean up stack
+                clr DEVNUM                      ; reset to screen/keyboard
+                jsr LB357                       ; parse a variable
+                stx VARDES                      ; save pointer to it
+                jsr LB146                       ; make sure it's a string
+                ldx #LINBUF                     ; point to input buffer
+                clra                            ; make sure we terminate on NUL only
+                jsr LB51A                       ; parse string and store it in string space
+                jmp LAFA4                       ; go assign the string to its final resting place
+; RENUM command
+L89FC           jsr LAF67                       ; read a line number
+                ldx BINVAL                      ; get value
+                rts
+L8A02           ldx VD1                         ; get current old number being renumbered
+L8A04           stx BINVAL                      ; save number being searched for
+                jmp LAD01                       ; go find line number
+RENUM           jsr LAD26                       ; erase variables
+                ldd #10                         ; default line number interval and start
+                std VD5                         ; set starting line number
+                std VCF                         ; set number interval
+                clrb                            ; now D is 0
+                std VD1                         ; save default start for renumbering
+                jsr GETCCH                      ; are there any arguments
+                bcc L8A20                       ; brif not numeric
+                bsr L89FC                       ; fetch line number
+                stx VD5                         ; save line beginning number
+                jsr GETCCH                      ; get input character
+L8A20           beq L8A3D                       ; brif end of line
+                jsr SYNCOMMA                    ; make sure we have a comma
+                bcc L8A2D                       ; brif next isn't numeric
+                bsr L89FC                       ; fetch starting line number
+                stx VD1                         ; save the number where we start working
+                jsr GETCCH                      ; fetch input character
+L8A2D           beq L8A3D                       ; brif end of line
+                jsr SYNCOMMA                    ; make sure we have a comma
+                bcc L8A3A                       ; brif we don't have a number
+                bsr L89FC                       ; parse the number
+                stx VCF                         ; save interval
+                beq L8A83                       ; brif we ave a zero interval
+L8A3A           jsr LA5C7                       ; raise error if more stuff
+L8A3D           bsr L8A02                       ; get address of old number to process
+                stx VD3                         ; save address
+                ldx VD5                         ; get the next renumbered line to use
+                bsr L8A04                       ; find that line
+                cmpx VD3                        ; is it before the previous one?
+                blo L8A83                       ; brif so - raise error
+                bsr L8A67                       ; make sure renumbered line numbers will be in range
+                jsr L8ADD                       ; convert line numbers to "expanded" binary
+                jsr LACEF                       ; recalculate next line pointers
+                bsr L8A02                       ; get address of first line to renumber
+                stx VD3                         ; save it
+                bsr L8A91                       ; make sure line numbers exist
+                bsr L8A68                       ; renumber the actual lines
+                bsr L8A91                       ; update line numbers in program text
+                jsr L8B7B                       ; convert packed binary line numbers to text
+                jsr LAD26                       ; erase variables, reset stack, etc.
+                jsr LACEF                       ; recalculate next line pointers
+                jmp LAC73                       ; bounce back to immediate mode
+L8A67           skip1lda                        ; set line number flag to nonzero (skip next instruction)
+L8A68           clra                            ; set line number flag to zero (insert new numbers)
+                sta VD8                         ; save line number flag
+                ldx VD3                         ; get address of line being renumbered
+                ldd VD5                         ; get the current renumbering number
+                bsr L8A86                       ; return if end of program
+L8A71           tst VD8                         ; test line number flag
+                bne L8A77                       ; brif not adding new numbers
+                std 2,x                         ; set new number
+L8A77           ldx ,x                          ; point to next line
+                bsr L8A86                       ; return if end of program
+                addd VCF                        ; add interval to current number
+                bcs L8A83                       ; brif we overflowed - bad line number
+                cmpa #MAXLIN                    ; maximum legal number?
+                blo L8A71                       ; brif so - do another
+L8A83           jmp LB44A                       ; raise FC error
+L8A86           pshs d                          ; save D (we're going to clobber it)
+                ldd ,x                          ; get next line pointer
+                puls d                          ; unclobber D
+                bne L8A90                       ; brif not end of program
+                leas 2,s                        ; return to caller's caller
+L8A90           rts
+L8A91           ldx TXTTAB                      ; get start of program
+                leax -1,x                       ; move pointer back one (compensate for leax 1,x below)
+L8A95           leax 1,x                        ; move to next line
+                bsr L8A86                       ; return if end of program
+L8A99           leax 3,x                        ; move past next line address and line number, go one before line
+L8A9B           leax 1,x                        ; move to next character
+                lda ,x                          ; check input character
+                beq L8A95                       ; brif end of line
+                stx TEMPTR                      ; save current pointer
+                deca                            ; is it start of packed numeric line number?
+                beq L8AB2                       ; brif so
+                deca                            ; does line exist?
+                beq L8AD3                       ; brif line number exists
+                deca                            ; not part of something to process?
+                bne L8A9B                       ; brif so
+L8AAC           lda #3                          ; set 1st byte to 3 to indicate line number not existing
+                sta ,x+
+                bra L8A99                       ; go process another
+L8AB2           ldd 1,x                         ; get MSB of line number
+                dec 2,x                         ; is MS byte zero?
+                beq L8AB9                       ; brif not
+                clra                            ; set MS byte to 0
+L8AB9           ldb 3,x                         ; get LSB of line number
+                dec 4,x                         ; is it zero?
+                beq L8AC0                       ; brif not
+                clrb                            ; clear byte
+L8AC0           std 1,x                         ; save binary number
+                std BINVAL                      ; save trial number
+                jsr LAD01                       ; find the line number
+L8AC7           ldx TEMPTR                      ; get start of packed line
+                bcs L8AAC                       ; brif line number not found
+                ldd V47                         ; get address of line number
+                inc ,x+                         ; bump first byte to 2 (exists if checking) or 1 if inserting
+                std ,x                          ; save address of correct number
+                bra L8A99                       ; go process more
+L8AD3           clr ,x                          ; clear carry and first byte
+                ldx 1,x                         ; point to address of correct line
+                ldx 2,x                         ; get correct line number
+                stx V47                         ; save it
+                bra L8AC7                       ; insert into line
+L8ADD           ldx TXTTAB                      ; get beginning of program
+                bra L8AE5
+L8AE1           ldx CHARAD                      ; get input pointer
+                leax 1,x                        ; move it forward
+L8AE5           bsr L8A86                       ; return if end of program
+                leax 2,x                        ; move past line address
+L8AE9           leax 1,x                        ; move forward
+L8AEB           stx CHARAD                      ; save input pointer
+L8AED           jsr GETNCH                      ; get an input character
+L8AEF           tsta                            ; is it actual 0?
+                beq L8AE1                       ; brif end of line
+                bpl L8AED                       ; brif not a token
+                ldx CHARAD                      ; get input pointer
+                cmpa #0xff                      ; function?
+                beq L8AE9                       ; brif so - ignore it (and following byte)
+                jsr RVEC22                      ; do the RAM hook thing
+                cmpa #0xa7                      ; THEN?
+                beq L8B13                       ; brif so
+                cmpa #0x84                      ; ELSE?
+                beq L8B13                       ; brif so
+                cmpa #0x81                      ; GO(TO|SUB)?
+                bne L8AED                       ; brif not - we don't have a line number
+                jsr GETNCH                      ; get TO/SUB
+                cmpa #0xa5                      ; GOTO?
+                beq L8B13                       ; brif so
+                cmpa #0xa6                      ; GOSUB?
+                bne L8AEB                       ; brif not
+L8B13           jsr GETNCH                      ; fetch character after token
+                bcs L8B1B                       ; brif numeric (line number)
+L8B17           jsr GETCCH                      ; set flags on input character
+                bra L8AEF                       ; keep checking for line numbers
+L8B1B           ldx CHARAD                      ; get input pointer
+                pshs x                          ; save it
+                jsr LAF67                       ; parse line number
+                ldx CHARAD                      ; get input pointer after line
+L8B24           lda ,-x                         ; get character before pointer
+                jsr L90AA                       ; set C if numeric
+                bcs L8B24                       ; brif not numeric
+                leax 1,x                        ; move pointer up
+                tfr x,d                         ; calculate size of line number
+                subb 1,s
+                subb #5                         ; make sure at least 5 bytes
+                beq L8B55                       ; brif exactly 5 bytes - no change
+                blo L8B41                       ; brif less than 5 bytes
+                leau ,x                         ; move remainder of program backward
+                negb                            ; negate extra number of bytes (to subtract from X)
+                leax b,x                        ; now X is the correct position to move program to
+                jsr L89B8                       ; shift program backward
+                bra L8B55
+L8B41           stx V47                         ; save end of line number space (end of copy)
+                ldx VARTAB                      ; get end of program
+                stx V43                         ; set source pointer
+                negb                            ; get positive difference
+                leax b,x                        ; now X is the top of the destination block
+                stx V41                         ; set copy destination
+                stx VARTAB                      ; save new end of program
+                jsr LAC1E                       ; make sure enough room and make a hole in the program
+                ldx V45                         ; get end address of destination block
+                stx CHARAD                      ; set input there
+L8B55           puls x                          ; get starting address of the line number
+                lda #1                          ; set "new number" flag
+                sta ,x
+                sta 2,x
+                sta 4,x
+                ldb BINVAL                      ; get MS byte of line number
+                bne L8B67                       ; brif it is not zero
+                ldb #1                          ; set to 1 if MSB is 0
+                inc 2,x                         ; flag MSB as 0
+L8B67           stb 1,x                         ; set MSB of line number
+                ldb BINVAL+1                    ; get LSB of number
+                bne L8B71                       ; brif nonzero
+                ldb #1                          ; set to 1 if LSB is 0
+                inc 4,x                         ; flag LSB as 0
+L8B71           stb 3,x                         ; save LSB of line number
+                jsr GETCCH                      ; get input character
+                cmpa #',                        ; multiple line numbers? (ON GOTO, ON GOSUB)
+                beq L8B13                       ; brif so - process another
+                bra L8B17                       ; go look for more line numbers
+L8B7B           ldx TXTTAB                      ; point to start of program
+                leax -1,x                       ; move back (compensate for inc below)
+L8B7F           leax 1,x                        ; move forward
+                ldd 2,x                         ; get this line number
+                std CURLIN                      ; save it (for error message)
+                jsr L8A86                       ; return if end of program
+                leax 3,x                        ; skip address and line number, stay one before line text
+L8B8A           leax 1,x                        ; move to next character
+L8B8C           lda ,x                          ; get input character
+                beq L8B7F                       ; brif end of line
+                deca                            ; valid line new line number?
+                beq L8BAE                       ; brif so
+                suba #2                         ; undefined line?
+                bne L8B8A                       ; brif not
+                pshs x                          ; save line number pointer
+                ldx #L8BD9-1                    ; show UL message
+                jsr STRINOUT
+                ldx ,s                          ; get input pointer
+                ldd 1,x                         ; get undefined line number
+                jsr LBDCC                       ; display line number
+                jsr LBDC5                       ; print out "IN XXXX"
+                jsr LB958                       ; do a newline
+                puls x                          ; get input pointer back
+L8BAE           pshs x                          ; save input pointer
+                ldd 1,x                         ; get binary value of line number
+                std FPA0+2                      ; save it in FPA0
+                jsr L880E                       ; adjust FPA0 as integer
+                jsr LBDD9                       ; convert to text string
+                puls u                          ; get previous input pointer address
+                ldb #5                          ; each expanded line uses 5 bytes
+L8BBE           leax 1,x                        ; move pointer forward (in string number) past sign
+                lda ,x                          ; do we have a digit?
+                beq L8BC9                       ; brif not - end of number
+                decb                            ; mark a byte consumed
+                sta ,u+                         ; put digit in program
+                bra L8BBE                       ; copy another digit
+L8BC9           leax ,u                         ; point to address at end of text number
+                tstb                            ; did number fill whole space?
+                beq L8B8C                       ; brif so - move on
+                leay ,u                         ; save end of number pointer
+                leau b,u                        ; point to the end of the original expanded number
+                jsr L89B8                       ; close up gap in program
+                leax ,y                         ; get end of line number pointer back
+                bra L8B8C                       ; go process more
+L8BD9           fcn 'UL '
+; HEX$ function
+HEXDOL          jsr LB740                       ; convert argument to positive integer
+                ldx #STRBUF+2                   ; point to string buffer
+                ldb #4                          ; convert 4 nibbles
+L8BE5           pshs b                          ; save nibble counter
+                clrb                            ; clear digit accumulator
+                lda #4                          ; do 4 shifts
+L8BEA           asl FPA0+3                      ; shift a bit off the left of the value into low bits of B
+                rol FPA0+2
+                rolb
+                deca                            ; done all shifts?
+                bne L8BEA                       ; brif not
+                tstb                            ; do we have a nonzero digit?
+                bne L8BFF                       ; brif so
+                lda ,s                          ; is it last digit?
+                deca
+                beq L8BFF                       ; brif so - keep the 0
+                cmpx #STRBUF+2                  ; is it a middle zero?
+                beq L8C0B                       ; brif not
+L8BFF           addb #'0                        ; add ASCII bias
+                cmpb #'9                        ; above 9?
+                bls L8C07                       ; brif not
+                addb #7                         ; adjust into alpha range
+L8C07           stb ,x+                         ; save digit in output
+                clr ,x                          ; make sure we have a NUL term
+L8C0B           puls b                          ; get back nibble counter
+                decb                            ; done all?
+                bne L8BE5                       ; brif not
+                leas 2,s                        ; don't return mainline (we're returning a string)
+                ldx #STRBUF+1                   ; point to start of converted number
+                jmp LB518                       ; save string in string space, etc., and return it
+; DLOAD command; this is eliminated on the Coco3. It was basically useless anyway so it was
+; a good candidate to overwrite for some extra code space in the lower 16K of the internal
+; ROM. Now, DLOAD functions as another entry into the RESET sequence.
+DLOAD           jsr LA429                       ; close tape file
+L8C1B           orcc #0x50                      ; make sure interrupts are disabled
+                lda #MC3+MC1                    ; disable MMU, 32K internal ROM, not "coco" compatible
+                sta INIT0
+                clr TYCLR                       ; go to ROM mapping mode
+                jmp SC000                       ; transfer control to the "hidden" init code
+L8C28           clr INT.FLAG                    ; set the interrupt flag to not valid
+                clr PIA1+3                      ; disable cartridge interrupt
+L8C2E           lda #COCO+MMUEN+MC3+MC2         ; enable SCS, 16K split, MMU, COCO mode
+                sta INIT0
+                clr TYCLR                       ; go to ROM mode
+L8C36           rts
+L8C37           pshs a,b,x                      ; save registers
+                ldx CURPOS                      ; get cursor position
+                ldb HRWIDTH                     ; hi-res mode?
+                lbne ALINK22                    ; brif so
+                ldb 1,s                         ; restore B
+                jmp LA30E                       ; go back to mainline code
+L8C46           pshs cc                         ; save Z
+                tst HRWIDTH                     ; hi-res?
+                beq L8C4F                       ; brif not
+                jmp ALINK23                     ; go to hi-res handler
+L8C4F           puls cc                         ; get back Z
+                jmp LA913                       ; go back to mainline code
+                nop
+                fcb 0xc7                        ; junk byte (too few NOPs above)
+; This returns to the remainder of the original ECB 1.1 DLOAD code
+                tstb                            ; ASCII?
+                beq L8C5F                       ; brif not - do error
+                jsr LAD19                       ; clear out program
+                jmp LAC7C                       ; go read program
+L8C5F           jmp LA616                       ; raise bad file mode
+; CLOADM patch for Extended Basic
+L8C62           jsr GETNCH                      ; get character after CLOAD
+                cmpa #'M                        ; CLOADM?
+                lbne CLOAD                      ; brif not - Color Basic's CLOAD can handle it
+                clr FILSTA                      ; close tape file
+                jsr GETNCH                      ; eat the "M"
+                jsr LA578                       ; parse file name
+                jsr LA648                       ; find the file
+                tst CASBUF+10                   ; is it a chunked file?
+                lbeq LA505                      ; brif not - Color Basic's CLOADM can handle it
+                ldu CASBUF+8                    ; get file type and ASCII flag
+                dec DEVNUM                      ; set source device to tape
+                jsr LA635                       ; go read the first block
+                tfr u,d                         ; put type and ASCII flag somewhere more useful
+; NOTE: DLOADM comes here to do the final processing
+L8C85           subd #0x200                     ; is it binary and "machine language"?
+                bne L8C5F                       ; brif not - raise an error
+                ldx ZERO                        ; default load offset
+                jsr GETCCH                      ; is there any offset?
+                beq L8C96                       ; brif not
+                jsr SYNCOMMA                    ; make sure there's a comma
+                jsr LB73D                       ; evaluate offset in X
+L8C96           stx VD3                         ; save offset
+                jsr LA5C7                       ; raise error if more stuff follows
+L8C9B           bsr L8CC6                       ; get type of "amble"
+                pshs a                          ; save it
+                bsr L8CBF                       ; read in block length
+                tfr d,y                         ; save it
+                bsr L8CBF                       ; read in load address
+                addd VD3                        ; add in offset
+                std EXECJP                      ; save it as the execution address
+                tfr d,x                         ; put load address in a pointer
+                lda ,s+                         ; get "amble" type
+                lbne LA42D                      ; brif postamble - close file
+L8CB1           bsr L8CC6                       ; read a data byte
+                sta ,x                          ; save in memory
+                cmpa ,x+                        ; did it actually save?
+                bne L8CCD                       ; brif not RAM - raise error
+                leay -1,y                       ; done yet?
+                bne L8CB1                       ; brif not
+                bra L8C9B                       ; look for another "amble"
+L8CBF           bsr L8CC1                       ; read a character to B
+L8CC1           bsr L8CC6                       ; read character to A
+                exg a,b                         ; swap character with previously read one
+L8CC5           rts
+L8CC6           jsr LA176                       ; read a character from input
+                tst CINBFL                      ; EOF?
+                beq L8CC5                       ; brif not
+L8CCD           jmp LA619                       ; raise I/O error if EOF
+L8CD0           bsr L8D14                       ; transmit file name
+                pshs b,a                        ; save file status
+                inca                            ; was file found?
+                beq L8CDD                       ; brif not
+                ldu ZERO                        ; zero U - first block
+                bsr L8CE4                       ; read block
+                puls a,b,pc                     ; restore status and return
+L8CDD           ldb #2*26                       ; code for NE error
+                jmp LAC46                       ; raise error
+L8CE2           ldu CBUFAD                      ; get block number
+L8CE4           leax 1,u                        ; bump block number
+                stx CBUFAD                      ; save new block number
+                ldx #CASBUF                     ; use cassette buffer
+                jsr L8D7C                       ; read a block
+                jmp LA644                       ; reset input buffer pointers
+; Generic input handler for Extended Basic
+XVEC4           lda DEVNUM                      ; get device number
+                cmpa #-3                        ; DLOAD?
+                bne L8D01                       ; brif not
+                leas 2,s                        ; don't return to mainline code
+                clr CINBFL                      ; reset EOF flag to not EOF
+                tst CINCTR                      ; anything available?
+                bne L8D02                       ; brif so - fetch one
+                com CINBFL                      ; flag EOF
+L8D01           rts
+L8D02           pshs u,y,x,b                    ; save registers
+                ldx CINPTR                      ; get buffer pointer
+                lda ,x+                         ; get character from buffer
+                pshs a                          ; save it for return
+                stx CINPTR                      ; save new input pointer
+                dec CINCTR                      ; account for byte removed from buffer
+                bne L8D12                       ; brif buffer not empty
+                bsr L8CE2                       ; go read a block
+L8D12           puls a,b,x,y,u,pc               ; restore registers, return value, and return
+L8D14           clra                            ; clear attempt counter
+                pshs x,b,a                      ; make a hole for variables
+                leay ,s                         ; set up frame pointer
+                bra L8D1D                       ; go read block
+L8D1B           bsr L8D48                       ; bump attempt counter
+L8D1D           lda #0x8a                       ; send file request control code
+                bsr L8D58
+                bne L8D1B                       ; brif no echo or error
+                ldx #CFNBUF+1                   ; point to file name
+L8D26           lda ,x+                         ; get file name characater
+                jsr L8E04                       ; send it
+                cmpx #CFNBUF+9                  ; end of file name?
+                bne L8D26                       ; brif not
+                bsr L8D62                       ; output check byte and look for response
+                bne L8D1B                       ; transmit name again if not ack
+                bsr L8D72                       ; get file type (0xff is not found)
+                bne L8D1B                       ; brif error
+                sta 2,y                         ; save file type
+                bsr L8D72                       ; read ASCII flag
+                bne L8D1B                       ; brif error
+                sta 3,y                         ; save ASCII flag
+                bsr L8D6B                       ; read check byte
+                bne L8D1B                       ; brif error
+                leas 2,s                        ; lose attempt counter and check byte
+                puls a,b,pc                     ; return file type and ascii flag
+L8D48           inc ,y                          ; bump attempt counter
+                lda ,y                          ; get new count
+                cmpa #5                         ; done 5 times?
+                blo L8D6A                       ; brif not
+                lda #0xbc                       ; send abort code
+                jsr L8E0C
+                jmp LA619                       ; raise an I/O error
+L8D58           pshs a                          ; save compare character
+                bsr L8DB8                       ; send character
+                bne L8D60                       ; brif read error
+                cmpa ,s                         ; does it match? (set Z if good)
+L8D60           puls a,pc                       ; restore character and return
+L8D62           lda 1,y                         ; get XOR check byte
+                bsr L8DB8                       ; send it and read
+                bne L8D6A                       ; brif read error
+                cmpa #0xc8                      ; is it ack? (set Z if so)
+L8D6A           rts
+L8D6B           bsr L8D72                       ; read character from rs232
+                bne L8D6A                       ; brif error
+                lda 1,y                         ; get check byte
+                rts
+L8D72           bsr L8DBC                       ; read a character from rs232
+                pshs a,cc                       ; save result (and flags)
+                eora 1,y                        ; accumulate xor checksum
+                sta 1,y
+                puls cc,a,pc                    ; restore byte, flags, and return
+L8D7C           clra                            ; reset attempt counter
+                pshs u,y,x,b,a                  ; make a stack frame
+                asl 7,s                         ; split block number into two 7 bit chuncks
+                rol 6,s
+                lsr 7,s
+                leay ,s                         ; set up frame pointer
+                bra L8D8B
+L8D89           bsr L8D48                       ; bump attempt counter
+L8D8B           lda #0x97                       ; send block request code
+                bsr L8D58
+                bne L8D89                       ; brif error
+                lda 6,y                         ; send out block number (high bits first)
+                bsr L8E04
+                lda 7,y
+                bsr L8E04
+                bsr L8D62                       ; send check byte and get ack
+                bne L8D89                       ; brif error
+                bsr L8D72                       ; read block size
+                bne L8D89                       ; brif read error
+                sta 4,y                         ; save character count
+                ldx 2,y                         ; get buffer pointer
+                ldb #128                        ; length of data block
+L8DA7           bsr L8D72                       ; read a data byte
+                bne L8D89                       ; brif error
+                sta ,x+                         ; save byte in buffer
+                decb                            ; done a whole block?
+                bne L8DA7                       ; brif not
+                bsr L8D6B                       ; read check byte
+                bne L8D89                       ; brif error
+                leas 4,s                        ; lose attempt counter, check byte, and buffer pointer
+                puls a,b,x,pc                   ; return with character count in A, clean rest of stack
+L8DB8           clr 1,y                         ; clear check byte
+                bsr L8E0C                       ; output character
+L8DBC           clra                            ; clear attempt counter
+                pshs x,b,cc                     ; save registers and interrupt status
+                orcc #0x50                      ; disable interrupts
+                lda TIMOUT                      ; get timout delay (variable)
+                ldx ZERO                        ; get constant timeout value
+L8DC5           bsr L8DE6                       ; get RS232 status
+                bcc L8DC5                       ; brif "space" - waiting for "mark"
+L8DC9           bsr L8DE6                       ; get RS232 status
+                bcs L8DC9                       ; brif "mark" - waiting for "space" (start bit)
+                bsr L8DF9                       ; delay for half of bit time
+                ldb #1                          ; set bit probe
+                pshs b                          ; save it
+                clra                            ; reset data byte
+L8DD4           bsr L8DF7                       ; wait one bit time
+                ldb PIA1+2                      ; get input bit to carry
+                rorb
+                bcc L8DDE                       ; brif "space" (0)
+                ora ,s                          ; merge bit probe in
+L8DDE           asl ,s                          ; shift bit probe over
+                bcc L8DD4                       ; brif we haven't done 8 bits
+                leas 1,s                        ; remove bit probe
+                puls cc,b,x,pc                  ; restore interrupts, registers, and return
+L8DE6           ldb PIA1+2                      ; get RS232 value
+                rorb                            ; put in C
+                leax 1,x                        ; bump timeout 
+                bne L8DF6                       ; brif nonzero
+                deca                            ; did the number of waits expire?
+                bne L8DF6                       ; brif not
+                leas 2,s                        ; don't return - we timed out
+                puls cc,b,x                     ; restore interrupts and registers
+                inca                            ; clear Z (A was zero above)
+L8DF6           rts
+L8DF7           bsr L8DF9                       ; do first half of bit delay then fall through for second
+L8DF9           pshs a                          ; save register
+                lda DLBAUD                      ; get baud rate constant
+L8DFD           brn L8DFD                       ; do nothing - delay
+                deca                            ; time expired?
+                bne L8DFD                       ; brif not
+                puls a,pc                       ; restore register and return
+L8E04           pshs a                          ; save character to send
+                eora 1,y                        ; accumulate chechsum
+                sta 1,y
+                puls a                          ; get character back
+L8E0C           pshs b,a,cc                     ; save registers and interrupt status
+                orcc #0x50                      ; disable interrupts
+                bsr L8DF7                       ; do a bit delay
+                bsr L8DF7                       ; do another bit delay
+                clr PIA1                        ; set output to space (start bit)
+                bsr L8DF7                       ; do a bit delay
+                ldb #1                          ; bit probe start at LSB
+                pshs b                          ; save bitprobe
+L8E1D           lda 2,s                         ; get output byte
+                anda ,s                         ; see what our current bit is
+                beq L8E25                       ; brif output is 0
+                lda #2                          ; set output to "marking"
+L8E25           sta PIA1                        ; send bit
+                bsr L8DF7                       ; do a bit delay
+                asl ,s                          ; shift bit probe
+                bcc L8E1D                       ; brif not last bit
+                lda #2                          ; set output to marking ("stop" bit)
+                sta PIA1
+                leas 1,s                        ; lose bit probe
+                puls cc,a,b,pc                  ; restore registers, interrupts, and return
+; PRINT USING
+; This is a massive block of code for something that has limited utility. It is *almost* flexible enough to
+; be truly useful outside of a narrow range of use cases. Indeed, this comes in at about 1/8 of the total
+; Extended Color Basic ROM.
+;
+; This uses several variables:
+; VD5: pointer to format string descriptor
+; VD7: next print item flag
+; VD8: right digit counter
+; VD9: left digit counter (or length of string argument)
+; VDA: status byte (bits as follows):
+;     6: force comma
+;     5: force leading *
+;     4: floating $
+;     3: pre-sign
+;     2: post-sign
+;     0: scientific notation
+L8E37           lda #1                          ; set length to use to 1
+                sta VD9
+L8E3B           decb                            ; consume character from format string
+                jsr L8FD8                       ; show error flag if flags set
+                jsr GETCCH                      ; get input character
+                lbeq L8ED8                      ; brif end of line - bail
+                stb VD3                         ; save remaining string length
+                jsr LB156                       ; evaluate the argument
+                jsr LB146                       ; error if numeric
+                ldx FPA0+2                      ; get descriptor for argument
+                stx V4D                         ; save it for later
+                ldb VD9                         ; get length counter to use
+                jsr LB6AD                       ; get B bytes of string space (do a LEFT$)
+                jsr LB99F                       ; print the formatted string
+                ldx FPA0+2                      ; get formatted string descriptor
+                ldb VD9                         ; get requested length
+                subb ,x                         ; see if we have any left over
+L8E5F           decb                            ; have we got the right width?
+                lbmi L8FB3                      ; brif so - go process more
+                jsr LB9AC                       ; output a space
+                bra L8E5F                       ; go see if we're done yet
+L8E69           stb VD3                         ; save current format string counter and pointer
+                stx TEMPTR
+                lda #2                          ; initial spaces count = 2 (for the two %s)
+                sta VD9                         ; save length counter
+L8E71           lda ,x                          ; get character in string
+                cmpa #'%                        ; is it the end of the sequence?
+                beq L8E3B                       ; brif so - display requested part of the strign
+                cmpa #0x20                      ; space?
+                bne L8E82                       ; brif not
+                inc VD9                         ; bump spaces count
+                leax 1,x                        ; move format pointer forward
+                decb                            ; consume character
+                bne L8E71                       ; brif not end of format string
+L8E82           ldx TEMPTR                      ; restore format string pointer
+                ldb VD3                         ; get back format string length
+                lda #'%                         ; show % as debugging aid
+L8E88           jsr L8FD8                       ; send error indicator if flags set
+                jsr PUTCHR                      ; output character
+                bra L8EB9                       ; go process more format string
+; PRINT extension for USING
+XVEC9           cmpa #0xcd                      ; USING?
+                beq L8E95                       ; brif so
+                rts                             ; return to mainline code
+; This is the main entry point for PRINT USING
+L8E95           leas 2,s                        ; don't return to the mainline code
+                jsr LB158                       ; evaluate the format string
+                jsr LB146                       ; error if numeric
+                ldb #';                         ; make sure there's a ; after the string
+                jsr LB26F
+                ldx FPA0+2                      ; get format string descriptor
+                stx VD5                         ; save it for later
+                bra L8EAE                       ; process format string
+L8EA8           lda VD7                         ; is there a print item?
+                beq L8EB4                       ; brif not
+                ldx VD5                         ; get back format string descriptor
+L8EAE           clr VD7                         ; reset next print item flag
+                ldb ,x                          ; get length of format string
+                bne L8EB7                       ; brif string is non-null
+L8EB4           jmp LB44A                       ; raise FC error
+L8EB7           ldx 2,x                         ; point to start of string
+L8EB9           clr VDA                         ; clear status (new item)
+L8EBB           clr VD9                         ; clear left digit counter
+                lda ,x+                         ; get character from format string
+                cmpa #'!                        ; ! (use first character of string)?
+                lbeq L8E37                      ; brif so
+                cmpa #'#                        ; digit?
+                beq L8F24                       ; brif so - handle numeric
+                decb                            ; consume format character
+                bne L8EE2                       ; brif not done
+                jsr L8FD8                       ; show a "+" if any flags set - indicates error at end of string
+                jsr PUTCHR                      ; output format string character
+L8ED2           jsr GETCCH                      ; get current input character
+                bne L8EA8                       ; brif not end of statement
+                lda VD7                         ; get next item flag
+L8ED8           bne L8EDD                       ; brif more print items
+                jsr LB958                       ; do newline
+L8EDD           ldx VD5                         ; point to format string descriptor
+                jmp LB659                       ; remove from string stack, etc., if appropriate (and return)
+L8EE2           cmpa #'+                        ; is it + (pre-sign)?
+                bne L8EEF                       ; brif not
+                jsr L8FD8                       ; send a "+" if flags set
+                lda #8                          ; flag for pre-sign
+                sta VDA                         ; set flags
+                bra L8EBB                       ; go interpret some more stuff
+L8EEF           cmpa #'.                        ; decimal?
+                beq L8F41                       ; brif so - numeric
+                cmpa #'%                        ; % (show string)?
+                lbeq L8E69                      ; brif so
+                cmpa ,x                         ; do we have two identical characters?
+L8EFB           bne L8E88                       ; brif not - invalid format character
+                cmpa #'$                        ; double $?
+                beq L8F1A                       ; brif so - floating $
+                cmpa #'*                        ; double *?
+                bne L8EFB                       ; brif not
+                lda VDA                         ; get status byte
+                ora #0x20                       ; enable * padding
+                sta VDA
+                cmpb #2                         ; is $$ the last two?
+                blo L8F20                       ; brif so
+                lda 1,x                         ; is it $ after?
+                cmpa #'$
+                bne L8F20                       ; brif not
+                decb                            ; consume the "$"
+                leax 1,x
+                inc VD9                         ; add to digit counter * pad + $ counter
+L8F1A           lda VDA                         ; indicate floating $
+                ora #0x10
+                sta VDA
+L8F20           leax 1,x                        ; consume the second format character
+                inc VD9                         ; add one more left place
+L8F24           clr VD8                         ; clear right digit counter
+L8F26           inc VD9                         ; bump left digit counter
+                decb                            ; consume character
+                beq L8F74                       ; brif end of string
+                lda ,x+                         ; get next format character
+                cmpa #'.                        ; decimal?
+                beq L8F4F                       ; brif so
+                cmpa #'#                        ; digit?
+                beq L8F26                       ; brif so
+                cmpa #',                        ; comma flag?
+                bne L8F5A                       ; brif not
+                lda VDA                         ; set commas flag
+                ora #0x40
+                sta VDA
+                bra L8F26                       ; handle more characters to left of decimal
+L8F41           lda ,x                          ; get character after .
+                cmpa #'#                        ; digit?
+                lbne L8E88                      ; brif not - invalid
+                lda #1                          ; set right digit counter to 1 (for the .)
+                sta VD8
+                leax 1,x                        ; consume the .
+L8F4F           inc VD8                         ; add one to right digit counter
+                decb                            ; consume character
+                beq L8F74                       ; brif end of format string
+                lda ,x+                         ; get another format character
+                cmpa #'#                        ; digit?
+                beq L8F4F                       ; brif so
+L8F5A           cmpa #0x5e                      ; up arrow?
+                bne L8F74                       ; brif not
+                cmpa ,x                         ; two of them?
+                bne L8F74                       ; brif not
+                cmpa 1,x                        ; three of them?
+                bne L8F74                       ; brif not
+                cmpa 2,x                        ; four of them?
+                bne L8F74                       ; brif not
+                cmpb #4                         ; string actually has the characters?
+                blo L8F74                       ; brif not
+                subb #4                         ; consome them
+                leax 4,x
+                inc VDA                         ; set scientific notation bit
+L8F74           leax -1,x                       ; back up input pointer
+                inc VD9                         ; add one digit for pre-sign force
+                lda VDA                         ; is it pre-sign?
+                bita #8
+                bne L8F96                       ; brif so
+                dec VD9                         ; undo pre-sign adjustment
+                tstb                            ; end of string?
+                beq L8F96                       ; brif so
+                lda ,x                          ; get next character
+                suba #'-                        ; post sign force?
+                beq L8F8F                       ; brif so
+                cmpa #'+-'-                     ; plus?
+                bne L8F96                       ; brif not
+                lda #8                          ; trailing + is a pre-sign force
+L8F8F           ora #4                          ; add in post sign flag
+                ora VDA                         ; merge with flags
+                sta VDA
+                decb                            ; consume character
+L8F96           jsr GETCCH                      ; do we have an argument
+                lbeq L8ED8                      ; brif not
+                stb VD3                         ; save format string length
+                jsr LB141                       ; evluate numeric expression
+                lda VD9                         ; get left digit counter
+                adda VD8                        ; add in right digit counter
+                cmpa #17                        ; is it more than 16 digits + decimal?
+                lbhi LB44A                      ; brif so - this is a problem
+                jsr L8FE5                       ; format value according to settings
+                leax -1,x                       ; move buffer pointer back
+                jsr STRINOUT                    ; display formatted number string
+L8FB3           clr VD7                         ; reset next print item flag
+                jsr GETCCH                      ; get current input character
+                beq L8FC6                       ; brif end of statement
+                sta VD7                         ; set next print flag to nonzero
+                cmpa #';                        ; list separator ;?
+                beq L8FC4                       ; brif so
+                jsr SYNCOMMA                    ; require a comma between if not ;
+                bra L8FC6                       ; process next item
+L8FC4           jsr GETNCH                      ; munch the semicolon
+L8FC6           ldx VD5                         ; get format string descriptor
+                ldb ,x                          ; get length of string
+                subb VD3                        ; subtract amount left after last item
+                ldx 2,x                         ; point to string address
+                abx                             ; move pointer to correct spot
+                ldb VD3                         ; get remaining string length
+                lbne L8EB9                      ; if we have more, interpret from there
+                jmp L8ED2                       ; re-interpret from start if we hit the end
+L8FD8           pshs a                          ; save character
+                lda #'+                         ; "error" flag character
+                tst VDA                         ; did we have some flags set?
+                beq L8FE3                       ; brif not
+                jsr PUTCHR                      ; output error flag
+L8FE3           puls a,pc                       ; restore character and return
+L8FE5           ldu #STRBUF+4                   ; point to string buffer
+                ldb #0x20                       ; blank space
+                lda VDA                         ; get flags
+                bita #8                         ; pre-sign?
+                beq L8FF2                       ; brif not
+                ldb #'+                         ; plus sign
+L8FF2           tst FP0SGN                      ; get sign of value
+                bpl L8FFA                       ; brif positive
+                clr FP0SGN                      ; make number positive (for later)
+                ldb #'-                         ; negative sign
+L8FFA           stb ,u+                         ; put sign in buffer
+                ldb #'0                         ; put a zero there
+                stb ,u+
+                anda #1                         ; check scientific notation force
+                lbne L910D                      ; brif so
+                ldx #LBDC0                      ; point to FP 1E+9
+                jsr LBCA0                       ; is it less?
+                bmi L9023                       ; brif so
+                jsr LBDD9                       ; convert FP number to string (we're doing scientific notation)
+L9011           lda ,x+                         ; advance pointer to end of string
+                bne L9011
+L9015           lda ,-x                         ; make a hole at the start
+                sta 1,x
+                cmpx #STRBUF+3                  ; done yet?
+                bne L9015                       ; brif not
+                lda #'%                         ; put "overflow" flag at start
+                sta ,x
+                rts
+L9023           lda FP0EXP                      ; get exponent of value
+                sta V47                         ; save it
+                beq L902C                       ; brif value is 0
+                jsr L91CD                       ; convert to number with 9 significant figures to left of decimal
+L902C           lda V47                         ; get base 10 exponent offset
+                lbmi L90B3                      ; brif < 100,000,000
+                nega                            ; get negative difference
+                adda VD9                        ; add to number of left digits
+                suba #9                         ; account for the 9 we actually have
+                jsr L90EA                       ; put leading zeroes in buffer
+                jsr L9263                       ; initialize the decimal point and comma counters
+                jsr L9202                       ; convert FPA0 to decimal ASCII in buffer
+                lda V47                         ; get base 10 exponent
+                jsr L9281                       ; put that many zeroes in buffer, stop at decimal point
+                lda V47                         ; get base 10 exponent
+                jsr L9249                       ; check for decimal
+                lda VD8                         ; get right digit counter
+                bne L9050                       ; brif we want stuff after decimal
+                leau -1,u                       ; delete decimal if not needed
+L9050           deca                            ; subtract one place (for decimal)
+                jsr L90EA                       ; put zeroes in buffer (trailing)
+L9054           jsr L9185                       ; insert * padding, floating $, and post-sign
+                tsta                            ; was there a post sign?
+                beq L9060                       ; brif not
+                cmpb #'*                        ; was first character a *?
+                beq L9060                       ; brif so
+                stb ,u+                         ; store the post sign
+L9060           clr ,u                          ; make srue it's NUL terminated
+                ldx #STRBUF+3                   ; point to start of buffer
+L9065           leax 1,x                        ; move to next character
+                stx TEMPTR                      ; save it for later
+                lda VARPTR+1                    ; get address of decimal point
+                suba TEMPTR+1                   ; subtract out actual digits left of decimal
+                suba VD9                        ; subtract out required left digits
+                beq L90A9                       ; brif no padding needed
+                lda ,x                          ; get current character
+                cmpa #0x20                      ; space?
+                beq L9065                       ; brif so - advance pointer
+                cmpa #'*                        ; *?
+                beq L9065                       ; brif so - advance pointer
+                clra                            ; zero on stack is end of data ponter
+L907C           pshs a                          ; save character on stack
+                lda ,x+                         ; get next character
+                cmpa #'-                        ; minus?
+                beq L907C                       ; brif so
+                cmpa #'+                        ; plus?
+                beq L907C                       ; brif so
+                cmpa #'$                        ; $?
+                beq L907C                       ; brif so
+                cmpa #'0                        ; zero?
+                bne L909E                       ; brif not
+                lda 1,x                         ; get character after 0
+                bsr L90AA                       ; clear carry if number
+                bcs L909E                       ; brif not number
+L9096           puls a                          ; get character off stack
+                sta ,-x                         ; put it back in string buffer
+                bne L9096                       ; brif not - restore another
+                bra L9065                       ; keep cleaning up buffer
+L909E           puls a                          ; get the character on the stack
+                tsta                            ; is it NUL?
+                bne L909E                       ; brif not
+                ldx TEMPTR                      ; get string buffer start pointer
+                lda #'%                         ; put error flag in front
+                sta ,-x
+L90A9           rts
+L90AA           cmpa #'0                        ; zero?
+                blo L90B2                       ; brif not
+                suba #'9+1                      ; set C if > "9"
+                suba #-('9+1)
+L90B2           rts
+L90B3           lda VD8                         ; get right digit counter
+                beq L90B8                       ; brif not right digits
+                deca                            ; account for decimal point
+L90B8           adda V47                        ; add base 10 exponent offset
+                bmi L90BD                       ; if >= 0, no shifts are required
+                clra                            ; force shift counter to 0
+L90BD           pshs a                          ; save shift counter
+L90BF           bpl L90CB                       ; brif positive count
+                pshs a                          ; save shift counter
+                jsr LBB82                       ; divide FPA0 by 10 (shift 1 digit to the right)
+                puls a                          ; get shift counter back
+                inca                            ; account for the shift
+                bra L90BF                       ; see if we're done yet
+L90CB           lda V47                         ; get base 10 exponent offset
+                suba ,s+                        ; account for adjustment
+                sta V47                         ; save new exponent offset
+                adda #9                         ; account for significant places
+                bmi L90EE                       ; brif we don't need zeroes to left
+                lda VD9                         ; get left decimal counter
+                suba #9                         ; account for significant figures
+                suba V47                        ; subtract exponent offset
+                bsr L90EA                       ; output leading zeroes
+                jsr L9263                       ; initialize decimal and comma counters
+                bra L90FF                       ; process remainder of digits
+L90E2           pshs a                          ; save zero counter
+                lda #'0                         ; insert a 0
+                sta ,u+
+                puls a                          ; get back counter
+L90EA           deca                            ; do we need more zeroes?
+                bpl L90E2                       ; brif so
+                rts
+L90EE           lda VD9                         ; get left digit counter
+                bsr L90EA                       ; put that many zeroes in
+                jsr L924D                       ; put decimal in buffer
+                lda #-9                         ; figure out filler zeroes
+                suba V47
+                bsr L90EA                       ; output required leader zeroes
+                clr V45                         ; clear decimal pointer counter
+                clr VD7                         ; clear comma counter
+L90FF           jsr L9202                       ; decode FPA0 to decimal string
+                lda VD8                         ; get right digit counter
+                bne L9108                       ; brif there are right digits
+                ldu VARPTR                      ; point to decimal location of decimal
+L9108           adda V47                        ; add base 10 exponent
+                lbra L9050                      ; add in leading astrisks, etc.
+L910D           lda FP0EXP                      ; get exponent of FPA0
+                pshs a                          ; save it
+                beq L9116                       ; brif 0
+                jsr L91CD                       ; convert to number with 9 figures
+L9116           lda VD8                         ; get right digit counter
+                beq L911B                       ; brif no right digits
+                deca                            ; account for decimal point
+L911B           adda VD9                        ; get left digit counter
+                clr STRBUF+3                    ; use buffer byte as temporary storage
+                ldb VDA                         ; get status flags
+                andb #4                         ; post-sign?
+                bne L9129                       ; brif so
+                com STRBUF+3                    ; flip byte if no post sign
+L9129           adda STRBUF+3                   ; subtract 1 if no post sign
+                suba #9                         ; account for significant figures
+                pshs a                          ; save shift counter
+L9130           bpl L913C                       ; brif no more shifts needed
+                pshs a                          ; save counter
+                jsr LBB82                       ; divide by 10 (shift right one)
+                puls a                          ; get back counter
+                inca                            ; account for the shift
+                bra L9130                       ; see if we need more
+L913C           lda ,s                          ; get original shift count
+                bmi L9141                       ; brif shifting happened
+                clra                            ; flag for no shifting
+L9141           nega                            ; calculate position of decimal (negate shift count, add left digit and post sign if needed)
+                adda VD9                        ; add left digit counter
+                inca                            ; and post sign
+                adda STRBUF+3
+                sta V45                         ; save decimal counter
+                clr VD7                         ; clear comma counter
+                jsr L9202                       ; convert to decimal string
+                puls a                          ; get shift counter
+                jsr L9281                       ; put the needed zeroes in
+                lda VD8                         ; get right digit counter
+                bne L915A                       ; brif we want some
+                leau -1,u                       ; remove te decimal point
+L915A           ldb ,s+                         ; get original exponent
+                beq L9167                       ; brif it was 0
+                ldb V47                         ; get base 10 exponent
+                addb #9                         ; account for significant figures
+                subb VD9                        ; remove left digit count
+                subb STRBUF+3                   ; add one if post sign
+L9167           lda #'+                         ; positive sign
+                tstb                            ; is base 10 exponent positive?
+                bpl L916F                       ; brif so
+                lda #'-                         ; negative sign
+                negb                            ; flip exponent
+L916F           sta 1,u                         ; put exponent sign
+                lda #'E                         ; put "E" and advance output pointer
+                sta ,u++
+                lda #'0-1                       ; initialize digit accumulator
+L9177           inca                            ; bump digit
+                subb #10                        ; are we at the right digit?
+                bcc L9177                       ; brif not
+                addb #'0+10                     ; add ASCII bias and undo extra subtraction
+                std ,u++                        ; save exponent in buffer
+                clr ,u                          ; clear final byte in buffer
+                jmp L9054                       ; insert *, $, etc.
+L9185           ldx #STRBUF+4                   ; point to start of result
+                ldb ,x                          ; get sign
+                pshs b                          ; save it
+                lda #0x20                       ; default pad with spaces
+                ldb VDA                         ; get flags
+                bitb #0x20                      ; padding with *?
+                puls b
+                beq L919E                       ; brif no padding
+                lda #'*                         ; pad with *
+                cmpb #0x20                      ; do we have a blank? (positive)
+                bne L919E                       ; brif not
+                tfr a,b                         ; use pad character
+L919E           pshs b                          ; save first character
+L91A0           sta ,x+                         ; store padding
+                ldb ,x                          ; get next character
+                beq L91B6                       ; brif end of string
+                cmpb #'E                        ; exponent?
+                beq L91B6                       ; brif so - treat as 0
+                cmpb #'0                        ; zero?
+                beq L91A0                       ; brif so - pad it
+                cmpb #',                        ; leading comma?
+                beq L91A0                       ; brif so - pad it
+                cmpb #'.                        ; decimal?
+                bne L91BA                       ; brif so - don't put a 0 before it
+L91B6           lda #'0                         ; put a zero before
+                sta ,-x
+L91BA           lda VDA                         ; get status byte
+                bita #0x10                      ; floating $?
+                beq L91C4                       ; brif not
+                ldb #'$                         ; stuff a $ in
+                stb ,-x
+L91C4           anda #4                         ; pre-sgn?
+                puls b                          ; get back first character
+                bne L91CC                       ; brif not
+                stb ,-x                         ; save leading character (sign)
+L91CC           rts
+L91CD           pshs u                          ; save buffer pointer
+                clra                            ; initial exponent offset is 0
+L91D0           sta V47                         ; save exponent offset
+                ldb FP0EXP                      ; get actual exponent
+                cmpb #0x80                      ; is value >= 1.0?
+                bhi L91E9                       ; brif so
+                ldx #LBDC0                      ; point to FP number 1E9
+                jsr LBACA                       ; multiply by 1000000000
+                lda V47                         ; account for 9 shifts
+                suba #9
+                bra L91D0                       ; brif not there yet
+L91E4           jsr LBB82                       ; divide by 10
+                inc V47                         ; account for shift
+L91E9           ldx #LBDBB                      ; point to 999999999
+                jsr LBCA0                       ; compare it
+                bgt L91E4                       ; brif not in range yet
+L91F1           ldx #LBDB6                      ; point to 99999999.9
+                jsr LBCA0                       ; compare
+                bgt L9200                       ; brif in range
+                jsr LBB6A                       ; multiply by 10
+                dec V47                         ; account for shift
+                bra L91F1                       ; see if we're in range yet
+L9200           puls u,pc                       ; restore buffer pointer and return
+L9202           pshs u                          ; save buffer pointer           
+                jsr LB9B4                       ; add .5 (round off)
+                jsr LBCC8                       ; convert to integer format
+                puls u                          ; restore buffer pointer
+                ldx #LBEC5                      ; point to 32 bit powers of 10 (alternating signs)
+                ldb #0x80                       ; intitial digit counter is 0 with 0x80 bias
+L9211           bsr L9249                       ; check for comma
+L9213           lda FPA0+3                      ; add a power of 10
+                adda 3,x
+                sta FPA0+3
+                lda FPA0+2
+                adca 2,x
+                sta FPA0+2
+                lda FPA0+1
+                adca 1,x
+                sta FPA0+1
+                lda FPA0
+                adca ,x
+                sta FPA0
+                incb                            ; add one to digit counter
+                rorb                            ; set V if carry and sign differ
+                rolb
+                bvc L9213                       ; brif we haven't "wrapped"
+                bcc L9235                       ; brif subtracting
+                subb #10+1                      ; take 9's complement if adding
+                negb
+L9235           addb #'0-1                      ; add in ASCII bias
+                leax 4,x                        ; move to next power
+                tfr b,a                         ; save digit
+                anda #0x7f                      ; mask off subtract flag
+                sta ,u+                         ; save digit
+                comb                            ; toggle add/subtract
+                andb #0x80
+                cmpx #LBEE9                     ; done all places?
+                bne L9211                       ; brif not
+                clr ,u                          ; but NUL at end
+L9249           dec V45                         ; at decimal?
+                bne L9256                       ; brif not
+L924D           stu VARPTR                      ; save decimal point pointer
+                lda #'.                         ; insert decimal
+                sta ,u+
+                clr VD7                         ; clear comma counter
+                rts
+L9256           dec VD7                         ; do we need a comma?
+                bne L9262                       ; brif not
+                lda #3                          ; reset comma counter
+                sta VD7
+                lda #',                         ; insert comma
+                sta ,u+
+L9262           rts
+L9263           lda V47                         ; get base 10 exponent offset
+                adda #10                        ; account for significant figures
+                sta V45                         ; save decimal counter
+                inca                            ; add one for decimal point
+L926A           suba #3                         ; divide by 3, leave remainder in A
+                bcc L926A
+                adda #5                         ; renormalize to range 1-3
+                sta VD7                         ; save comma counter
+                lda VDA                         ; get status
+                anda #0x40                      ; commas wanted?
+                bne L927A                       ; brif not
+                sta VD7                         ; clear comma counter
+L927A           rts
+L927B           pshs a                          ; save zeroes counter
+                bsr L9249                       ; check for decimal
+                puls a                          ; get back counter
+L9281           deca                            ; need a zero?
+                bmi L928E                       ; brif not
+                pshs a                          ; save counter
+                lda #'0                         ; put a zero
+                sta ,u+
+                lda ,s+                         ; get back counter and set flags
+                bne L927B                       ; brif not done enough
+L928E           rts
+; From here to the end of the Extended Basic ROM is the PMODE graphics system and related
+; infrastructure with the exception of the PLAY command which shares some of its machinery
+; with the DRAW command.
+;
+; Fetch screen address calculation routine address for the selected graphics mode
+L928F           ldu #L929C                      ; point to normalization routine jump table
+                lda PMODE                       ; get graphics mode
+                asla                            ; two bytes per address
+                ldu a,u                         ; get routine address
+                rts
+; Normalize VERBEG/HORBEG coordinates and return screen address in X and pixel mask in A.
+L9298           bsr L928F                       ; fetch normalization routine pointer
+                jmp ,u                          ; transfer control to it
+L929C           fdb L92A6                       ; PMODE 0
+                fdb L92C2                       ; PMODE 1
+                fdb L92A6                       ; PMODE 2
+                fdb L92C2                       ; PMODE 3
+                fdb L92A6                       ; PMODE 4
+; Two colour mode address calculatoin
+L92A6           pshs u,b                        ; savce registers
+                ldb HORBYT                      ; get number of bytes in each graphics row
+                lda VERBEG+1                    ; get vertical coordinate
+                mul
+                addd BEGGRP                     ; now D is the absolute address of the start of the row
+                tfr d,x                         ; get address to the return location
+                ldb HORBEG+1                    ; get horizontal coordinate
+                lsrb                            ; divide by 8 (8 pixels per byte in 2 colour mode)
+                lsrb
+                lsrb
+                abx                             ; now X is the address of the actual pixel byte
+                lda HORBEG+1                    ; get horizontal coordinate
+                anda #7                         ; keep only the low 3 bits which contain the pixel number
+                ldu #L92DD                      ; point to pixel mask lookup
+                lda a,u                         ; get pixel mask
+                puls b,u,pc                     ; restore registers and return result
+; four colour address calculation
+L92C2           pshs u,b                        ; save registers
+                ldb HORBYT                      ; get bytes per graphics row
+                lda VERBEG+1                    ; get vertical coordinate
+                mul
+                addd BEGGRP                     ; now D is the address of the start of the row
+                tfr d,x                         ; put it in returnlocatin
+                ldb HORBEG+1                    ; get horizontal coordinate
+                lsrb                            ; divide by 4 (four colour modes have four pixels per byte)
+                lsrb
+                abx                             ; now X points to the screen byte
+                lda HORBEG+1                    ; get horizontal coordinate
+                anda #3                         ; keep low two bits for pixel number
+                ldu #L92E5                      ; point to four colour pixel masks
+                lda a,u                         ; get pixel mask
+                puls b,u,pc                     ; restore registers and return result
+L92DD           fcb 0x80,0x40,0x20,0x10         ; two colour pixel masks
+                fcb 0x08,0x04,0x02,0x01
+L92E5           fcb 0xc0,0x30,0x0c,0x03         ; four colour pixel masks
+;  Move X down one graphics row
+L92E9           ldb HORBYT                      ; get bytes per row
+                abx                             ; add to screen address
+                rts
+; Move one pixel right in 2 colour mode
+L92ED           lsra                            ; move pixel mask right
+                bcc L92F3                       ; brif same byte
+                rora                            ; move pixel mask to left of byte
+                leax 1,x                        ; move to next byte
+L92F3           rts
+; Move one pixel right in 4 colour mode
+L92F4           lsra                            ; shift mask half a pixel right
+                bcc L92ED                       ; brif not past end of byte - shift one more
+                lda #0xc0                       ; set mask on left of byte
+                leax 1,x                        ; move to next byte
+                rts
+; Evaluate two expressions (coordinates). Put first in HORBEG and second in VERBEG.
+L92FC           jsr LB734                       ; evaluate two expressions - first in BINVAL, second in B
+                ldy #HORBEG                     ; point to storage location
+L9303           cmpb #192                       ; is vertical outside range?
+                blo L9309                       ; brif not
+                ldb #191                        ; max it at bottom of screen
+L9309           clra                            ; zero extend vertical coordinate
+                std 2,y                         ; save vertical coordinate
+                ldd BINVAL                      ; get horizontal coordinate
+                cmpd #256                       ; in range?
+                blo L9317                       ; brif so
+                ldd #255                        ; max it out to right side of screen
+L9317           std ,y                          ; save horizontal coordinate
+                rts
+; Normalize coordinates for proper PMODE
+L931A           jsr L92FC                       ; parse coordinates
+L931D           ldu #HORBEG                     ; point to start coordinates
+L9320           lda PMODE                       ; get graphics mode
+                cmpa #2                         ; is it pmode 0 or 1?
+                bhs L932C                       ; brif not
+                ldd 2,u                         ; get vertical coordinate
+                lsra                            ; divide it by two
+                rorb
+                std 2,u                         ; save it back
+L932C           lda PMODE                       ; get graphics mode
+                cmpa #4                         ; pmode 4?
+                bhs L9338                       ; brif so
+                ldd ,u                          ; cut horizontal coordinate in half
+                lsra
+                rorb
+                std ,u                          ; save new coordinate
+L9338           rts
+; PPOINT function
+PPOINT          jsr L93B2                       ; evaluate two expressions (coordinates)
+                jsr L931D                       ; normalize coordinates
+                jsr L9298                       ; get screen address
+                anda ,x                         ; get colour value of desired screen coordinate
+                ldb PMODE                       ; get graphics mode
+                rorb                            ; is it a two colour m ode?
+                bcc L935B                       ; brif so
+L9349           cmpa #4                         ; is it on rightmost bits?
+                blo L9351                       ; brif not
+                rora                            ; shift right
+                rora
+                bra L9349                       ; see if we're there yet
+L9351           inca                            ; colour numbers start at 1
+                asla                            ; add in colour set (0 or 8)
+                adda CSSVAL
+                lsra                            ; get colour in range of 0 to 8
+L9356           tfr a,b                         ; put result to B
+                jmp LB4F3                       ; return B as FP number
+L935B           tsta                            ; is pixel on?
+                beq L9356                       ; brif not, return 0 (off)
+                clra                            ; set colour number to "1"
+                bra L9351                       ; make it 1 or 5 and return
+; PSET command
+PSET            lda #1                          ; PSET flag
+                bra L9366                       ; go turn on the pixel
+; PRESET command
+PRESET          clra                            ; PRESET flag
+L9366           sta SETFLG                      ; store whether we're setting or resetting
+                jsr LB26A                       ; enforce (
+                jsr L931A                       ; evaluate coordinates
+                jsr L9581                       ; evaluate colour
+                jsr LB267                       ; enforce )
+                jsr L9298                       ; get address of pixel
+L9377           ldb ,x                          ; get screen data
+                pshs b                          ; save it
+                tfr a,b                         ; duplicate pixel mask
+                coma                            ; invert mask
+                anda ,x                         ; turn off screen pixel
+                andb ALLCOL                     ; adjust pixel mask to be the current colour
+                pshs b                          ; merge pixel data into the screen data
+                ora ,s+
+                sta ,x                          ; put it on screen
+                suba ,s+                        ; nonzero if screen data changed
+                ora CHGFLG                      ; propagate change flag
+                sta CHGFLG
+                rts
+; Evaluate two sets of coordinates separated by a minus sign. First at HORBEG,VERBEG and
+; second at HOREND,VEREND. If no first set, use HORDEF,VERDEF.
+L938F           ldx HORDEF                      ; set default start coords
+                stx HORBEG
+                ldx VERDEF
+                stx VERBEG
+                cmpa #0xac                      ; do we start with a -?
+                beq L939E                       ; brif no starting coordinates
+                jsr L93B2                       ; parse coordinates
+L939E           ldb #0xac                       ; make sure we have a -
+                jsr LB26F
+                jsr LB26A                       ; require a (
+                jsr LB734                       ; evaluate two expressions
+                ldy #HOREND                     ; point to storage location
+                jsr L9303                       ; process coordinates
+                bra L93B8                       ; finish up with a )
+L93B2           jsr LB26A                       ; make sure there's a (
+                jsr L92FC                       ; evaluate coordinates
+L93B8           jmp LB267                       ; force a )
+; LINE command
+LINE            cmpa #0x89                      ; is it LINE INPUT?
+                lbeq L89C0                      ; brif so - go handle it
+                cmpa #'(                        ; starting coord?
+                beq L93CE                       ; brif so
+                cmpa #0xac                      ; leading -?
+                beq L93CE                       ; brif so
+                ldb #'@                         ; if it isn't the above, make sure it's @
+                jsr LB26F
+L93CE           jsr L938F                       ; parse coordinates
+                ldx HOREND                      ; set ending coordinates as the defaults
+                stx HORDEF
+                ldx VEREND
+                stx VERDEF
+                jsr SYNCOMMA                    ; make sure we have a comma
+                cmpa #0xbe                      ; PRESET?
+                beq L93E9                       ; brif so
+                cmpa #0xbd                      ; PSET?
+                lbne LB277                      ; brif not
+                ldb #01                         ; PSET flag
+                skip1lda                        ; skip byte and set A nonzero
+L93E9           clrb                            ; PRESET flag
+                pshs b                          ; save PSET/PRESET flag
+                jsr GETNCH                      ; eat the PSET/PRESET
+                jsr L9420                       ; normalize coordinates
+                puls b                          ; get back PSET/PRESET flag
+                stb SETFLG                      ; flag which we're doing
+                jsr L959A                       ; set colour byte
+                jsr GETCCH                      ; get next bit
+                lbeq L94A1                      ; brif no box option
+                jsr SYNCOMMA                    ; make sure it's comma
+                ldb #'B                         ; make sure "B" for "box"
+                jsr LB26F
+                bne L9429                       ; brif something follows the B
+                bsr L9444                       ; draw horizontal line
+                bsr L946E                       ; draw vertical line
+                ldx HORBEG                      ; save horizontal coordinate
+                pshs x                          ; save it
+                ldx HOREND                      ; switch in horizontal end
+                stx HORBEG
+                bsr L946E                       ; draw vertical line
+                puls x                          ; get back original start
+                stx HORBEG                      ; put it back
+                ldx VEREND                      ; do the same dance with the vertical end
+                stx VERBEG
+                bra L9444                       ; draw horizontal line
+L9420           jsr L931D                       ; normalize the start coordinates
+                ldu #HOREND                     ; point to end coords
+                jmp L9320                       ; normalize those coordinates
+L9429           ldb #'F                         ; make sure we have "BF" for "filled box"
+                jsr LB26F
+                bra L9434                       ; fill the box
+L9430           leax -1,x                       ; move vertical coordinate up one
+L9432           stx VERBEG                      ; save new vertical coordinate
+L9434           jsr L9444                       ; draw a horizontal line
+                ldx VERBEG                      ; are we at the end of the box?
+                cmpx VEREND
+                beq L9443                       ; brif so
+                bcc L9430                       ; brif we're moving up the screen
+                leax 1,x                        ; move down the screen
+                bra L9432                       ; go draw another line
+L9443           rts
+; Draw a horizontal line from HORBEG to HOREND at VERBEG using color mask in ALLCOL
+L9444           ldx HORBEG                      ; get starting horizontal coordinate
+                pshs x                          ; save it
+                jsr L971D                       ; get absolute value of HOREND-HORBEG
+                bcc L9451                       ; brif end is > start
+                ldx HOREND                      ; copy end coordinate to start it is smaller
+                stx HORBEG
+L9451           tfr d,y                         ; save difference - it's a pixel count
+                leay 1,y                        ; coordinates are inclusive
+                jsr L9298                       ; get screen position of start coord
+                puls u                          ; restore original start coordinate
+                stu HORBEG
+                bsr L9494                       ; point to routine to move pizel pointers to right
+L945E           sta VD7                         ; save pixel mask
+                jsr L9377                       ; turn on pixel
+                lda VD7                         ; get pixel mask back
+                jsr ,u                          ; move one pixel right
+                leay -1,y                       ; turned on enough pixels yet?
+                bne L945E                       ; brif not
+L946B           rts
+L946C           puls b,a                        ; clean up stack
+L946E           ldd VERBEG                      ; save original vertical start coordinate
+                pshs b,a
+                jsr L9710                       ; get vertical difference
+                bcc L947B                       ; brif end coordinate > start
+                ldx VEREND                      ; swap in end coordinate if not
+                stx VERBEG
+L947B           tfr d,y                         ; save number of pixels to set
+                leay 1,y                        ; the coordinates are inclusive
+                jsr L9298                       ; get screen pointer
+                puls u                          ; restore start coordinate
+                stu VERBEG
+                bsr L949D                       ; point to routine to move down one row
+                bra L945E                       ; draw vertical line
+; Point to routine which will move one pixel right
+L948A           fdb L92ED                       ; PMODE 0
+                fdb L92F4                       ; PMODE 1
+                fdb L92ED                       ; PMODE 2
+                fdb L92F4                       ; PMODE 3
+                fdb L92ED                       ; PMODE 4
+L9494           ldu #L948A                      ; point to jump table
+                ldb PMODE                       ; get graphics mode
+                aslb                            ; two bytes per address
+                ldu b,u                         ; get jump address
+                rts
+; Point to routine to move down one row
+L949D           ldu #L92E9                      ; point to "move down one row" routien
+                rts
+; Draw a line from HORBEG,VERBEG to HOREND,VEREND
+L94A1           ldy #L950D                      ; point to increase vertical coord
+                jsr L9710                       ; calculate difference
+                lbeq L9444                      ; brif none - draw a horizontal line
+                bcc L94B2                       ; brif vertical end is > vertical start
+                ldy #L951B                      ; point to decrease vertical coord
+L94B2           pshs d                          ; save vertical difference
+                ldu #L9506                      ; point to increase horizontal coord
+                jsr L971D                       ; get difference
+                beq L946C                       ; brif none - draw a vertical line
+                bcc L94C1                       ; brif horizontal end > horizontal start
+                ldu #L9514                      ; point to decrease hoizontal coord
+L94C1           cmpd ,s                         ; compare vert and horiz differences
+                puls x                          ; get X difference
+                bcc L94CC                       ; brif horiz diff > vert diff
+                exg u,y                         ; swap change routine pointers
+                exg d,x                         ; swap differences
+L94CC           pshs u,d                        ; save larger difference and routine
+                pshs d                          ; save larger difference
+                lsra                            ; divide by two
+                rorb
+                bcs L94DD                       ; brif odd number
+                cmpu #L950D+1                   ; increase or decrease?
+                blo L94DD                       ; brif increase
+                subd #1                         ; back up one
+L94DD           pshs x,b,a                      ; save smallest difference and initial middle offset
+                jsr L928F                       ; point to proper coordinate to screen conversion routine
+L94E2           jsr ,u                          ; convert coordinates to screen address
+                jsr L9377                       ; turn on a pixel
+                ldx 6,s                         ; get distnace counter
+                beq L9502                       ; brif line is completely drawn
+                leax -1,x                       ; account for one pixel drawn
+                stx 6,s                         ; save new counter
+                jsr [8,s]                       ; increment/decrement larger delta
+                ldd ,s                          ; get the minor coordinate increment counter
+                addd 2,s                        ; add the smallest difference
+                std ,s                          ; save new minor coordinate incrementcounter
+                subd 4,s                        ; subtractout the largest difference
+                bcs L94E2                       ; brif not greater - draw another pixel
+                std ,s                          ; save new minor coordinate increment
+                jsr ,y                          ; adjust minor coordinate
+                bra L94E2                       ; go draw another pixel
+L9502           puls x                          ; clean up stack and return
+                puls a,b,x,y,u,pc
+L9506           ldx HORBEG                      ; bump horizontal coordinate
+                leax 1,x
+                stx HORBEG
+                rts
+L950D           ldx VERBEG                      ; bump vertical coordinate
+                leax 1,x
+                stx VERBEG
+                rts
+L9514           ldx HORBEG                      ; decrement horizontal coordinate
+                leax -1,x
+                stx HORBEG
+                rts
+L951B           ldx VERBEG                      ; decrement vertical coordinate
+                leax -1,x
+                stx VERBEG
+                rts
+; Get normalized maximum coordinate values in VD3 and VD5
+L9522           ldu #VD3                        ; point to temp storage
+                ldx #255                        ; set maximum horizontal
+                stx ,u
+                ldx #191                        ; set maximum vertical
+                stx 2,u
+                jmp L9320                       ; normalize them
+; PCLS command
+PCLS            beq L9542                       ; clear to background colour if no argument
+                bsr L955A                       ; evaluate colour
+L9536           lda #0x55                       ; consider each byte as 4 groups of 2 bit sub-nibbles
+                mul                             ; now colour is in all four sub-pixels
+                ldx BEGGRP                      ; get start of graphics screen
+L953B           stb ,x+                         ; set byte to proper colour
+                cmpx ENDGRP                     ; at end of graphics page?
+                bne L953B                       ; brif not
+                rts
+L9542           ldb BAKCOL                      ; get background colour
+                bra L9536                       ; do the clearing dance
+; COLOR command
+COLOR           cmpa #',                        ; check for comma
+                beq L9552                       ; brif no foreground colour
+                bsr L955A                       ; evaluate first colour
+                stb FORCOL                      ; set foreground colour
+                jsr GETCCH                      ; is there a background colour?
+                beq L9559                       ; brif not
+L9552           jsr SYNCOMMA                    ; make sure we have a comma
+                bsr L955A                       ; evaluate background colour argument
+                stb BAKCOL                      ; set background colour
+L9559           rts
+; Evaluate a colour agument and convert to proper code based on graphics mode
+L955A           jsr EVALEXPB                    ; evaluate colour code
+L955D           cmpb #9                         ; is it in range of 0-8?
+                lbhs LB44A                      ; brif not - raise error
+                clra                            ; CSS value for first colour set
+                cmpb #5                         ; is it first or second colour set?
+                blo L956C                       ; brif first colour set
+                lda #8                          ; flag second colour set
+                subb #4                         ; adjust into basic range
+L956C           pshs a                          ; save CSS value
+                lda PMODE                       ; get graphics mode
+                rora                            ; 4 colour or 2?
+                bcc L957B                       ; brif 2 colour
+                tstb                            ; was it 0?
+                bne L9578                       ; brif not
+L9576           ldb #4                          ; if so, make it 4
+L9578           decb                            ; convert to zero based
+L9579           puls a,pc                       ; get back CSS value and return
+L957B           rorb                            ; is colour number odd?
+                bcs L9576                       ; brif so - force all bits set colour
+                clrb                            ; force colour 0 if not
+                bra L9579
+; Set all pixel byte and active colour
+L9581           jsr L959A                       ; set colour byte
+                jsr GETCCH                      ; is there something to evaluate?
+                beq L9598                       ; brif not
+                cmpa #')                        ; )?
+                beq L9598                       ; brif so
+                jsr SYNCOMMA                    ; force comma
+                cmpa #',                        ; another comma?
+                beq L9598                       ; brif so
+                jsr L955A                       ; evaluate expression and return colour
+                bsr L95A2                       ; save colour and pixel byte
+L9598           jmp GETCCH                      ; re-fetch input character and return
+L959A           ldb FORCOL                      ; use foreground colour by default
+                tst SETFLG                      ; doing PRESET?
+                bne L95A2                       ; brif not
+                ldb BAKCOL                      ; default to background colour
+L95A2           stb WCOLOR                      ; save working colour
+                lda #0x55                       ; consider a byte as 4 pixels
+                mul                             ; now all pixels are set to the same bit pattern
+                stb ALLCOL                      ; set all pixels byte
+                rts
+L95AA           bne L95CF                       ; brif graphics mode
+L95AC           pshs x,b,a                      ; save registers
+                ldx #SAMREG+8                   ; point to middle of control register
+                sta 10,x                        ; reset display page to 0x400
+                sta 8,x
+                sta 6,x
+                sta 4,x
+                sta 2,x
+                sta 1,x
+                sta -2,x
+                sta -4,x                        ; reset to alpha mode
+                sta -6,x
+                sta -8,x
+                lda PIA1+2                      ; set VDG to alpha mode, colour set 0
+                anda #7
+                sta PIA1+2
+                puls a,b,x,pc                   ;restore registers and return
+L95CF           pshs x,b,a                      ; save registers
+                lda PMODE                       ; get graphics mode
+                adda #3                         ; offset to 3-7 (we don't use the bottom 3 modes)
+                ldb #0x10                       ; shift to high 4 bits
+                mul
+                orb #0x80                       ; set to graphics mode
+                orb CSSVAL                      ; set the desired colour set
+                lda PIA1+2                      ; get get original PIA values
+                anda #7                         ; mask off VDG control
+                pshs a                          ; merge with new VDG control
+                orb ,s+
+                stb PIA1+2                      ; set new VDG mode
+                lda BEGGRP                      ; get start of graphics page
+                lsra                            ; divide by two - pages are on 512 byte boundaries
+                jsr L960F                       ; set SAM control register
+                lda PMODE                       ; get graphics mode
+                adda #3                         ; shift to VDG values
+                cmpa #7                         ; PMODE 4?
+                bne L95F7                       ; brif not
+                deca                            ; treat PMODE 4 the same as PMODE 3
+L95F7           bsr L95FB                       ; program SAM's VDG bits
+                puls a,b,x,pc                   ; restore registers and return
+L95FB           ldb #3                          ; set 3 bits in register
+                ldx #SAMREG                     ; point to VDG control bits
+L9600           rora                            ; get bit to set
+                bcc L9607                       ; brif we need to clear the bit
+                sta 1,x                         ; set the bit
+                bra L9609
+L9607           sta ,x                          ; clear the bit
+L9609           leax 2,x                        ; move to next bit
+                decb                            ; done all bits?
+                bne L9600                       ; brif not
+                rts
+L960F           ldb #7                          ; 7 screen address bits
+                ldx #SAMREG+6                   ; point to screen address bits in SAM
+                bra L9600                       ; go program SAM bits
+L9616           lda PIA1+2                      ; get VDG bits
+                anda #0xf7                      ; keep everything but CSS bit
+                ora CSSVAL                      ; set correct CSS bit
+                sta PIA1+2                      ; set desired CSS
+                rts
+; PMODE command
+PMODETOK        cmpa #',                        ; is first argument missing?
+                beq L9650                       ; brif so
+                jsr EVALEXPB                    ; evaluate PMODE number
+                cmpb #5                         ; valid (0-4)?
+                bhs L966D                       ; brif not
+                lda GRPRAM                      ; get start of graphics memory
+L962E           sta BEGGRP                      ; set start of graphics page
+                aslb                            ; multiply mode by two (table has two bytes per entry)
+                ldu #L9706+1                    ; point to lookup table
+                adda b,u                        ; add in number of 256 byte pages used for graphics screen
+                cmpa TXTTAB                     ; does it fit?
+                bhi L966D                       ; brif not
+                sta ENDGRP                      ; save end of graphics
+                leau -1,u                       ; point to bytes per horizontal row
+                lda b,u                         ; get bytes per row
+                sta HORBYT                      ; set it
+                lsrb                            ; restore PMODE value
+                stb PMODE                       ; set graphics mode
+                clra                            ; set background colour to 0
+                sta BAKCOL
+                lda #3                          ; set foreground colour to maximum (3)
+                sta FORCOL
+                jsr GETCCH                      ; is there a starting page number?
+                beq L966C                       ; brif not
+L9650           jsr LB738                       ; evaluate an expression following a comma
+                tstb                            ; page 0?
+                beq L966D                       ; brif so - not valid
+                decb                            ; zero-base it
+                lda #6                          ; each graphics page is 6*256
+                mul
+                addb GRPRAM                     ; add to start of graphics memory
+                pshs b                          ; save start of screen memory
+                addb ENDGRP                     ; add current and address
+                subb BEGGRP                     ; subtract current start (adds size of screen)
+                cmpb TXTTAB                     ; does it fit?
+                bhi L966D                       ; brif not
+                stb ENDGRP                      ; save new end of graphics
+                puls b                          ; get back start of graphics
+                stb BEGGRP                      ; set start of graphics
+L966C           rts
+L966D           jmp LB44A                       ; raise FC error
+; SCREEN command
+SCREEN          cmpa #',                        ; is there a mode?
+                beq L967F                       ; brif no mode
+                jsr EVALEXPB                    ; get mode argument
+                tstb                            ; set Z if alpha
+                jsr L95AA                       ; set SAM/VDG for graphics mode
+                jsr GETCCH                      ; is there a second argument?
+                beq L966C                       ; brif not
+L967F           jsr LB738                       ; evaluate ,<expr>
+                tstb                            ; colour set 0?
+                beq L9687                       ; brif so
+                ldb #8                          ; flag for colour set 1
+L9687           stb CSSVAL                      ; set colour set
+                bra L9616                       ; set up VDG
+; PCLEAR command
+PCLEAR          jsr EVALEXPB                    ; evaulate number of pages requested
+                tstb                            ; 0?
+                beq L966D                       ; brif zero - not allowed
+                cmpb #9                         ; more than 8?
+                bhs L966D                       ; brif so - not allowed
+                lda #6                          ; there are 6 "pages" per graphics page
+                mul                             ; now B is the number of pages to reserve
+                addb GRPRAM                     ; add to start of graphics memory
+                tfr b,a                         ; now A is the MSB of the start of free memory
+                ldb #1                          ; program memory always starts one above
+                tfr d,y                         ; save pointer to program memory
+                cmpd ENDGRP                     ; are we trying to deallocate the current graphics page?
+                blo L966D                       ; brif so (note that this prevents PCLEAR 0 anyway)
+                subd TXTTAB                     ; subtract out current start of basic program
+                addd VARTAB                     ; add in end of program - now D is new top of program
+                tfr d,x                         ; save new end of program
+                inca                            ; make some extra space (for stack)
+                subd FRETOP                     ; see if new top of program fits
+                bhs L966D                       ; brif there isn't enough space
+                jsr L80D0                       ; adjust input pointer
+                nop                             ; space filler for 1.1 patch (the JSR above)
+                ldu VARTAB                      ; get end of program
+                stx VARTAB                      ; save new end of program
+                cmpu VARTAB                     ; is old end higher?
+                bhs L96D4                       ; brif so
+L96BD           lda ,-u                         ; copy a byte upward
+                sta ,-x
+                cmpu TXTTAB                     ; at beginning?
+                bne L96BD                       ; brif not
+                sty TXTTAB                      ; save new start of program
+                clr -1,y                        ; there must always be a NUL before the program
+L96CB           jsr LACEF                       ; re-assign basic program addresses
+                jsr LAD26                       ; reset variables and stack
+                jmp LAD9E                       ; return to interpretation loop
+L96D4           ldu TXTTAB                      ; get start of program
+                sty TXTTAB                      ; save new start of program
+                clr -1,y                        ; there must be a NUL at the start of the program
+L96DB           lda ,u+                         ; move a byte downward
+                sta ,y+
+                cmpy VARTAB                     ; at the top of the program?
+                bne L96DB                       ; brif not
+                bra L96CB                       ; finish up
+; Graphics initialization routine - this really should be up at the start of the ROM with the
+; rest of the initialization code.
+L96E6           ldb #0x1e                       ; set start of program to 0x1e00 ("PCLEAR 4")
+                stb TXTTAB
+                lda #6                          ; graphics memory starts immediately after the screen
+L96EC           sta GRPRAM                      ; set graphics memory start
+                sta BEGGRP                      ; set start of current graphics page
+                clra                            ; set PMODE to 0
+                sta PMODE
+                lda #16                         ; 16 bytes per graphics row
+                sta HORBYT
+                lda #3                          ; set foreground colour to 3
+                sta FORCOL
+                lda #0x0c                       ; set ending graphics page (for PMODE 0)
+                sta ENDGRP
+                ldx TXTTAB                      ; get start of program
+                clr -1,x                        ; make sure there's a NUL before it
+L9703           jmp LAD19                       ; do a "NEW"
+; PMODE data table (bytes per row and number of 256 byte pages required for a screen)
+L9706           fcb 16,6                        ; PMODE 0
+                fcb 32,12                       ; PMODE 1
+                fcb 16,12                       ; PMODE 2
+                fcb 32,24                       ; PMODE 3
+                fcb 32,24                       ; PMODE 4
+; Calculate absolute value of vertical coordinate difference
+L9710           ldd VEREND                      ; get ending address
+                subd VERBEG                     ; get difference
+L9714           bcc L9751                       ; brif we didn't carry
+                pshs cc                         ; save status (C set if start > end)
+                jsr L9DC3                       ; negate the difference to be positive
+                puls cc,pc                      ; restore C and return
+; Calculate absolute value of horizontal coordinate difference
+L971D           ldd HOREND                      ; get end coordinate
+                subd HORBEG                     ; calculate difference
+                bra L9714                       ; turn into absolute value
+; PCOPY command
+PCOPY           bsr L973F                       ; fetch address of the source page
+                pshs d                          ; save address
+                ldb #0xa5                       ; make sure we have TO
+                jsr LB26F
+                bsr L973F                       ; fetch address of the second page
+                puls x                          ; get back source
+                tfr d,u                         ; put destination into a pointer
+                ldy #0x300                      ; 0x300 words to copy
+L9736           ldd ,x++                        ; copy a word
+                std ,u++
+                leay -1,y                       ; done?
+                bne L9736                       ; brif not
+                rts
+L973F           jsr EVALEXPB                    ; evaluate page number
+                tstb                            ; zero?
+                beq L9752                       ; brif invalid page number
+; BUG: this should be deferred until after the address is calculated at which point it should
+; be bhs instead of bhi. There should also be a check to make sure the page number is less than
+; or equal to 8 above so we don't have to test for overflows below.
+                cmpb TXTTAB                     ; is page number higher than start of program (BUG!)
+                bhi L9752                       ; brif so - error
+                decb                            ; zero-base the page number
+                lda #6                          ; 6 "pages" per graphics page
+                mul                             ; now we have proper number of "pages" for the offset
+                addb GRPRAM                     ; add start of graphics memory
+                exg a,b                         ; put MSB into A, 0 into B.
+L9751           rts
+L9752           jmp LB44A                       ; raise illegal function call
+; GET command
+GET             clrb                            ; GET flag
+                bra L975A                       ; go on to the main body
+PUT             ldb #1                          ; PUT flag
+L975A           stb VD8                         ; save GET/PUT flag
+                jsr RVEC22                      ; do the RAM hook dance (so Disk Basic can do its thing)
+L975F           cmpa #'@                        ; @ before coordinates?
+                bne L9765                       ; brif not
+                jsr GETNCH                      ; eat the @
+L9765           jsr L938F                       ; evaluate start/end coordinates
+                jsr SYNCOMMA                    ; make sure we have a comma
+                jsr L98CC                       ; get pointer to array
+                tfr X,D                         ; save descriptor pointer
+                ldu ,x                          ; get offset to next descriptor
+                leau -2,u                       ; move back to array name
+                leau d,u                        ; point to end of array
+                stu VD1                         ; save end of data
+                leax 2,x                        ; point to number of dimensions
+                ldb ,x                          ; get dimension count
+                aslb                            ; two bytes per dimension size
+                abx                             ; now X points to start of data
+                stx VCF                         ; save start of array data
+                lda VALTYP                      ; is it numeric
+                bne L9752                       ; brif not
+                clr VD4                         ; set default graphic action to PSET
+                jsr GETCCH                      ; get input character
+                beq L97B7                       ; brif no action flag
+                com VD4                         ; flag action enabled
+                jsr SYNCOMMA                    ; make sure there's a comma
+                tst VD8                         ; PUT?
+                bne L979A                       ; brif so
+                ldb #'G                         ; check for full graphics option
+                jsr LB26F
+                bra L97CA                       ; handle the rest of the process
+L979A           ldb #5                          ; 5 legal actions for PUT
+                ldx #L9839                      ; point to action table
+L979F           ldu ,x++                        ; get "clear bit" action routine
+                ldy ,x++                        ; get "set bit" action routine
+                cmpa ,x+                        ; does token match?
+                beq L97AE                       ; brif so
+                decb                            ; checked all?
+                bne L979F                       ; brif not
+                jmp LB277                       ; raise error
+L97AE           sty VD5                         ; save set bit action address
+                stu VD9                         ; save clear bit action address
+                jsr GETNCH                      ; munch the acton token
+                bra L97CA                       ; handle rest of process
+L97B7           ldb #0xf8                       ; mask for bottom three bits
+                lda PMODE                       ; get graphics mode
+                rora                            ; odd number mode?
+                bcc L97C0                       ; brif even
+                ldb #0xfc                       ; bottom 2 bits mask
+L97C0           tfr b,a                         ; save mask
+                andb HORBEG+1                   ; round down the start address
+                stb HORBEG+1
+                anda HOREND+1                   ; round down end address
+                sta HOREND+1
+L97CA           jsr L971D                       ; get horizontal size
+                bcc L97D3                       ; brif end > start
+                ldx HOREND                      ; switch end in for start
+                stx HORBEG
+L97D3           std HOREND                      ; save size
+                jsr L9710                       ; calculate vertical size
+                bcc L97DE                       ; brif end > start
+                ldx VEREND                      ; swap in vertical end for the start
+                stx VERBEG
+L97DE           std VEREND                      ; save vertical size
+                lda PMODE                       ; get graphics mode
+                rora                            ; even?
+                ldd HOREND                      ; get difference
+                bcc L97EB                       ; brif even (2 colour)
+                addd HOREND                     ; add in size (double it)
+                std HOREND                      ; save adjusted end size
+L97EB           jsr L9420                       ; normalize differences
+                ldd HOREND                      ; get end coord
+                ldx VEREND                      ; get end size
+                leax 1,x                        ; make vertical size inclusive
+                stx VEREND                      ; save it back
+                tst VD4                         ; got "G" or GET action
+                bne L9852                       ; brif given
+                lsra                            ; we're going for whole bytes here
+                rorb
+                lsra
+                rorb
+                lsra
+                rorb
+                addd #1                         ; make it inclusive
+                std HOREND                      ; save new coordinate
+                jsr L9298                       ; convert to screen address
+L9808           ldb HOREND+1                    ; get horizontal size
+                pshs x                          ; save screen position
+L980C           tst VD8                         ; get/put flag
+                beq L9831                       ; brif get
+                bsr L9823                       ; bump array data pointer
+                lda ,u                          ; copy data from array to screen
+                sta ,x+
+L9816           decb                            ; are we done the row?
+                bne L980C                       ; brif not
+                puls x                          ; get screen address
+                jsr L92E9                       ; move to next row
+                dec VEREND+1                    ; done?
+                bne L9808                       ; brif not
+L9822           rts
+L9823           ldu VCF                         ; get array data location
+                leau 1,u                        ; bump it
+                stu VCF                         ; save new array data location
+                cmpu VD1                        ; did we hit the end of the array?
+                bne L9822                       ; brif not
+L982E           jmp LB44A                       ; raise function call error
+L9831           lda ,x+                         ; get data from screen
+                bsr L9823                       ; bump array data pointer
+                sta ,u                          ; put data in array
+                bra L9816                       ; do the loopy thing
+; PUT actions
+L9839           fdb L9894,L989B                 ; PSET
+                fcb 0xbd
+                fdb L989B,L9894                 ; PRESET
+                fcb 0xbe
+                fdb L98B1,L989B                 ; OR
+                fcb 0xb1
+                fdb L9894,L98B1                 ; AND
+                fcb 0xb0
+                fdb L98A1,L98A1                 ; NOT
+                fcb 0xa8
+L9852           addd #1                         ; add to horiz difference
+                std HOREND                      ; save it
+                lda VD8                         ; PUT?
+                bne L9864                       ; brif so
+                ldu VD1                         ; get end of array
+L985D           sta ,-u                         ; zero out a byte
+                cmpu VCF                        ; done?
+                bhi L985D                       ; brif not
+L9864           jsr L9298                       ; get screen address
+                ldb PMODE                       ; get graphics mode
+                rorb                            ; even?
+                bcc L986E                       ; brif so
+                anda #0xaa                      ; use as pixel mask for 4 colour mode
+L986E           ldb #1                          ; set bit probe
+                ldy VCF                         ; point to start of array data
+L9873           pshs x,a                        ; save screen address
+                ldu HOREND                      ; get horizontal size
+L9877           pshs u,a                        ; save horizontal size and pixel mask
+                lsrb                            ; move bit probe right
+                bcc L9884                       ; brif we didn't fall off a byte
+                rorb                            ; shift carry back in on the left
+                leay 1,y                        ; move ahead a byte in the array
+                cmpy VD1                        ; end of array data?
+                beq L982E                       ; raise error if so
+L9884           tst VD8                         ; PUT?
+                beq L98A7                       ; brif not
+                bitb ,y                         ; test bit in array
+                beq L9890                       ; brif not set
+                jmp [VD5]                       ; do action routine for bit set
+L9890           jmp [VD9]                       ; do action routine for bit clear
+L9894           coma                            ; invert mask
+                anda ,x                         ; read screen data and reset the desired bit
+                sta ,x                          ; save on screen
+                bra L98B1
+L989B           ora ,x                          ; merge pixel mask with screen data (turn on bit)
+                sta ,x                          ; save on screen
+                bra L98B1
+L98A1           eora ,x                         ; invert the pixel in the screen data
+                sta ,x                          ; save on screen
+                bra L98B1
+L98A7           bita ,x                         ; is the bit set?
+                beq L98B1                       ; brif not - do nothing
+                tfr b,a                         ; get bit probe
+                ora ,y                          ; turn on proper bit in data
+                sta ,y
+L98B1           puls a,u                        ; get back array address
+                jsr L92ED                       ; move screen address to the right
+                leau -1,u                       ; account for consumed pixel
+                cmpu ZERO                       ; done yet?
+                bne L9877                       ; brif not
+                ldx 1,s                         ; get start of row back
+                lda HORBYT                      ; get number of bytes per row
+                leax a,x                        ; move ahead one line
+                puls a                          ; get back screen pixel mask
+                leas 2,s                        ; lose the screen pointer
+                dec VEREND+1                    ; done all rows?
+                bne L9873                       ; brif not
+                rts
+L98CC           jsr LB357                       ; evaluate a variable
+                ldb ,-x                         ; get variable name
+                lda ,-x
+                tfr d,u                         ; save it
+                ldx ARYTAB                      ; get start of arrays
+L98D7           cmpx ARYEND                     ; end of arrays?
+                lbeq LB44A                      ; brif not found
+                cmpu ,x                         ; correct variable?
+                beq L98E8                       ; brif so
+                ldd 2,x                         ; get array size
+                leax d,x                        ; move to next array
+                bra L98D7                       ; check this array
+L98E8           leax 2,x                        ; move pointer to the array header
+                rts                             ; obviously this rts is not needed
+L98EB           rts
+; PAINT command
+PAINT           cmpa #'@                        ; do we have @ before coords?
+                bne L98F2                       ; brif not
+                jsr GETNCH                      ; eat the @
+L98F2           jsr L93B2                       ; evaluate coordinates
+                jsr L931D                       ; normalize coordinates
+                lda #1                          ; PSET flag (use working colour)
+                sta SETFLG
+                jsr L9581                       ; parse colour and set working colour, etc.
+                ldd WCOLOR                      ; get working colour and all pixels byte
+                pshs d                          ; save them
+                jsr GETCCH                      ; is there anything else?
+                beq L990A                       ; brif not
+                jsr L9581                       ; evaluate border colour
+L990A           lda ALLCOL                      ; get border colour all pixel byte
+                sta VD8                         ; save border colour pixel byte
+                puls d                          ; get back working colour details
+                std WCOLOR
+                clra                            ; store a "stop" frame on the stack so PAINT knows when it's finished unwinding
+                pshs u,x,b,a
+                jsr L9522                       ; set up starting coordinates
+                jsr L928F                       ; point to pixel mask routine
+                stu VD9                         ; save pixel mask routine
+                jsr L99DF                       ; paint from current horizontal coordinate to zero (left)
+                beq L9931                       ; brif hit border immediately
+                jsr L99CB                       ; paint from current horizontal coordinate upward (right)
+                lda #1                          ; set direction to "down"
+                sta VD7
+                jsr L99BA                       ; save "down" frame
+                neg VD7                         ; set direction to "up"
+                jsr L99BA                       ; save "up" frame
+L9931           sts TMPSTK                      ; save stack pointer
+L9934           tst CHGFLG                      ; did the paint change anything?
+                bne L993B                       ; brif so
+                lds TMPSTK                      ; get back stack pointer
+L993B           puls a,b,x,u                    ; get frame from stack
+                clr CHGFLG                      ; mark nothing changed
+                sts TMPSTK                      ; save stack pointer
+                leax 1,x                        ; move start coordinate right
+                stx HORBEG                      ; save new coordinate
+                stu VD1                         ; save length of line
+                sta VD7                         ; save up/down flag
+                beq L98EB                       ; did we hit the "stop" frame?
+                bmi L9954                       ; brif negative going (up)?
+                incb                            ; bump vertical coordinate
+                cmpb VD6                        ; at end?
+                bls L9958                       ; brif not
+                clrb                            ; set vertical to 0 (wrap around)
+L9954           tstb                            ; did we wrap?
+                beq L9934                       ; do another block if so
+                decb                            ; move up a row
+L9958           stb VERBEG+1                    ; save vertical coordinate
+                jsr L99DF                       ; paint from horizontal to 0
+                beq L996E                       ; brif we hit the border immediately
+                cmpd #3                         ; less than 3 pixels?
+                blo L9969                       ; brif so
+                leax -2,x                       ; move two pixels left
+                bsr L99A1                       ; save paint block on the stack
+L9969           jsr L99CB                       ; continue painting to the right
+L996C           bsr L99BA                       ; save paint data frame
+L996E           coma                            ; complement length of line just painted and add to length of line
+                comb
+L9970           addd VD1                        ; save difference between this line and parent line
+                std VD1
+                ble L998C                       ; brif parent line is shorter
+                jsr L9506                       ; bump horizontal coordinate
+                jsr L9A12                       ; see if we bounced into the border
+                bne L9983                       ; brif not border
+                ldd #-1                         ; move left
+                bra L9970                       ; keep looking
+L9983           jsr L9514                       ; move horizontally left
+                bsr L99C6                       ; save horizontal coordinate
+                bsr L99E8                       ; paint right
+                bra L996C                       ; save paint block and do more
+L998C           jsr L9506                       ; bump horizontal coordinate
+                leax d,x                        ; point to right end of parent line
+                stx HORBEG                      ; set as curent coordinate
+                coma                            ; get amount we extend past parent line
+                comb
+                subd #1
+                ble L999E                       ; brif doesn't extend
+                tfr d,x                         ; save length of line
+                bsr L99A1                       ; save paint frame
+L999E           jmp L9934
+L99A1           std VCB                         ; save number of pixels painted
+                puls y                          ; get return address
+                ldd HORBEG                      ; get horizontal coordinate
+                pshs x,b,a                      ; save horizontal coordinate and pointer
+                lda VD7                         ; get up/down flag
+                nega                            ; reverse it
+L99AC           ldb VERBEG+1                    ; get vertical coordainte
+                pshs b,a                        ; save vertical coord and up/down flag
+                pshs y                          ; put return address back
+                ldb #2                          ; make sure we haven't overflowed memory
+                jsr LAC33
+                ldd VCB                         ; get line length back
+                rts
+L99BA           std VCB                         ; save length of painted line
+                puls y                          ; get return address
+                ldd HOREND                      ; get start coord
+                pshs x,b,a                      ; save horizontal start and length
+                lda VD7                         ; get up/down flag
+                bra L99AC                       ; finish up with the stack
+L99C6           ldx HORBEG                      ; save current horizontal coord and save it
+                stx HOREND
+                rts
+L99CB           std VCD                         ; save number of pixels painted
+                ldy HOREND                      ; get last horizontal start
+                bsr L99C6                       ; save current coordinate
+                sty HORBEG                      ; save coordinate
+                bsr L99E8                       ; paint a line
+                ldx VCD                         ; get number painted
+                leax d,x                        ; add to the number painted going the other way
+                addd #1                         ; now D is length of line
+                rts
+L99DF           jsr L99C6                       ; put starting coordinate in end
+                ldy #L9514                      ; decrement horizontal coordinate address
+                bra L99EE                       ; go paint line
+L99E8           ldy #L9506                      ; increment horizontal coordinate address
+                jsr ,y                          ; bump coordinate
+L99EE           ldu ZERO                        ; initialize pixel count
+                ldx HORBEG                      ; get starting coordinate
+L99F2           bmi L9A0B                       ; brif out of range for hoizontal coordinate
+                cmpx VD3                        ; at end?
+                bhi L9A0B                       ; brif right of max
+                pshs u,y                        ; save counter and inc/dec routine pointer
+                bsr L9A12                       ; at border?
+                beq L9A09                       ; brif so
+                jsr L9377                       ; set pixel to paint colour
+                puls y,u                        ; restore counter and inc/dec/pointer
+                leau 1,u                        ; bump number of painted pixels
+                jsr ,y                          ; inc/dec screen address
+                bra L99F2                       ; go do another pixel
+L9A09           puls y,u                        ; get back counter and inc/dec routine
+L9A0B           tfr u,d                         ; save count in D
+                tfr d,x                         ; and in X
+                subd ZERO                       ; set flags on D (smaller/faster than cmpd ZERO)
+                rts
+L9A12           jsr [VD9]                       ; get the screen address
+                tfr a,b                         ; save pixel mask
+                andb VD8                        ; set pixel to border colour
+                pshs b,a                        ; save mask and border
+                anda ,x                         ; mask current pixel into A
+                cmpa 1,s                        ; does it match border? Z=1 if so
+                puls a,b,pc                     ; restore mask, border pixel, and return
+; PLAY command
+; This is here mixed in with the graphics package because it shares some machinery with DRAW.
+PLAY            ldx ZERO                        ; default values for note length, etc.
+                ldb #1
+                pshs x,b                        ; save default values
+                jsr LB156                       ; evaluate argument
+                clrb                            ; enable DA and sound output
+                jsr LA9A2
+                jsr LA976
+L9A32           jsr LB654                       ; fetch PLAY string details
+                bra L9A39                       ; go evaluate the string
+L9A37           puls b,x                        ; get back play string details
+L9A39           stb VD8                         ; save length of string
+                beq L9A37                       ; brif end of string
+                stx VD9                         ; save start of string
+                lbeq LA974                      ; brif NULL string - disable sound and return
+L9A43           tst VD8                         ; have anything left?
+                beq L9A37                       ; brif not
+                jsr L9B98                       ; get command character
+                cmpa #';                        ; command separator?
+                beq L9A43                       ; brif so - ignore it
+                cmpa #''                        ; '?
+                beq L9A43                       ; brif so - ignore it
+                cmpa #'X                        ; execuate sub string?
+                lbeq L9C0A                      ; brif so - handle it
+                bsr L9A5C                       ; handle other commands
+                bra L9A43                       ; look for more stuff
+L9A5C           cmpa #'O                        ; octave?
+                bne L9A6D                       ; brif not
+                ldb OCTAVE                      ; get current octave
+                incb                            ; 1-base it
+                bsr L9AC0                       ; get value if present
+                decb                            ; zero-base it
+                cmpb #4                         ; valid octave?
+                bhi L9ACD                       ; raise error if not
+                stb OCTAVE                      ; save new octave
+                rts
+L9A6D           cmpa #'V                        ; volume?
+                bne L9A8B                       ; brif not
+                ldb VOLHI                       ; get current high volume limit
+                lsrb                            ; shift 2 bits right (DA is 6 bits in high bits)
+                lsrb
+                subb #31                        ; subtract out mid value offset
+                bsr L9AC0                       ; read argument
+                cmpb #31                        ; maximum range is 31
+                bhi L9ACD                       ; brif out of range
+                aslb                            ; adjust back in range
+                aslb
+                pshs b                          ; save new volume
+                ldd #0x7e7e                     ; midrange value for both high and low
+                adda ,s                         ; add new volume to high limit
+                subb ,s+                        ; subtract volume from low limit
+                std VOLHI                       ; save new volume limits (sets high and low amplitudes)
+                rts
+L9A8B           cmpa #'L                        ; note length?
+                bne L9AB2                       ; brif not
+                ldb NOTELN                      ; get current length
+                bsr L9AC0                       ; read parameter
+                tstb                            ; resulting length 0?
+                beq L9ACD                       ; brif so - problem
+                stb NOTELN                      ; save new length
+                clr DOTVAL                      ; reset note timer scale factor
+L9A9A           bsr L9A9F                       ; check for dot
+                bcc L9A9A                       ; brif there was one
+                rts
+L9A9F           tst VD8                         ; check length
+                beq L9AAD                       ; brif zero
+                jsr L9B98                       ; get command character
+                cmpa #'.                        ; dot?
+                beq L9AAF                       ; brif so
+                jsr L9BE2                       ; move input back and bump length
+L9AAD           coma                            ; set C to indicate nothing found
+                rts
+L9AAF           inc DOTVAL                      ; bump number of dots
+                rts
+L9AB2           cmpa #'T                        ; tempo?
+                bne L9AC3                       ; brif not
+                ldb TEMPO                       ; get current tempo
+                bsr L9AC0                       ; parse tempo argument
+                tstb                            ; 0?
+                beq L9ACD                       ; brif so - invalid
+                stb TEMPO                       ; save new tempo
+                rts
+L9AC0           jmp L9BAC                       ; evaluate various operators
+L9AC3           cmpa #'P                        ; pause?
+                bne L9AEB                       ; brif not
+                jsr L9CCB                       ; evaluate parameter
+                tstb                            ; is the pause number 0?
+                bne L9AD0                       ; brif not
+L9ACD           jmp LB44A                       ; raise FC error
+L9AD0           lda DOTVAL                      ; save current volume and note scale
+                ldx VOLHI
+                pshs x,a
+                lda #0x7e                       ; drop DA to mid range
+                sta VOLHI
+                sta VOLLOW
+                clr DOTVAL
+                bsr L9AE7                       ; go play a "silence"
+                puls a,x                        ; restore volume and note scale
+                sta DOTVAL
+                stx VOLHI
+                rts
+L9AE7           clr ,-s                         ; set not number 0
+                bra L9B2B                       ; go play it
+L9AEB           cmpa #'N                        ; N for "note"?
+                bne L9AF2                       ; brif not - it's optional
+                jsr L9B98                       ; skip the "N"
+L9AF2           cmpa #'A                        ; is it a valid note?
+                blo L9AFA                       ; brif not
+                cmpa #'G                        ; is it above the note range?
+                bls L9AFF                       ; brif not - valid note
+L9AFA           jsr L9BBE                       ; evaluate a number
+                bra L9B22                       ; process note value
+L9AFF           suba #'A                        ; normalize note number to 0
+                ldx #L9C5B                      ; point to note number lookup table
+                ldb a,x                         ; get not number
+                tst VD8                         ; any command characters left?
+                beq L9B22                       ; brif not
+                jsr L9B98                       ; get character
+                cmpa #'#                        ; sharp?
+                beq L9B15                       ; brif so
+                cmpa #'+                        ; also sharp?
+                bne L9B18                       ; brif not
+L9B15           incb                            ; add one half tone
+                bra L9B22
+L9B18           cmpa #'-                        ; flat?
+                bne L9B1F                       ; brif not
+                decb                            ; subtract one half tone
+                bra L9B22
+L9B1F           jsr L9BE2                       ; back up command pointer
+L9B22           decb                            ; adjust note number (zero base it)
+                cmpb #11                        ; is it valid?
+                bhi L9ACD                       ; raise error if not
+                pshs b                          ; save note value
+                ldb NOTELN                      ; get note length
+L9B2B           lda TEMPO                       ; get tempo value
+                mul                             ; calculate note duration
+                std VD5                         ; save duration
+                leau 1,s                        ; point to where the stack goes after we're done
+                lda OCTAVE                      ; get current octave
+                cmpa #1                         ; 0 or 1?
+                bhi L9B64                       ; brif not
+                ldx #L9C62                      ; point to delay table
+                ldb #2*12                       ; 24 bytes per octave
+                mul                             ; now we have the base address
+                abx                             ; now X points to the octave base
+                puls b                          ; get back note value
+                aslb                            ; two bytes per delay
+                abx                             ; now we're pointing to the delay
+                leay ,x                         ; save pointer to note value
+                bsr L9B8C                       ; calculate note timer value
+                std PLYTMR                      ; set timer for note playing (IRQ will count this down)
+L9B49           bsr L9B57                       ; set to mid range and delay
+                lda VOLHI                       ; get high value
+                bsr L9B5A                       ; set to high value and delay
+                bsr L9B57                       ; set to mid range and delay
+                lda VOLLOW                      ; get low value
+                bsr L9B5A                       ; set to low value and delay
+                bra L9B49                       ; do it again (IRQ will break the loop)
+L9B57           lda #0x7e                       ; mid value for DA with RS232 marking
+                nop                             ; a delay to fine tune frequencies
+L9B5A           sta PIA1                        ; set DA
+                ldx ,y                          ; get delay value
+L9B5F           leax -1,x                       ; count down
+                bne L9B5F                       ; brif not done yet
+                rts
+L9B64           ldx #L9C92-2*12                 ; point to delay table for octaves 2+
+                ldb #12                         ; 12 bytes per octave
+                mul                             ; now we have the offset to the desired octave
+                abx                             ; now we point to the start of the octave
+                puls b                          ; get back note value
+                abx                             ; now we point to the delay value
+                bsr L9B8C                       ; calculate timer value
+                std PLYTMR                      ; set play timer (IRQ counts this down)
+L9B72           bsr L9B80                       ; send mid value and delay
+                lda VOLHI                       ; get high value
+                bsr L9B83                       ; send high value and delay
+                bsr L9B80                       ; send low value and delay
+                lda VOLLOW                      ; get low value
+                bsr L9B83                       ; send low value and delay
+                bra L9B72                       ; do it again (IRQ will break the loop)
+L9B80           lda #0x7e                       ; mid range value with RS232 marking
+                nop                             ; fine tuning delay
+L9B83           sta PIA1                        ; set DA
+                lda ,x                          ; get delay value
+L9B88           deca                            ; count down
+                bne L9B88                       ; brif not done
+                rts
+L9B8C           ldb #0xff                       ; base timer value
+                lda DOTVAL                      ; get number of dots
+                beq L9B97                       ; use default value if 0
+                adda #2                         ; add in constant timer factor
+                mul                             ; multiply scale by base
+                lsra                            ; divide by two - each increment will increase note timer by 128
+                rorb
+L9B97           rts
+L9B98           pshs x                          ; save register
+L9B9A           tst VD8                         ; do we have anything left?
+                beq L9BEB                       ; brif not - raise error
+                ldx VD9                         ; get parsing address
+                lda ,x+                         ; get character
+                stx VD9                         ; save pointer
+                dec VD8                         ; account for character consumed
+                cmpa #0x20                      ; space?
+                beq L9B9A                       ; brif so - skip it
+                puls x,pc                       ; restore register and return
+L9BAC           bsr L9B98                       ; get character
+                cmpa #'+                        ; add one?
+                beq L9BEE                       ; brif so
+                cmpa #'-                        ; subtract one?
+                beq L9BF2                       ; brif so
+                cmpa #'>                        ; double?
+                beq L9BFC                       ; brif so
+                cmpa #'<                        ; halve?
+                beq L9BF7                       ; brif so
+L9BBE           cmpa #'=                        ; variable equate?
+                beq L9C01                       ; brif so
+                jsr L90AA                       ; clear carry if numeric
+                bcs L9BEB                       ; brif not numeric
+                clrb                            ; initialize value to 0
+L9BC8           suba #'0                        ; remove ASCII bias
+                sta VD7                         ; save digit
+                lda #10                         ; make room for digit
+                mul
+                tsta                            ; did we overflow 8 bits?
+                bne L9BEB                       ; brif so
+                addb VD7                        ; add in digit
+                bcs L9BEB                       ; brif that overflowed
+                tst VD8                         ; more digits?
+                beq L9BF1                       ; brif not
+                jsr L9B98                       ; get character
+                jsr L90AA                       ; clear carry if numeric
+                bcc L9BC8                       ; brif another digit
+L9BE2           inc VD8                         ; unaccount for character just read
+                ldx VD9                         ; move pointer back
+                leax -1,x
+                stx VD9
+                rts
+L9BEB           jmp LB44A                       ; raise FC error
+L9BEE           incb                            ; bump param
+                beq L9BEB                       ; brif overflow
+L9BF1           rts
+L9BF2           tstb                            ; already zero?
+                beq L9BEB                       ; brif so - underflow
+                decb                            ; decrease parameter
+                rts
+L9BF7           tstb                            ; already at 0?
+                beq L9BEB                       ; brif so - raise error
+                lsrb                            ; halve it
+                rts
+L9BFC           tstb                            ; will it overflow?
+                bmi L9BEB                       ; brif so
+                aslb                            ; double it
+                rts
+L9C01           pshs u,y                        ; save registers
+                bsr L9C1B                       ; interpret command string as a variable
+                jsr LB70E                       ; convert it to an 8 bit number
+                puls y,u,pc                     ; restore registers and return
+L9C0A           jsr L9C1B                       ; evaluate expression in command string
+                ldb #2                          ; room for 4 bytes?
+                jsr LAC33
+                ldb VD8                         ; get the command length and pointer
+                ldx VD9
+                pshs x,b                        ; save them
+                jmp L9A32                       ; go process the sub string
+L9C1B           ldx VD9                         ; get command pointer
+                pshs x                          ; save it
+                jsr L9B98                       ; get input character
+                jsr LB3A2                       ; set carry if not alpha
+                bcs L9BEB                       ; brif not a variable reference
+L9C27           jsr L9B98                       ; get command character
+                cmpa #';                        ; semicolon?
+                bne L9C27                       ; keep scanning if not
+                puls x                          ; get back start of variable string
+                ldu CHARAD                      ; get current interpreter input pointer
+                pshs u                          ; save it
+                stx CHARAD                      ; point interpreter at command string
+                jsr LB284                       ; evaluate expression as string
+                puls x                          ; restore interpeter input pointer
+                stx CHARAD
+                rts
+; The bit of Extended Basic's IRQ routine that handles PLAY. Note that everything after
+; clr PLYTMR+1 could be replaced with a simple lds 8,s followed by rts.
+L9C3E           clra                            ; make sure DP is set to 0
+                tfr a,dp
+                ldd PLYTMR                      ; is PLAY running?
+                lbeq LA9BB                      ; brif not - transfer control on the Color Basic's routine
+                subd VD5                        ; subtract out the interval
+                std PLYTMR                      ; save new timer value
+                bhi L9C5A                       ; brif it isn't <= 0
+                clr PLYTMR                      ; disable the timer
+                clr PLYTMR+1
+                puls a                          ; get saved CC
+                lds 7,s                         ; set stack to saved U value
+                anda #0x7f                      ; clear E flag (to return minimal state)
+                pshs a                          ; set fake "FIRQ" stack frame
+L9C5A           rti
+L9C5B           fcb 10,12,1,3,5,6,8             ; table of half tone numbers for notes A-G
+L9C62           fdb 0x01a8,0x0190,0x017a,0x0164 ; delays for octave 1
+                fdb 0x0150,0x013d,0x012b,0x011a
+                fdb 0x010a,0x00fb,0x00ed,0x00df
+                fdb 0x00d3,0x00c7,0x00bb,0x00b1 ; delays for octave 2
+                fdb 0x00a6,0x009d,0x0094,0x008b
+                fdb 0x0083,0x007c,0x0075,0x006e
+L9C92           fcb 0xa6,0x9c,0x93,0x8b         ; delays for octave 3
+                fcb 0x83,0x7b,0x74,0x6d
+                fcb 0x67,0x61,0x5b,0x56
+                fcb 0x51,0x4c,0x47,0x43         ; delays for octave 4
+                fcb 0x3f,0x3b,0x37,0x34
+                fcb 0x31,0x2e,0x2b,0x28
+                fcb 0x26,0x23,0x21,0x1f         ; delays for octave 5
+                fcb 0x1d,0x1b,0x19,0x18
+                fcb 0x16,0x14,0x13,0x12
+; DRAW command
+DRAW            ldx ZERO                        ; create an empty "DRAW" frame
+                ldb #1
+                pshs x,b
+                stb SETFLG                      ; set to "PSET" mode
+                stx VD5                         ; clear update and draw flag
+                jsr L959A                       ; set active colour byte
+                jsr LB156                       ; evaluate command string
+L9CC6           jsr LB654                       ; fetch command string details
+                bra L9CD3                       ; interpret the command string
+L9CCB           jsr L9B98                       ; fetch command character
+                jmp L9BBE                       ; evaluate a number
+L9CD1           puls b,x                        ; get previously saved command string
+L9CD3           stb VD8                         ; save length counter
+                beq L9CD1                       ; brif end of string
+                stx VD9                         ; save pointer
+                lbeq L9DC7                      ; brif overall end of command
+L9CDD           tst VD8                         ; are we at the end of the string?
+                beq L9CD1                       ; brif so - return to previous string
+                jsr L9B98                       ; get command character
+                cmpa #';                        ; semicolon?
+                beq L9CDD                       ; brif so - ignore it
+                cmpa #''                        ; '?
+                beq L9CDD                       ; brif so - ignore that too
+                cmpa #'N                        ; update position toggle?
+                bne L9CF4                       ; brif not
+                com VD5                         ; toggle update position flag
+                bra L9CDD                       ; get on for another command
+L9CF4           cmpa #'B                        ; blank flag?
+                bne L9CFC                       ; brif not
+                com VD6                         ; toggle blank flag
+                bra L9CDD                       ; get on for another command
+L9CFC           cmpa #'X                        ; substring?
+                lbeq L9D98                      ; brif so - execute command
+                cmpa #'M                        ; move draw position?
+                lbeq L9E32                      ; brif so
+                pshs a                          ; save command character
+                ldb #1                          ; default value if no number follows
+                tst VD8                         ; is there something there?
+                beq L9D21                       ; brif not
+                jsr L9B98                       ; get character
+                jsr LB3A2                       ; set C if not alpha
+                pshs cc                         ; save alpha state
+                jsr L9BE2                       ; move back pointer
+                puls cc                         ; get back alpha flag
+                bcc L9D21                       ; brif it's alpha
+                bsr L9CCB                       ; evaluate a number
+L9D21           puls a                          ; get command back
+                cmpa #'C                        ; color change?
+                beq L9D4F                       ; brif so
+                cmpa #'A                        ; angle?
+                beq L9D59                       ; brif so
+                cmpa #'S                        ; scale?
+                beq L9D61                       ; brif so
+                cmpa #'U                        ; up?
+                beq L9D8F                       ; brif so
+                cmpa #'D                        ; down?
+                beq L9D8C                       ; brif so
+                cmpa #'L                        ; left?
+                beq L9D87                       ; brif so
+                cmpa #'R                        ; right?
+                beq L9D82                       ; brif so
+                suba #'E                        ; normalize the half cardinals to 0
+                beq L9D72                       ; brif E (45°)
+                deca                            ; F (135°?)
+                beq L9D6D                       ; brif so
+                deca                            ; G (225°?)
+                beq L9D7B                       ; brif so
+                deca                            ; H (315°?)
+                beq L9D69                       ; brif so
+L9D4C           jmp LB44A                       ; raise FC error
+L9D4F           jsr L955D                       ; adjust colour for PMODE
+                stb FORCOL                      ; save new foreground colour
+                jsr L959A                       ; set up working colour and all pixels byte
+L9D57           bra L9CDD                       ; go process another command
+L9D59           cmpb #4                         ; only 3 angles are valid
+                bhs L9D4C                       ; brif not valid
+                stb ANGLE                       ; save new angle
+                bra L9D57                       ; go process another command
+L9D61           cmpb #63                        ; only 64 scale values are possible
+                bhs L9D4C                       ; brif out of range
+                stb SCALE                       ; save new scale factor
+                bra L9D57                       ; go process another command
+L9D69           clra                            ; make horizontal negative
+                bsr L9DC4
+                skip1
+L9D6D           clra                            ; keep horizontal distance positive
+                tfr d,x                         ; make horizontal distance and vertical distance the same
+                bra L9DCB                       ; go do the draw thing
+L9D72           clra                            ; zero extend horizontal distance
+                tfr d,x                         ; set it as vertical
+                bsr L9DC4                       ; negate horizontal distance
+                exg d,x                         ; swap directions (vertical is now negative)
+                bra L9DCB                       ; go do the draw thing
+L9D7B           clra                            ; zero extend horizontal distance
+                tfr d,x                         ; copy horizontal to vertical
+                bsr L9DC4                       ; negate horizontal
+                bra L9DCB                       ; go do the drawing thing
+L9D82           clra                            ; zero extend horizontal distance
+L9DB3           ldx ZERO                        ; no vertical distance
+                bra L9DCB                       ; go do the drawing things
+L9D87           clra                            ; zero extend horizontal
+                bsr L9DC4                       ; negate horizontal
+                bra L9DB3                       ; zero out vertical and do the drawing thing
+L9D8C           clra                            ; zero extend distance
+                bra L9D92                       ; make the distance vertical and zero out horizontal
+L9D8F           clra                            ; zero extend distance
+                bsr L9DC4                       ; negate distance
+L9D92           ldx ZERO                        ; zero out vertical distance
+                exg x,d                         ; swap vertical and horizontal
+                bra L9DCB                       ; go do the drawing thing
+L9D98           jsr L9C1B                       ; evaluate substring expression
+                ldb #2                          ; is there enough room for the state?
+                jsr LAC33
+                ldb VD8                         ; save current command string state
+                ldx VD9
+                pshs x,b
+                jmp L9CC6                       ; go evaluate the sub string
+L9DA9           ldb SCALE                       ; get scale factor
+                beq L9DC8                       ; brif zero - default to full size
+                clra                            ; zero extend
+                exg d,x                         ; put distance somewhere useful
+                sta ,-s                         ; save MS of distance
+                bpl L9DB6                       ; brif positive distance
+                bsr L9DC3                       ; negate the distance
+L9DB6           jsr L9FB5                       ; multiply D and X
+                tfr u,d                         ; save ms bytes in D
+                lsra                            ; divide by 2
+                rorb
+L9DBD           lsra                            ; ...divide by 4
+                rorb
+                tst ,s+                         ; negative distance?
+                bpl L9DC7                       ; brif it was positive
+L9DC3           nega                            ; negate D
+L9DC4           negb
+                sbca #0
+L9DC7           rts
+L9DC8           tfr x,d                         ; copy unchanged sitance to D
+                rts
+L9DCB           pshs b,a                        ; save horizontal distance
+                bsr L9DA9                       ; apply scale factor to vertical
+                puls x                          ; get horizontal distance
+                pshs b,a                        ; save scaled vertical
+                bsr L9DA9                       ; apply scale to horizontal
+                puls x                          ; get back vertical distance
+                ldy ANGLE                       ; get draw angle and scale
+                pshs y                          ; save them
+L9DDC           tst ,s                          ; is there an angle?
+                beq L9DE8                       ; brif no angle
+                exg x,d                         ; swap distances
+                bsr L9DC3                       ; negate D
+                dec ,s                          ; account for one tick around the rotation
+                bra L9DDC                       ; see if we're there yet
+L9DE8           puls y                          ; get angle and scale back
+                ldu ZERO                        ; default end position (horizontal) is 0
+                addd HORDEF                     ; add default horizontal to horizontal distance
+                bmi L9DF2                       ; brif we went negative
+                tfr d,u                         ; save calculated end coordindate
+L9DF2           tfr x,d                         ; get vertical distance somewhere useful
+                ldx ZERO                        ; default vertical end is 0
+                addd VERDEF                     ; add distance to default vertical start
+                bmi L9DFC                       ; brif negative - use 0
+                tfr d,x                         ; save calculated end coordinate
+L9DFC           cmpu #256                       ; is horizontal in range?
+                blo L9E05                       ; brif su
+                ldu #255                        ; maximize it
+L9E05           cmpx #192                       ; is vertical in range?
+                blo L9E0D                       ; brif so
+                ldx #191                        ; maximize it
+L9E0D           ldd HORDEF                      ; set starting coordinates for the line
+                std HORBEG
+                ldd VERDEF
+                std VERBEG
+                stx VEREND                      ; set end coordinates
+                stu HOREND
+                tst VD5                         ; are we updating position?
+                bne L9E21                       ; brif not
+                stx VERDEF                      ; update default coordinates
+                stu HORDEF
+L9E21           jsr L9420                       ; normalize coordindates
+                tst VD6                         ; are we drawing something?
+                bne L9E2B                       ; brif not
+                jsr L94A1                       ; draw the line
+L9E2B           clr VD5                         ; reset draw and update flags
+                clr VD6
+                jmp L9CDD                       ; do another command
+L9E32           jsr L9B98                       ; get a command character
+                pshs a                          ; save it
+                jsr L9E5E                       ; evaluate horizontal distance
+                pshs b,a                        ; save it
+                jsr L9B98                       ; get character
+                cmpa #',                        ; comma between coordinates?
+                lbne L9D4C                      ; brif not - raise error
+                jsr L9E5B                       ; evaluate vertical distance
+                tfr d,x                         ; save vertical distance
+                puls u                          ; get horizontal distance
+                puls a                          ; get back first command character
+                cmpa #'+                        ; was it + at start?
+                beq L9E56                       ; brif +; treat values as positive
+                cmpa #'-                        ; was it -?
+                bne L9DFC                       ; brif not - treat it as absolute
+L9E56           tfr u,d                         ; put horizontal distance somewhere useful
+                jmp L9DCB                       ; move draw position (relative)
+L9E5B           jsr L9B98                       ; get input character
+L9E5E           cmpa #'+                        ; leading +?
+                beq L9E69                       ; brif so
+                cmpa #'-                        ; leading -?
+                beq L9E6A                       ; brif so - negative
+                jsr L9BE2                       ; move pointer back one
+L9E69           clra                            ; 0  for +, nonzero for -
+L9E6A           pshs a                          ; save sign flag
+                jsr L9CCB                       ; evaluate number
+                puls a                          ; get sign flag
+                tsta                            ; negative?
+                beq L9E78                       ; brif not
+                clra                            ; zero extend and negate
+                negb
+                sbca #0
+L9E78           rts
+; Table of sines and cosines for CIRCLE
+L9E79           fdb 0x0000,0x0001               ; subarc 0
+                fdb 0xfec5,0x1919               ; subarc 1
+                fdb 0xfb16,0x31f2               ; subarc 2
+                fdb 0xf4fb,0x4a51               ; subarc 3
+                fdb 0xec84,0x61f9               ; subarc 4
+                fdb 0xe1c7,0x78ae               ; subarc 5
+                fdb 0xd4dc,0x8e3b               ; subarc 6
+                fdb 0xc5e5,0xa269               ; subarc 7
+                fdb 0xb506,0xb506               ; subarc 8
+; CIRCLE command
+; The circle is drawn as a 64 sided polygon (64 LINE commands essentially)
+CIRCLE          cmpa #'@                        ; is there an @ before coordinates?
+                bne L9EA3                       ; brif not
+                jsr GETNCH                      ; eat the @
+L9EA3           jsr L9522                       ; get max coordinates for screen
+                jsr L93B2                       ; parse coordinates for circle centre
+                jsr L931D                       ; normalize the start coordinates
+                ldx ,u                          ; get horizontal coordinate
+                stx VCB                         ; save it
+                ldx 2,u                         ; get vertical coordinate
+                stx VCD                         ; saveit
+                jsr SYNCOMMA                    ; make sure we have a comma
+                jsr LB73D                       ; evaluate radius expression
+                ldu #VCF                        ; point to temp storage
+                stx ,u                          ; save radius
+                jsr L9320                       ; normalize radius
+                lda #1                          ; default to PSET
+                sta SETFLG
+                jsr L9581                       ; evaluate the colour expression
+                ldx #0x100                      ; height/width default value
+                jsr GETCCH                      ; is there a ratio?
+                beq L9EDF                       ; brif not
+                jsr SYNCOMMA                    ; make sure we have a comma
+                jsr LB141                       ; evaluate the ratio
+                lda FP0EXP                      ; multiply ratio by 256
+                adda #8
+                sta FP0EXP
+                jsr LB740                       ; evaluate ratio to X (fraction part in LSB)
+L9EDF           lda PMODE                       ; get graphics mode
+                bita #2                         ; is it even?
+                beq L9EE9                       ; brif so
+                tfr x,d                         ; double the ratio
+                leax d,x
+L9EE9           stx VD1                         ; save height/width ratio
+                ldb #1                          ; set the SET flag to PSET
+                stb SETFLG
+                stb VD8                         ; set first time flag (set to 0 after arc drawn)
+                jsr L9FE2                       ; evaluate circle starting point (octant, subarc)
+                pshs b,a                        ; save startpoint
+                jsr L9FE2                       ; evaluate circle end point (octant, subarc)
+                std VD9                         ; save endp oint
+                puls a,b
+L9EFD           pshs b,a                        ; save current circle position
+                ldx HOREND                      ; move end coordinates to start coordinates
+                stx HORBEG
+                ldx VEREND
+                stx VERBEG
+                ldu #L9E79+2                    ; point to sine/cosine table
+                anda #1                         ; even octant?
+                beq L9F11                       ; brif so
+                negb                            ; convert 0-7 to 8-1 for odd octants
+                addb #8
+L9F11           aslb                            ; four bytes per table entry
+                aslb
+                leau b,u                        ; point to correct table entry
+                pshs u                          ; save sine/cosine table entry pointer
+                jsr L9FA7                       ; calculate horizontal offset
+                puls u                          ; get back table entry pointer
+                leau -2,u                       ; move to cosine entry
+                pshs x                          ; save horizontal offset
+                jsr L9FA7                       ; calculate vertical offset
+                puls y                          ; put horizontal in Y
+                lda ,s                          ; get octant number
+                anda #3                         ; is it 0 or 4?
+                beq L9F31                       ; brif so
+                cmpa #3                         ; is it 3 or 7?
+                beq L9F31                       ; brif so
+                exg x,y                         ; swap horizontal and vertical
+L9F31           stx HOREND                      ; save horizontal offset
+                tfr y,x                         ; put vertical offset in X
+                ldd VD1                         ; get height/width ratio
+                jsr L9FB5                       ; multiply vertical by h/w ratio
+                tfr y,d                         ; save the product to D
+                tsta                            ; did it overflow?
+                lbne LB44A                      ; brif so
+                stb VEREND                      ; save vertical coordinate MSB
+                tfr u,d                         ; get LSW of product
+                sta VEREND+1                    ; save LSB of integer part (we have 8 bits of fraction in the ratio)
+                lda ,s                          ; get octant
+                cmpa #2                         ; is it 0 or 1?
+                blo L9F5B                       ; brif so
+                cmpa #6                         ; is it 6 or 7?
+                bhs L9F5B                       ; brif so
+                ldd VCB                         ; get horizontal centre
+                subd HOREND                     ; subtract horizontal displacement
+                bcc L9F68                       ; brif we didn't overflow the screen
+                clra                            ; zero out coordinate if we overflowed the screen
+                clrb
+                bra L9F68
+L9F5B           ldd VCB                         ; get horizontal coordinate of the centre
+                addd HOREND                     ; add displacement
+                bcs L9F66                       ; brif overlod
+                cmpd VD3                        ; larger than max horizontal coord?
+                blo L9F68                       ; brif not
+L9F66           ldd VD3                         ; maximize the coordinate
+L9F68           std HOREND                      ; save horizontal ending coordainte
+                lda ,s                          ; get octant
+                cmpa #4                         ; is it 0-3?
+                blo L9F7A                       ; brif so
+                ldd VCD                         ; get vertical coordinate of centre
+                subd VEREND                     ; subtract displacement
+                bcc L9F87                       ; brif we didn't overflow the screen
+                clra                            ; minimize to top of screen
+                clrb
+                bra L9F87
+L9F7A           ldd VCD                         ; get vertical centre coordinate
+                addd VEREND                     ; add displacement
+                bcs L9F85                       ; brif we overflowed the screen
+                cmpd VD5                        ; did we go past max coordinate?
+                blo L9F87                       ; brif not
+L9F85           ldd VD5                         ; maximize the coordinate
+L9F87           std VEREND                      ; save end coordinate
+                tst VD8                         ; check first time flag
+                bne L9F8F                       ; do not draw if first time through (it was setting start coord)
+                bsr L9FDF                       ; draw the line
+L9F8F           puls a,b                        ; get arc number and sub arc
+                lsr VD8                         ; get first time flag value (and clear it!)
+                bcs L9F9A                       ; do not check for end point after drawing for first coordinate
+                cmpd VD9                        ; at end point?
+                beq L9FA6                       ; brif drawing finished
+L9F9A           incb                            ; bump arc counter
+                cmpb #8                         ; done 8 arcs?
+                bne L9FA3                       ; brif not
+                inca                            ; bump octant
+                clrb                            ; reset subarc number
+                anda #7                         ; make sure octant number stays in 0-7 range
+L9FA3           jmp L9EFD                       ; go do another arc
+L9FA6           rts
+L9FA7           ldx VCF                         ; get radius
+                ldd ,u                          ; get sine/cosine table entry
+                beq L9FB4                       ; brif 0 - offset = radius
+                subd #1                         ; adjust values to correct range
+                bsr L9FB5                       ; multiply radius by sine/cosine
+                tfr y,x                         ; resturn result in X
+L9FB4           rts
+L9FB5           pshs u,y,x,b,a                  ; save registers and reserve temp space
+                clr 4,s                         ; reset overflow byte (YH)
+                lda 3,s                         ; calcuate B*XL
+                mul
+                std 6,s                         ; put in "U"
+                ldd 1,s                         ; calculate B*XH
+                mul
+                addb 6,s                        ; accumluate with previous product
+                adca #0
+                std 5,s                         ; save in YL,UH
+                ldb ,s                          ; calculate A*XL
+                lda 3,s
+                mul
+                addd 5,s                        ; accumulate with previous partical product
+                std 5,s                         ; save in YL,UH
+                bcc L9FD4                       ; brif no carry
+                inc 4,s                         ; bump YH for carry
+L9FD4           lda ,s                          ; calculate A*XH
+                ldb 2,s
+                mul
+                addd 4,s                        ; accumulate with previous partial product
+                std 4,s                         ; save in Y (we can't have a carry here)
+                puls a,b,x,y,u,pc               ; restore multiplicands and return results
+L9FDF           jmp L94A1                       ; go draw a line
+L9FE2           clrb                            ; default arc number (0)
+                jsr GETCCH                      ; is there something there for a value?
+                beq L9FF8                       ; brif not
+                jsr SYNCOMMA                    ; evaluate , + expression
+                jsr LB141
+                lda FP0EXP                      ; multiply by 64
+                adda #6
+                sta FP0EXP
+                jsr LB70E                       ; get integer value of circle fraction
+                andb #0x3f                      ; max value of 63
+L9FF8           tfr b,a                         ; save arc value in A to calculate octant
+                andb #7                         ; calculate subarc
+                lsra                            ; calculate octant
+                lsra
+                lsra
+                rts
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; COLOR BASIC ROM area
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; This is the official set of ROM entry points. It is unfortunate that the generic input ("console in") routine is not exposed
+; here. It is also unfortunate that no open and close file routines are exposed. This and other oversignts led to a lot of
+; software either having to re-invent the wheel or calling directly into the ROM instead of via these official entry points.
+POLCAT          fdb KEYIN                       ; indirect jump, get a keystroke
+CHROUT          fdb PUTCHR                      ; indirect jump, output character
+CSRDON          fdb CASON                       ; indirect jump, turn cassette on and start reading
+BLKIN           fdb GETBLK                      ; indirect jump, read a block from tape
+BLKOUT          fdb SNDBLK                      ; indirect jump, write a block to tape
+JOYIN           fdb GETJOY                      ; indirect jump, read joystick axes
+WRTLDR          fdb WRLDR                       ; indirect jump, turn cassette on and write a leader
+; Initialization code.
+LA00E           lds #LINBUF+LBUFMX+1            ; put the stack in the line input buffer which is a safe place for now
+                lda #0x37                       ; enable the cartidge interrupt (to detect autostarting cartridges)
+                sta PIA1+3
+                lda RSTFLG                      ; get warm start flag
+                cmpa #0x55                      ; is it valid?
+                bne BACDST                      ; brif not - cold start
+                ldx RSTVEC                      ; get warm start routine pointer
+                lda ,x                          ; get first byte of the routine
+                cmpa #0x12                      ; is it NOP?
+                bne BACDST                      ; brif not - the routine is invalid so do a cold start
+                jmp ,x                          ; transfer control to the warm start routine
+; RESET/power on comes here
+RESVEC          leay LA00E,pcr                  ; point to warm start check code
+LA02A           lda #0x3a                       ; restore MMU block in 0x4000-0x5fff block
+                sta MMUREG+2
+                ldx #PIA1                       ; point to PIA1
+                ldd #0xff34                     ; set up for initializing PIAs
+                clr 1,x                         ; set PIA1 DA to direction mode
+                clr 3,x                         ; set PIA1 DB to direction mode
+                deca
+                sta ,x                          ; set PIA1 DA bits 7-1 as output, 0 as input
+                lda #0xf8                       ; set PIA1 DB bits 7-3 as output, 2-0 as input
+                sta 2,x
+                stb 1,x                         ; set PIA1 DA to data mode
+                stb 3,x                         ; set PIA1 DB to data mode
+                clr 2,x                         ; set VDG to alpha-numeric
+                lda #2                          ; set RS232 to marking
+                sta ,x
+                lda #0xff
+                ldx #PIA0                       ; point to PIA0
+                clr 1,x                         ; set PIA0 DA to direction mode
+                clr 3,x                         ; set PIA0 DB to direction mode
+                clr ,x                          ; set PIA0 DA to input
+                sta 2,x                         ; set PIA0 DB to output
+                stb 1,x                         ; set PIA0 DA to direction mode
+                stb 3,x                         ; set PIA0 DB to direction mode
+                jmp LA072                       ; continue initializing
+LA05E           jsr L8C2E                       ; map ROM pack
+                jmp 0xc000                      ; transfer control to ROM pack
+; Left over initialization code from Color Basic 1.2 follows
+	bitb 2,x                        ; check RAMSZ input
+	beq LA072                       ; brif set for 4K RAMs
+	clr -2,x                        ; set strobe low
+	bitb 2,x                        ; check input
+	beq LA070                       ; brif set for 64K rams
+	leau -2,u                       ; adjust pointer to set SAM for 16K RAMs
+LA070           sta -3,u                        ; program SAM for either 16K or 64K RAMs
+LA072           jmp ,y                          ; transfer control to startup routine
+; Cold start jumps here
+BACDST          ldx #VIDRAM+1                   ; point past the top of the first 1K of memory (for double predec below)
+LA077           clr ,--x                        ; clear a byte (last will actually try clearing LSB of RESET vector in ROM)
+                leax 1,x                        ; move forward one byte (will set Z if we're done)
+                bne LA077                       ; brif not donw yet
+                jsr LA928                       ; clear the screen
+                clr ,x+                         ; put the constant zero that lives before the program
+                stx TXTTAB                      ; set beginning of program storage
+LA084           ldx #0x7fff                     ; set to of available RAM to just below the "ROM" area
+                bra LA093
+                nop
+                nop
+                nop
+                nop
+                nop
+                nop
+                nop
+                nop
+                nop
+                nop
+LA093           stx TOPRAM                      ; save top of memory (one below actual top because we need a byte for VAL() to work)
+                stx MEMSIZ                      ; save top of string space
+                stx STRTAB                      ; set bottom of allocated string space
+                leax -200,x                     ; allocate 200 bytes of string space
+                stx FRETOP                      ; set top of actually free memory
+                tfr x,s                         ; put the stack there
+                ldx #LA10D                      ; point to variable initializer
+                ldu #CMPMID                     ; point to variables to initialize (first batch)
+                ldb #28                         ; 28 bytes in first batch
+                jsr LA59A                       ; copy bytes to variables
+                ldu #IRQVEC                     ; point to variables to initialize (second batch)
+                ldb #30                         ; 30 bytes this time
+                jsr LA59A                       ; copy bytes to variables
+                ldx -12,x                       ; get SN error address
+                stx 3,u                         ; set ECB's command handlers to error
+                stx 8,u
+                ldx #RVEC0                      ; point to RAM vectors
+                ldd #0x394b                     ; write 75 RTS opcodes (25 RAM vectors)
+LA0C0           sta ,x+                         ; put an RTS
+                decb                            ; done?
+                bne LA0C0                       ; brif not
+                sta LINHDR-1                    ; make temporary line header data for line encoding have a nonzero next line pointer
+                jsr LAD19                       ; do a "NEW"
+                jmp L8002                       ; transfer control to ECB's initialization routine
+LA0CE           pshs b,x                        ; save registers
+                tst HRWIDTH                     ; is it VDG mode?
+                lbne ALINK24                    ; brif not
+LA0D6           jsr LA199                       ; do a "cursor"
+                jsr KEYIN                       ; read a key
+                beq LA0D6                       ; brif no key
+LA0DE           jmp LA1B9                       ; return to mainline
+                fcb 0x72                        ; left-over from code replacement above
+LA0E2           lda #0x55                       ; warm start valid flag
+                sta RSTFLG                      ; mark warm start valid
+                bra LA0F3                       ; go to direct mode
+; Warm start entry point
+BAWMST          nop                             ; valid routine marker
+                clr DEVNUM                      ; reset output/input to screen
+                jsr LAD33                       ; do a partial NEW
+                andcc #0xaf                     ; start interrupts
+                jsr CLS                         ; clear the screen
+LA0F3           jmp LAC73                       ; go to direct mode
+; FIRQ service routine - this handles starting autostart cartridges
+BFRQSV          tst PIA1+3                      ; is it the cartridge interrupt?
+                bmi LA0FC                       ; brif so
+                rti
+LA0FC           jsr L8C28                       ; map cartridge
+                jsr LA7D1                       ; delay for another while
+                leay <LA108,pcr                 ; point to cartridge starter
+                jmp LA02A                       ; go initialize everything clean for the cartridge
+LA108           clr RSTFLG                      ; force a cold start a cartridge reset
+                jmp ROMPAK                      ; transfer control to the cartridge
+; Variable initializers (first batch)
+LA10D           fcb 18                          ; mid band partition of the 1200/2400 Hz period
+                fcb 24                          ; upper limit of 1200 Hz period
+                fcb 10                          ; upper limit of 2400 Hz period
+                fdb 128                         ; number of 0x55s for cassette leader
+                fcb 11                          ; cursor blink delay
+                fdb 88                          ; 600 baud delay constant
+                fdb 1                           ; printer carriage return delay constant
+                fcb 16                          ; printer tab field width
+                fcb 112                         ; last printer tab zone
+                fcb 132                         ; printer carriage width
+                fcb 0                           ; printer carriage position
+                fdb LB44A                       ; default execution address for EXEC
+                inc CHARAD+1                    ;* character fetching routines (DP portion) - we first do a two
+                bne LA123                       ;* two stage increment of CHARAD then load the value into A
+                inc CHARAD                      ;* before transferring control to the bottom half routine in ROM
+LA123           lda >0                          ; NOTE: the 0 is a placeholder, extended addressing is required
+                jmp BROMHK
+; Variable initializers (second batch)
+                jmp BIRQSV                      ; IRQ handler
+                jmp BFRQSV                      ; FIRQ handler
+                jmp LB44A                       ; default USR() address
+                fcb 0x80,0x4f,0xc7,0x52,0x59    ; random seed
+                fcb 0xff                        ; capslock flag - default to upper case
+                fdb DEBDEL                      ; keyboard debounce delay (why is it a variable?)
+                jmp LB277                       ; exponentiation handler vector
+                fcb 53                          ; (command interpretation table) 53 commands
+                fdb LAA66                       ; (command interpretation table) reserved words list (commands)
+                fdb LAB67                       ; (command interpretation table) jump table (commands)
+                fcb 20                          ; (command interpretation table) 20 functions
+                fdb LAB1A                       ; (command interpretation table) reserved words list (functions)
+                fdb LAA29                       ; (command interpretation table) jump table (functions)
+; This is the signon message.
+LA147           fcc 'COLOR BASIC 1.2'
+                fcb 0x0d
+                fcc '(C) 1982 TANDY'
+                fcb 0
+; This is the "invalid colour" CLS easter egg text. Basically 11 wasted bytes
+LA166           fcc 'MICROSOFT'
+                fcb 0x0d,0
+; Read a character from current device and mask off bit 7 (keep it as 7 bit ASCII)
+LA171           bsr LA176                       ; get character
+                anda #0x7f                      ; mask off high bit
+                rts
+; Generic read routine. Reads a character from the device specified by DEVNUM. If no input was available,
+; CINBFL will bet nonzero (on EOF). If input was available, CINBFL will be zero. Note that this routine
+; has undefined results when called on an output only device. All registers except CC and A are preserved.
+LA176           jsr RVEC4                       ; do RAM hook
+                clr CINBFL                      ; flag data available
+                tst DEVNUM                      ; is it keyboard?
+                beq LA1B1                       ; brif so - blink cursor and wait for key press
+                tst CINCTR                      ; is there anything in cassette input buffer?
+                bne LA186                       ; brif so
+                com CINBFL                      ; flag EOF
+                rts
+; Read character from cassette file
+LA186           pshs u,y,x,b                    ; preserve registers
+                ldx CINPTR                      ; get input buffer pointer
+                lda ,x+                         ; get character from buffer
+                pshs a                          ; save it for return
+                stx CINPTR                      ; save new input buffer pointer
+                dec CINCTR                      ; count character just consumed
+                bne LA197                       ; brif buffer is not empty yet
+                jsr LA635                       ; go read another block, if any, to refill the buffer
+LA197           puls a,b,x,y,u,pc               ; restore registers and return the character
+; Blink the cursor. This might be better timed via an interrupt or something.
+LA199           dec BLKCNT                      ; is it time to blink the cursor?
+                bne LA1AB                       ; brif not
+                ldb #11                         ; reset blink timer
+                stb BLKCNT
+                ldx CURPOS                      ; get cursor position
+                lda ,x                          ; get character at the cursor
+                adda #0x10                      ; move to next color
+                ora #0x8f                       ; make sure it's a grahpics block with all elements lit
+                sta ,x                          ; put new cursor block on screen
+LA1AB           ldx #DEBDEL                     ; we'll use the debounce delay for the cursor blink timer (10ms)
+LA1AE           jmp LA7D3                       ; go count X down
+; Blink cursor while waiting for a key press
+LA1B1           pshs x,b                        ; save registers
+LA1B3           bsr LA199                       ; go do a cursor iteration
+                bsr KEYIN                       ; go read a key
+                beq LA1B3                       ; brif no key pressed
+LA1B9           ldb #0x60                       ; VDG screen space character
+                stb [CURPOS]                    ; blank cursor out
+                puls b,x,pc                     ; restore registers and return
+; This is the actual keyboard polling routine. Returns 0 if no new key is down. Compared to the 1.0 and 1.1
+; ROMs, this routine is quite a lot more compact and robust.
+LA1C1           jmp KEYIN                       ; transfer control to actual keyboard scan
+                rts                             ;* this actually removes a check to see if any keys are actually down
+                rts                             ;* which is unfortunate because it makes programs run slower.
+                rts
+                rts
+                rts
+                rts
+                rts
+KEYIN           pshs u,x,b                      ; save registers
+                ldu #PIA0                       ; point to keyboard PIA
+                ldx #KEYBUF                     ; point to state table
+                clra                            ; clear carry, set column to 0xff (no strobe)
+                deca                            ; (note: deca does not affect C)
+                pshs x,a                        ; save column counter and make a couple of holes for temporaries
+                sta 2,u                         ; set strobe to no columns
+LA1D9           rol 2,u                         ; move to next column (C is 0 initially, 1 after)
+                bcc LA220                       ; brif we shifted out a 0 - we've done 8 columns
+                inc 0,s                         ; bump column counter (first bump goes to 0)
+                bsr LA23A                       ; read row data
+                sta 1,s                         ; save key data (for debounce check and later saving)
+                eora ,x                         ; now bits set if key state changed
+                anda ,x                         ; now bits are only set if a key has been pressed
+                ldb 1,s                         ; get new key data
+                stb ,x+                         ; save in state table
+                tsta                            ; was a key down?
+                beq LA1D9                       ; brif not - do another (nothing above cleared C)
+                ldb 2,u                         ; get strobe data
+                stb 2,s                         ; save it for debounce check
+                ldb #0xf8                       ; set up so B is 0 after first add
+LA1F4           addb #8                         ; add 8 for each row
+                lsra                            ; did we hit the right row?
+                bcc LA1F4                       ; brif not
+                addb 0,s                        ; add in column number
+                beq LA245                       ; brif @
+                cmpb #26                        ; letter?
+                bhi LA247                       ; brif not
+                orb #0x40                       ; bias into letter range
+                bsr LA22E                       ; check for SHIFT
+                ora CASFLG                      ; merge in capslock state
+                bne LA20C                       ; brif either capslock or SHIFT - keep upper case
+                orb #0x20                       ; move to lower case
+LA20C           stb 0,s                         ; save ASCII value
+                ldx DEBVAL                      ; get debounce delay
+                bsr LA1AE                       ; do the 10ms debounce delay
+                ldb #0xff                       ; set strobe to none - only joystick buttons register now
+                bsr LA238                       ; read keyboard
+                inca                            ; A now 0 if no buttons down
+                bne LA220                       ; brif button down - return nothing since we have interference
+LA21A           ldb 2,s                         ; get column strobe data
+                bsr LA238                       ; read row data
+                cmpa 1,s                        ; does it match original read?
+LA220           puls a,x                        ; clean up stack and get return value
+                bne LA22B                       ; brif failed debounce or a joystick button down
+                cmpa #0x12                      ; is it SHIFT-0?
+                bne LA22C                       ; brif not
+                com CASFLG                      ; swap capslock state
+LA22B           clra                            ; set no key down
+LA22C           puls b,x,u,pc                   ; restore registers and return
+LA22E           lda #0x7f                       ; column strobe for SHIFT
+                sta 2,u                         ; set column
+                lda ,u                          ; get row data
+                coma                            ; set if key down
+                anda #0x40                      ; only keep SHIFT state
+                rts
+LA238           stb 2,u                         ; save strobe data
+LA23A           lda ,u                          ; get row data
+                ora #0x80                       ; mask off comparator so it doesn't interfere
+                tst 2,u                         ; are we on column 7?
+                bmi LA244                       ; brif not
+                ora #0xc0                       ; also mask off SHIFT
+LA244           rts
+LA245           ldb #51                         ; scan code for @
+LA247           ldx #CONTAB-0x36                ; point to code table
+                cmpb #33                        ; arrows, space, zero?
+                blo LA264                       ; brif so
+                ldx #CONTAB-0x54                ; adjust to other half of table
+                cmpb #48                        ; ENTER, CLEAR, BREAK, @?
+                bhs LA264                       ; brif so
+                bsr LA22E                       ; read shift state
+                cmpb #43                        ; is it a number, colon, semicolon?
+                bls LA25D                       ; brif so
+                eora #0x40                      ; invert shift state for others
+LA25D           tsta                            ; shift down?
+                bne LA20C                       ; brif not - return result
+                addb #0x10                      ; add in offset to shifted character
+                bra LA20C                       ; go return result
+LA264           lslb                            ; two entries per key
+                bsr LA22E                       ; check SHIFT state
+                beq LA26A                       ; brif not shift
+                incb                            ; point to shifted entry
+LA26A           ldb b,x                         ; get actual key code
+                bra LA20C                       ; go return result
+CONTAB          fcb 0x5e,0x5f                   ; <UP> (^, _)
+                fcb 0x0a,0x5b                   ; <DOWN> (LF, [)
+                fcb 0x08,0x15                   ; <LEFT> (BS, ^U)
+                fcb 0x09,0x5d                   ; <RIGHT> (TAB, ])
+                fcb 0x20,0x20                   ; <SPACE>
+                fcb 0x30,0x12                   ; <0> (0, ^R)
+                fcb 0x0d,0x0d                   ; <ENTER> (CR, CR)
+                fcb 0x0c,0x5c                   ; <CLEAR> (FF, \)
+                fcb 0x03,0x03                   ; <BREAK> (^C, ^C)
+                fcb 0x40,0x13                   ; <@> (@, ^S)
+; Generic output routine.
+; Output character in A to the device specified by DEVNUM. All registers are preserved except CC.
+; Sending output to a device that does not support output is undefined.
+PUTCHR          jsr RVEC3                       ; call RAM hook
+                pshs b                          ; save B
+                ldb DEVNUM                      ; get desired device number
+                incb                            ; set flags (Z for -1, etc.)
+                puls b                          ; restore B
+                bmi LA2BF                       ; brif < -1 (line printer)
+                bne LA30A                       ; brif > -1 (screen)
+; Write character to tape file
+                pshs x,b,a                      ; save registers
+                ldb FILSTA                      ; get file status
+                decb                            ; input file?
+                beq LA2A6                       ; brif so
+                ldb CINCTR                      ; get character count
+                incb                            ; account for this character
+                bne LA29E                       ; brif buffer not full
+                bsr LA2A8                       ; write previously full block to tape
+LA29E           ldx CINPTR                      ; get output buffer pointer
+                sta ,x+                         ; put character in output
+                stx CINPTR                      ; save new buffer pointer
+                inc CINCTR                      ; account for this character
+LA2A6           puls a,b,x,pc                   ; restore registers and return
+; Write a block of data to tape.
+LA2A8           ldb #1                          ; data block type
+LA2AA           stb BLKTYP                      ; set block type
+                ldx #CASBUF                     ; point to output buffer
+                stx CBUFAD                      ; set buffer pointer
+                ldb CINCTR                      ; get number of bytes in the block
+                stb BLKLEN                      ; set length to write
+                pshs u,y,a                      ; save registers
+                jsr LA7E5                       ; write a block to tape
+                puls a,y,u                      ; restore registers
+                jmp LA650                       ; reset buffer pointers
+; Send byte to line printer
+LA2BF           pshs x,b,a,cc                   ; save registers and interrupt status
+                orcc #0x50                      ; disable interrupts
+LA2C3           ldb PIA1+2                      ; get RS232 status
+                lsrb                            ; get status to C
+                bcs LA2C3                       ; brif busy - loop until not busy
+                bsr LA2FB                       ; set output to marking
+                clrb                            ; transmit one start bit
+                bsr LA2FD
+                ldb #8                          ; counter for 8 bits
+LA2D0           pshs b                          ; save bit count
+                clrb                            ; zero output bits
+                lsra                            ; bet output bit to C
+                rolb                            ; get output bit to correct bit for output byte
+                lslb
+                bsr LA2FD                       ; transmit bit
+                puls b                          ; get back bit counter
+                decb                            ; are we done yet?
+                bne LA2D0                       ; brif not
+                bsr LA2FB                       ; send stop bit (marking)
+                puls cc,a                       ; restore interrupt status and output character
+                cmpa #0x0d                      ; carriage return?
+                beq LA2ED                       ; brif so
+                inc LPTPOS                      ; bump output position
+                ldb LPTPOS                      ; get new position
+                cmpb LPTWID                     ; end of line?
+                blo LA2F3                       ; brif not
+LA2ED           clr LPTPOS                      ; reset position to start of line
+                bsr LA305                       ; do carriage return delay
+                bsr LA305
+LA2F3           ldb PIA1+2                      ; get RS232 status
+                lsrb                            ; get status to C
+                bcs LA2F3                       ; brif still busy, keep waiting
+                puls b,x,pc                     ; restore registers and return
+LA2FB           ldb #2                          ; set output to high (marking)
+LA2FD           stb PIA1                        ; set RS232 output
+                bsr LA302                       ; do baud delay (first iteration) then fall through for second
+LA302           ldx LPTBTD                      ; get buard rate delay constant
+                skip2
+LA305           ldx LPTLND                      ; get carriage return delay constant
+                jmp LA7D3                       ; count X down
+; Output character to screen
+LA30A           pshs x,b,a                      ; save registers
+                ldx CURPOS                      ; get cursor pointer
+LA30E           cmpa #0x08                      ; backspace?
+                bne LA31D                       ; brif not
+                cmpx #VIDRAM                    ; at top of screen?
+                beq LA35D                       ; brif so - it's a no-op
+                lda #0x60                       ; VDG space character
+                sta ,-x                         ; put a space at previous location and move pointer back
+                bra LA344                       ; save new cursor position and return
+LA31D           cmpa #0x0d                      ; carriage return?
+                bne LA32F                       ; brif not
+                ldx CURPOS                      ; get cursor pointer (why? we already have it)
+LA323           lda #0x60                       ; VDG space character
+                sta ,x+                         ; put output space
+                tfr x,d                         ; see if we at a multiple of 32 now
+                bitb #0x1f
+                bne LA323                       ; brif not
+                bra LA344                       ; go check for scrolling
+LA32F           cmpa #0x20                      ; control character?
+                blo LA35D                       ; brif so
+                tsta                            ; is it graphics block?
+                bmi LA342                       ; brif so
+                cmpa #0x40                      ; number or special?
+                blo LA340                       ; brif so (flip "case" bit)
+                cmpa #0x60                      ; upper case alpha?
+                blo LA342                       ; brif so - keep it unmodified
+                anda #0xdf                      ; clear bit 5 (inverse video)
+LA340           eora #0x40                      ; flip inverse video bit
+LA342           sta ,x+                         ; output character
+LA344           stx CURPOS                      ; save new cursor position
+                cmpx #VIDRAM+511                ; end of screen?
+                bls LA35D                       ; brif not
+                ldx #VIDRAM                     ; point to start of screen
+LA34E           ldd 32,x                        ; get two characters from next row
+                std ,x++                        ; put them on this row
+                cmpx #VIDRAM+0x1e0              ; at start of last row on screen?
+                blo LA34E                       ; brif not
+                ldb #0x60                       ; VDG space
+                jsr LA92D                       ; blank out last line (borrow CLS's loop)
+LA35D           puls a,b,x,pc                   ; restore registers and return
+; Set up device parameters for output
+LA35F           jsr RVEC2                       ; do the RAM hook dance
+                pshs x,b,a                      ; save registers
+                clr PRTDEV                      ; flag device as a screen
+                lda DEVNUM                      ; get devicenumber
+                beq LA373                       ; brif screen
+                inca                            ; is it tape?
+                beq LA384                       ; brif so
+                ldx LPTCFW                      ; get tab width and last tab stop for printer
+                ldd LPTWID                      ; get line width and current position for printer
+                bra LA37C                       ; set parameters
+LA373           ldb CURPOS+1                    ; get LSB of cursor position
+                andb #0x1f                      ; now we have the offset into the line
+                ldx #0x1010                     ; 16 character tab, position 16 is last tab stop
+                lda #32                         ; screen is 32 characters wide
+LA37C           stx DEVCFW                      ; save tab width and last tab stop for active device
+                stb DEVPOS                      ; save line position for current device
+                sta DEVWID                      ; save line width for current device
+                puls a,b,x,pc                   ; restore registers and return
+LA384           com PRTDEV                      ; flag device as non-display
+                ldx #0x0100                     ; tab width is 1, last tab field is 0
+                clra                            ; line width is 0
+                clrb                            ; character position on line is 0
+                bra LA37C                       ; go set parameters
+; This is the line input routine used for reading lines for Basic, both in immediate mode and for
+; INPUT and LINE INPUT. Exit with C set if terminated by BREAK and C clear if terminated by ENTER.
+; The actualy entry point is LA390. Note that this routine echoes to *all* devices.
+LA38D           jsr LA928                       ; clear screen (CLEAR key handling)
+LA390           jsr RVEC12                      ; do the RAM hook dance
+                clr IKEYIM                      ; reset cached input character from BREAK check
+                ldx #LINBUF+1                   ; point to line input buffer (input pointer)
+                ldb #1                          ; Number of characters in line (we start at 1 so BS handling is easier)
+LA39A           jsr LA171                       ; get an input character, only keep low 7 bits
+                tst CINBFL                      ; is it EOF?
+                bne LA3CC                       ; brif EOF
+                tst DEVNUM                      ; is it keyboard input?
+                bne LA3C8                       ; brif not - don't do line editing
+                cmpa #0x0c                      ; form feed (CLEAR)?
+                beq LA38D                       ; brif so - clear screen and reset
+                cmpa #0x08                      ; backspace?
+                bne LA3B4                       ; brif not
+                decb                            ; move back one character
+                beq LA390                       ; brif we were at the start of the line - reset and start again
+                leax -1,x                       ; move input pointer back
+                bra LA3E8                       ; echo the backspace and continue
+LA3B4           cmpa #0x15                      ; SHIFT-LEFT (kill line)?
+                bne LA3C2                       ; brif not
+LA3B8           decb                            ; at start of line?
+                beq LA390                       ; brif so - reset and restart
+                lda #0x08                       ; echo a backspace
+                jsr PUTCHR
+                bra LA3B8                       ; see if we've erased everything yet
+LA3C2           cmpa #0x03                      ; BREAK?
+                orcc #1                         ; set C if it is (only need Z for the next test
+LA3C6           beq LA3CD                       ; brif BREAK - exit
+LA3C8           cmpa #0x0d                      ; ENTER (CR)
+                bne LA3D9                       ; brif not
+LA3CC           clra                            ; clear carry (it might not be clear on EOF)
+LA3CD           pshs cc                         ; save ENTER/BREAK flag
+                jsr LB958                       ; echo a carriage return
+                clr ,x                          ; make sure we have a NUL at the end of the buffer
+                ldx #LINBUF                     ; point to input buffer
+                puls cc,pc                      ; restore ENTER/BREAK flag and return
+LA3D9           cmpa #0x20                      ; control character?
+                blo LA39A                       ; brif so - skip it
+                cmpa #'z+1                      ; above z?
+                bhs LA39A                       ; brif so - ignore it
+                cmpb #LBUFMX                    ; is the buffer full?
+                bhs LA39A                       ; brif so - ignore extra characters
+                sta ,x+                         ; put character in the buffer
+                incb                            ; bump character count
+LA3E8           jsr PUTCHR                      ; echo character
+                bra LA39A                       ; go handle next input character
+; Check if DEVNUM Is valid for reading. Raise FM error if open but not for reading. NO error if not open.
+LA3ED           jsr RVEC5                       ; do the RAM hook dance
+                lda DEVNUM                      ; get device number
+                beq LA415                       ; brif keyboard - always valid
+                inca                            ; is it tape?
+                bne LA403                       ; brif not
+                lda FILSTA                      ; get tape file status
+                bne LA400                       ; brif file is open
+LA3FB           ldb #22*2                       ; raise NO error
+                jmp LAC46
+LA400           deca                            ; is it in input mode?
+                beq LA415                       ; brif so
+LA403           jmp LA616                       ; raise FM error
+; Check if DEVNUM is valid for writing. Raise FM error if open but not for writing. NO error if not open.
+LA406           jsr RVEC6                       ; do the RAM hook dance
+                lda DEVNUM                      ; get device number
+                inca                            ; is it tape?
+                bne LA415                       ; brif not
+                lda FILSTA                      ; get file status
+                beq LA3FB                       ; brif not open
+                deca                            ; is it open for reading?
+                beq LA403                       ; brif so - bad mode
+LA415           rts
+; CLOSE command
+CLOSE           beq LA426                       ; brif no file specified - close all files
+                jsr LA5A5                       ; parse device number
+LA41B           bsr LA42D                       ; close specified file
+                jsr GETCCH                      ; is there more?
+                beq LA44B                       ; brif not
+                jsr LA5A2                       ; check for comma and parse another device number
+                bra LA41B                       ; go close this one
+; Close all files handler.
+LA426           jsr RVEC7                       ; Yup. The RAM hook dance.
+LA429           lda #-1                         ; start with tape file
+                sta DEVNUM
+; Close file specified in DEVNUM. Note that this never fails.
+LA42D           jsr RVEC8                       ; You know it. RAM hook.
+                lda DEVNUM                      ; get device we're closing
+                clr DEVNUM                      ; reset to screen/keyboard
+                inca                            ; is it tape?
+                bne LA44B                       ; brif not
+                lda FILSTA                      ; get file status
+                cmpa #2                         ; is it output?
+                bne LA449                       ; brif not
+                lda CINCTR                      ; is there anything waiting to be written?
+                beq LA444                       ; brif not
+                jsr LA2A8                       ; write final block of data
+LA444           ldb #0xff                       ; write EOF block
+                jsr LA2AA
+LA449           clr FILSTA                      ; mark tape file closed
+LA44B           rts
+; CSAVE command
+CSAVE           jsr LA578                       ; parse filename
+                jsr GETCCH                      ; see what we have after the file name
+                beq LA469                       ; brif none
+                jsr SYNCOMMA                    ; make sure there's a comma
+                ldb #'A                         ; make sure there's an A after
+                jsr LB26F
+                bne LA44B                       ; brif not end of line
+                clra                            ; file type 0 (basic program)
+                jsr LA65C                       ; write out header block
+                lda #-1                         ; set output to tape
+                sta DEVNUM
+                clra                            ; set Z so we list the whole program
+                jmp LIST                        ; go list the program to tape
+LA469           clra                            ; file type 0 (basic program)
+                ldx ZERO                        ; set to binary file mode
+                jsr LA65F                       ; write header block
+                clr FILSTA                      ; close files
+                inc BLKTYP                      ; set block type to data
+                jsr WRLDR                       ; write out a leader
+                ldx TXTTAB                      ; point to start of program
+LA478           stx CBUFAD                      ; set buffer location
+                lda #255                        ; block size to 255 bytes (max size)
+                sta BLKLEN
+                ldd VARTAB                      ; get end of program
+                subd CBUFAD                     ; how much is left?
+                beq LA491                       ; brif we have nothing left
+                cmpd #255                       ; do we have a full block worth?
+                bhs LA48C                       ; brif so
+                stb BLKLEN                      ; save actual remainder as block length
+LA48C           jsr SNDBLK                      ; write a block out
+                bra LA478                       ; go do another block
+LA491           neg BLKTYP                      ; set block type to 0xff (EOF)
+                clr BLKLEN                      ; no data in EOF block
+                jmp LA7E7                       ; write EOF, stop tape, and return
+; CLOAD and CLOADM commands
+CLOAD           clr FILSTA                      ; close tape file
+                cmpa #'M                        ; is it ClOADM?
+                beq LA4FE                       ; brif so
+                leas 2,s                        ; clean up stack
+                jsr LA5C5                       ; parse file name
+                jsr LA648                       ; go find the file
+                tst CASBUF+10                   ; is it binary?
+                beq LA4C8                       ; brif so
+                lda CASBUF+9                    ; is it ASCII?
+                beq LA4CD                       ; brif not
+                jsr LAD19                       ; clear out existing program
+                lda #-1                         ; set up for reading from tape
+                sta DEVNUM
+                inc FILSTA                      ; set tape file to input
+                jsr LA635                       ; go read first block
+                jmp LAC7C                       ; go to immediate mode to read in the program
+; This is the EOF handler for immediate mode. It's rather assinine for this to be located here. It is
+; probably an artifact of a substantially different code layout prior to compacting the ROM to fit in
+; 8K.
+LA4BF           jsr RVEC13                      ; do the RAM hook dance
+                jsr LA42D                       ; close file
+                jmp LAC73                       ; go back to immediate mode
+LA4C8           lda CASBUF+8                    ; get file type
+                beq LA4D0                       ; brif basic program
+LA4CD           jmp LA616                       ; raise FM error
+LA4D0           jsr LAD19                       ; erase existing program
+                jsr CASON                       ; start reading tape
+                ldx TXTTAB                      ; get start of program storage
+LA4D8           stx CBUFAD                      ; set load address for block
+                ldd CBUFAD                      ; get start of block
+                inca                            ; bump by 256
+                jsr LAC37                       ; check if there's room for a maximum sized block of 255
+                jsr GETBLK                      ; go read a block
+                bne LA4F8                       ; brif there was an error during reading
+                lda BLKTYP                      ; get type of block read
+                beq LA4F8                       ; brif header block - IO error
+                bpl LA4D8                       ; brif data block - read another
+                stx VARTAB                      ; save new end of program
+                bsr LA53B                       ; stop tape
+                ldx #LABED-1                    ; point to "OK" prompt
+                jsr STRINOUT                    ; show prompt
+                jmp LACE9                       ; reset various things and return
+LA4F8           jsr LAD19                       ; clear out partial program load
+LA4FB           jmp LA619                       ; raise IO error
+; This is the CLOADM command
+LA4FE           jsr GETNCH                      ; eat the "M"
+                bsr LA578                       ; parse file name
+                jsr LA648                       ; go find the file
+LA505           ldx ZERO                        ; default offset is 0
+                jsr GETCCH                      ; see if there's something after the file name
+                beq LA511                       ; brif no offset
+                jsr SYNCOMMA                    ; make sure there's a comma
+                jsr LB73D                       ; evaluate offset to X
+LA511           lda CASBUF+8                    ; get file mode
+                cmpa #2                         ; M/L program?
+                bne LA4CD                       ; brif not - FM error
+                ldd CASBUF+11                   ; get load address
+                leau D,x                        ; add in offset
+                stu EXECJP                      ; set EXEC default address
+                tst CASBUF+10                   ; is it binary?
+                bne LA4CD                       ; brif not
+                ldd CASBUF+13                   ; get load address
+                leax d,x                        ; add in offset
+                stx CBUFAD                      ; set buffer address for loading
+                jsr CASON                       ; start up tape
+LA52E           jsr GETBLK                      ; read a block
+                bne LA4FB                       ; brif error reading
+                stx CBUFAD                      ; save new load address
+                tst BLKTYP                      ; set flags on block type
+                beq LA4FB                       ; brif another header - IO error
+                bpl LA52E                       ; brif it was data - read more
+LA53B           jmp LA7E9                       ; turn off tape and return
+; The EXEC command
+EXEC            beq LA545                       ; brif no argument - use default address
+                jsr LB73D                       ; evaluate EXEC address to X
+                stx EXECJP                      ; set new default EXEC address
+LA545           jmp [EXECJP]                    ; transfer control to execution address
+; Break check for LIST so it doesn't interrupt ASCII saves. Why is this here instead of with the rest of the break
+; check logic or packaged up with LIST?
+LA549           jsr RVEC11                      ; do the RAM hook dance
+                lda DEVNUM                      ; get device number
+                inca                            ; is it tape?
+                beq LA5A1                       ; brif so - don't do break check
+                jmp LADEB                       ; do the actual break check
+; Evaluate an expression and make sure it is within the limits of the screen and sets the cursor position.
+; This really should be located with the PRINT command.
+LA554           jsr LB3E4                       ; evaluate a positive expression to D
+                subd #511                       ; is it within bounds?
+                lbhi LB44A                      ; brif not - error out
+                addd #VIDRAM+511                ; adjust to be within the screen (and undo the SUBD above)
+                std CURPOS                      ; set cursor position
+                rts
+; INKEY$ function
+INKEY           lda IKEYIM                      ; was a key down during break check?
+                bne LA56B                       ; brif so
+                jsr KEYIN                       ; poll the keyboard
+LA56B           clr IKEYIM                      ; reset the break check cache
+                sta FPA0+3                      ; store result for later return
+                lbne LB68F                      ; brif a key was down - return it as a string
+                sta STRDES                      ; set string length to 0 (no key down)
+                jmp LB69B                       ; return the NULL string
+; Parse a filename
+LA578           ldx #CFNBUF                     ; point to file name buffer
+                clr ,x+                         ; zero out file name length
+                lda #0x20                       ; space character to initialize file name
+LA57F           sta ,x+                         ; put a space in the buffer
+                cmpx #CASBUF                    ; at end of file name?
+                bne LA57F                       ; brif not
+                jsr GETCCH                      ; get input character
+                beq LA5A1                       ; brif no name present
+                jsr LB156                       ; evaluate the file name expression
+                jsr LB654                       ; point to start of the file name
+                ldu #CFNBUF                     ; point to file name buffer
+                stb ,u+                         ; save string length
+                beq LA5A1                       ; brif empty - we're done
+                skip2
+LA598           ldb #8                          ; copy 8 bytes
+; Move B bytes from (X) to (U)
+LA59A           lda ,x+                         ; copy a byte
+                sta ,u+
+                decb                            ; done yet?
+                bne LA59A                       ; brif not
+LA5A1           rts
+; Parse a device number and check validity
+LA5A2           jsr SYNCOMMA                    ; check for comma and SN error if not
+LA5A5           cmpa #'#                        ; do we have a #?
+                bne LA5AB                       ; brif not (it's optional)
+                jsr GETNCH                      ; munch the #
+LA5AB           jsr LB141                       ; evaluate the expression
+LA5AE           jsr INTCNV                      ; convert it to an integer in D
+                rolb                            ; move sign of B into C
+                adca #0                         ; add sign of B to A
+                bne LA61F                       ; brif A doesn't match the sign of B
+                rorb                            ; restore B (ADCA will have set C if B was negative)
+                stb DEVNUM                      ; set device number
+                jsr RVEC1                       ; do the RAM hook dance
+                beq LA5C4                       ; brif device number set to screen/keyboard (valid)
+                bpl LA61F                       ; brif not negative (not valid)
+                cmpb #-2                        ; is it printer or tape?
+                blt LA61F                       ; brif not (not valid)
+LA5C4           rts
+; Read file name from the line and do an error if anything follows it
+LA5C5           bsr LA578                       ; parse file name
+LA5C7           jsr GETCCH                      ; set flags on current character
+LA5C9           beq LA5C4                       ; brif nothing there - it's good
+                jmp LB277                       ; raise SN error
+; EOF function
+EOF             jsr RVEC14                      ; do the RAM hook dance
+                lda DEVNUM                      ; get device number
+                pshs a                          ; save it (so we can restore it later)
+                bsr LA5AE                       ; check the device number (which is in FPA0)
+                jsr LA3ED                       ; check validity for reading
+LA5DA           clrb                            ; not EOF = 0 (FALSE)
+                lda DEVNUM                      ; get device number
+                beq LA5E4                       ; brif keyboard - never EOF
+                tst CINCTR                      ; is there anything in the input buffer?
+                bne LA5E4                       ; brif so - not EOF
+                comb                            ; set EOF flag to -1 (true)
+LA5E4           puls a                          ; get back original device
+                sta DEVNUM                      ; restore it
+LA5E8           sex                             ; sign extend result to 16 bits
+                jmp GIVABF                      ; go return the result
+; SKIPF command
+SKIPF           bsr LA5C5                       ; parse file name
+                bsr LA648                       ; look for the file
+                jsr LA6D1                       ; read the file
+                bne LA619                       ; brif error reading file
+                rts
+; OPEN command
+OPEN            jsr RVEC0                       ; do the RAM hook dance
+                jsr LB156                       ; get file status (input/output)
+                jsr LB6A4                       ; get first character of status string
+                pshs b                          ; save status
+                bsr LA5A2                       ; parse a comma then the device number
+                jsr SYNCOMMA                    ; make sure there's a comma
+                bsr LA5C5                       ; parse the file name
+                lda DEVNUM                      ; get device number of the file
+                clr DEVNUM                      ; reset actual device to the screen
+                puls b                          ; get back status
+                cmpb #'I                        ; INPUT?
+                beq LA624                       ; brif so - open a file for INPUT
+                cmpb #'O                        ; OUTPUT?
+                beq LA658                       ; brif so - open a file for OUTPUT
+LA616           ldb #21*2                       ; raise FM error
+                skip2
+LA619           ldb #20*2                       ; raise I/O error
+                skip2
+LA61C           ldb #18*2                       ; raise AO error
+                skip2
+LA61F           ldb #19*2                       ; raise DN error
+                jmp LAC46
+LA624           inca                            ; are we opening the tape?
+                bmi LA616                       ; brif printer - FM error; printer can't be opened for READ
+                bne LA657                       ; brif screen - screen is always open
+                bsr LA648                       ; read header block
+                lda CASBUF+9                    ; clear A if binary or machine language file
+                anda CASBUF+10
+                beq LA616                       ; bad file mode if not data file
+                inc FILSTA                      ; open file for input
+LA635           jsr LA701                       ; start tape, read block           
+                bne LA619                       ; brif error during read
+                tst BLKTYP                      ; check block type
+                beq LA619                       ; brif header block - something's wrong
+                bmi LA657                       ; brif EOF
+                lda BLKLEN                      ; get length of block
+                beq LA635                       ; brif empty block - read another
+LA644           sta CINCTR                      ; set buffer count
+                bra LA652                       ; reset buffer pointer
+LA648           tst FILSTA                      ; is the file open?
+                bne LA61C                       ; brif so - AO error
+                bsr LA681                       ; search for file
+                bne LA619                       ; brif error on read
+LA650           clr CINCTR                      ; mark buffer empty
+LA652           ldx #CASBUF                     ; set buffer pointer to start of buffer
+                stx CINPTR
+LA657           rts
+LA658           inca                            ; check for tape device
+                bne LA657                       ; brif not tape (nothing doing - it's always open)
+                inca                            ; make file type 1
+LA65C           ldx #0xffff                     ; ASCII and data mode
+LA65F           tst FILSTA                      ; is file open?
+                bne LA61C                       ; brif so - raise error
+                ldu #CASBUF                     ; point to tape buffer
+                stu CBUFAD                      ; set address of block to write
+                sta 8,u                         ; set file type
+                stx 9,u                         ; set ASCII flag and mode
+                ldx #CFNBUF+1                   ; point to file name
+                jsr LA598                       ; move file name to the tape buffer
+                clr BLKTYP                      ; set for header block
+                lda #15                         ; 15 bytes in a header block
+                sta BLKLEN                      ; set block length
+                jsr LA7E5                       ; write the block
+                lda #2                          ; set file type to output
+                sta FILSTA
+                bra LA650                       ; reset file pointers
+; Search for correct cassette file name
+LA681           ldx #CASBUF                     ; point to cassette buffer
+                stx CBUFAD                      ; set location to read blocks to
+LA686           lda CURLIN                      ; are we in immediate mode?
+                inca
+                bne LA696                       ; brif not
+                jsr LA928                       ; clear screen
+                ldx CURPOS                      ; get start of screen (set after clear)
+                ldb #'S                         ; for "searching"
+                stb ,x++                        ; put it on the screen
+                stx CURPOS                      ; save cursor position to be one past the search indicator
+LA696           bsr LA701                       ; read a block
+                orb BLKTYP                      ; merge error flag with block type
+                bne LA6D0                       ; brif error or not header
+                ldx #CASBUF                     ; point to block just read
+                ldu #CFNBUF+1                   ; point to the desired name
+                ldb #8                          ; compare 8 characters
+                clr ,-s                         ; set flag to "match"
+LA6A6           lda ,x+                         ; get character from just read block
+                ldy CURLIN                      ; immediate mode?
+                leay 1,y
+                bne LA6B4                       ; brif not
+                clr DEVNUM                      ; set output to screen
+                jsr PUTCHR                      ; display character
+LA6B4           suba ,u+                        ; subtract from desired file name (nonzero if no match)
+                ora ,s                          ; merge with match flag
+                sta ,s                          ; save new match flag (will be nonzero if any character differs)
+                decb                            ; done all characters?
+                bne LA6A6                       ; brif not - do another
+                lda ,s+                         ; get match flag (and set flags)
+                beq LA6CB                       ; brif we have a match
+                tst -9,u                        ; did we actually have a file name or will any file do?
+                beq LA6CB                       ; brif any file will do
+                bsr LA6D1                       ; go read past the file
+                bne LA6D0                       ; return on error
+                bra LA686                       ; keep looking
+LA6CB           lda #'F                         ; for "found"
+                bsr LA6F8                       ; put "F" on screen
+                clra                            ; set Z to indicat eno errors
+LA6D0           rts
+LA6D1           tst CASBUF+10                   ; check type of file
+                bne LA6DF                       ; brif "blocked" file
+                jsr CASON                       ; turn on tape
+LA6D9           bsr GETBLK                      ; read a block
+                bsr LA6E5                       ; error or EOF?
+                bra LA6D9                       ; read another block
+LA6DF           bsr LA701                       ; read a single block
+                bsr LA6E5                       ; error or EOF?
+                bra LA6DF                       ; read another block
+LA6E5           bne LA6ED                       ; got error reading block
+                lda BLKTYP                      ; check block type
+                nega                            ; A is 0 now if EOF
+                bmi LA700                       ; brif not end of file
+                deca                            ; clear error indicator
+LA6ED           sta CSRERR                      ; set error flag
+                leas 2,s                        ; don't return to original caller
+                bra LA705                       ; turn off motor and return
+LA6F3           lda VIDRAM                      ; get first char on screen
+                eora #0x40                      ; flip case
+LA6F8           ldb CURLIN                      ; immediate mode?
+                incb
+                bne LA700                       ; brif not
+                sta VIDRAM                      ; save flipped case character
+LA700           rts
+; Read a single block from tape (for a "blocked" file)
+LA701           bsr CASON                       ; start tape going
+                bsr GETBLK                      ; read block
+LA705           jsr LA7E9                       ; stop tape
+                ldb CSRERR                      ; get error status
+                rts
+; Read a block from tape - this does the heavy lifting
+GETBLK          orcc #0x50                      ; disable interrupts (timing is important)
+                bsr LA6F3                       ; reverse video of upper left character in direct mode
+                ldx CBUFAD                      ; point to destination buffer
+                clra                            ; reset read byte
+LA712           bsr LA755                       ; read a bit
+                rora                            ; move bit into accumulator
+                cmpa #0x3c                      ; have we synched on the start of the block data yet?
+                bne LA712                       ; brif not
+                bsr LA749                       ; read block type
+                sta BLKTYP
+                bsr LA749                       ; get block size
+                sta BLKLEN
+                adda BLKTYP                     ; accumulate checksum
+                sta CCKSUM                      ; save current checksum
+                lda BLKLEN                      ; get back count
+                sta CSRERR                      ; initialize counter; we use this since it will be ovewritten later anyway
+                beq LA73B                       ; brif empty block
+LA72B           bsr LA749                       ; read a byte
+                sta ,x                          ; save in buffer
+                cmpa ,x+                        ; make sure it wrote
+                bne LA744                       ; brif error if it didn't match
+                adda CCKSUM                     ; accumulate checksum
+                sta CCKSUM
+                dec CSRERR                      ; read all bytes?
+                bne LA72B                       ; brif not
+LA73B           bsr LA749                       ; read checksum from tape
+                suba CCKSUM                     ; does it match?
+                beq LA746                       ; brif so
+                lda #1                          ; checksum error flag
+                skip2
+LA744           lda #2                          ; non-RAM error flag
+LA746           sta CSRERR                      ; save error status
+                rts
+LA749           lda #8                          ; read 8 bits
+                sta CPULWD                      ; initialize counter
+LA74D           bsr LA755                       ; read a bit
+                rora                            ; put it into accumulator
+                dec CPULWD                      ; got all 8 bits?
+                bne LA74D                       ; brif not
+                rts
+LA755           bsr LA75D                       ; get time between transitions
+                ldb CPERTM                      ; get timer
+                decb
+                cmpb CMPMID                     ; set C if timer is below the transition point - high or 1; clear otherwise
+                rts
+LA75D           clr CPERTM                      ; reset timer
+                tst CBTPHA                      ; check which phase we synched on
+                bne LA773                       ; brif HI-LO synch
+LA763           bsr LA76C                       ; read input
+                bcs LA763                       ; brif still high
+LA767           bsr LA76C                       ; read input
+                bcc LA767                       ; brif still low
+                rts
+LA76C           inc CPERTM                      ; bump timer
+                ldb PIA1                        ; get input bit to C
+                rorb
+                rts
+LA773           bsr LA76C                       ; read input
+                bcc LA773                       ; brif still low
+LA777           bsr LA76C                       ; read output
+                bcs LA777                       ; brif still high
+                rts
+; Start tape and look for sync bytes
+CASON           orcc #0x50                      ; disable interrupts
+                bsr LA7CA                       ; turn on tape
+                clr CPULWD                      ; reset timer
+LA782           bsr LA763                       ; wait for low-high transition
+LA784           bsr LA7AD                       ; wait for it to go low again
+                bhi LA797                       ; brif in range for 1200 Hz
+LA788           bsr LA7A7                       ; wait for it to go high again
+                blo LA79B                       ; brif in range for 2400 Hz
+                dec CPULWD                      ; decrement counter (synched on low-high)
+                lda CPULWD                      ; get counter
+                cmpa #-96                       ; have we seen 96 1-0-1-0 patterns (48 0x55s)?
+LA792           bne LA782                       ; brif not - wait some more
+                sta CBTPHA                      ; save phase we synched on
+                rts
+LA797           bsr LA7A7                       ; wait for it to go high again
+                bhi LA784                       ; brif another 1200 Hz, 2 in a row, try again
+LA79B           bsr LA7AD                       ; wait for it to go low again
+                blo LA788                       ; brif another 2400 Hz; go try again for high
+                inc CPULWD                      ; bump counter
+                lda CPULWD                      ; get counter
+                suba #96                        ; set 0 if we've seen enought 0-1-0-1 patterns (0xaa)
+                bra LA792                       ; set phase and return or keep waiting
+LA7A7           clr CPERTM                      ; reset period timer
+                bsr LA767                       ; wait for high
+                bra LA7B1                       ; set flags on result
+LA7AD           clr CPERTM                      ; reset period timer
+                bsr LA777                       ; wait for low
+LA7B1           ldb CPERTM                      ; get period count
+                cmpb CMP0                       ; is it too long for 1200Hz?
+                bhi LA7BA                       ; brif so - reset counts
+                cmpb CMP1                       ; set C if 2400Hz, clear C if 1200 Hz
+                rts
+LA7BA           clr CPULWD                      ; reset sync counter (too slow or drop out)
+                rts
+; MOTOR command
+MOTOR           tfr a,b                         ; save ON/OFF
+                jsr GETNCH                      ; eat the ON/OFF token
+                cmpb #0xaa                      ; OFF?
+                beq LA7E9                       ; brif so - turn off tape
+                cmpb #0x88                      ; ON?
+                jsr LA5C9                       ; SN error if no match
+; Turn on tape
+LA7CA           lda PIA1+1                      ; get motor control value
+                ora #8                          ; turn on bit 3 (starts motor)
+                bsr LA7F0                       ; put it back (dumb but it saves a byte)
+LA7D1           ldx ZERO                        ; maximum delay timer
+LA7D3           leax -1,x                       ; count down
+                bne LA7D3                       ; brif not at 0 yet
+                rts
+; Write a synch leader to tape
+WRLDR           orcc #0x50                      ; disable interrupts
+                bsr LA7CA                       ; turn on tape
+                ldx SYNCLN                      ; get count of 0x55s to write
+LA7DE           bsr LA828                       ; write a 0x55
+                leax -1,x                       ; done?
+                bne LA7DE                       ; brif not
+                rts
+; Write sync bytes and a block, then stop tape
+LA7E5           bsr WRLDR                       ; write sync
+LA7E7           bsr SNDBLK                      ; write block
+; Turn off tape
+LA7E9           andcc #0xaf                     ; enable interrupts
+                lda PIA1+1                      ; get control register
+                anda #0xf7                      ; disable motor bit
+LA7F0           sta PIA1+1                      ; set motor enable bit
+                rts
+; Write a block to tape.
+SNDBLK          orcc #0x50                      ; disable interrupts
+                ldb BLKLEN                      ; get block size
+                stb CSRERR                      ; initialize character counter
+                lda BLKLEN                      ; initialize checksum
+                beq LA805                       ; brif empty block
+                ldx CBUFAD                      ; point to tape buffer
+LA800           adda ,x+                        ; accumulate checksum
+                decb                            ; end of block data?
+                bne LA800                       ; brif not
+LA805           adda BLKTYP                     ; accumulate block type into checksum
+                sta CCKSUM                      ; save calculated checksum
+                ldx CBUFAD                      ; point to buffer
+                bsr LA828                       ; send a 0x55
+                lda #0x3c                       ; and then a 0x3c
+                bsr LA82A
+                lda BLKTYP                      ; send block type
+                bsr LA82A
+                lda BLKLEN                      ; send block size
+                bsr LA82A
+                tsta                            ; empty block?
+                beq LA824                       ; brif so
+LA81C           lda ,x+                         ; send character from block data
+                bsr LA82A
+                dec CSRERR                      ; are we done yet?
+                bne LA81C                       ; brif not
+LA824           lda CCKSUM                      ; send checksum
+                bsr LA82A
+LA828           lda #0x55                       ; send a 0x55
+LA82A           pshs a                          ; save output byte
+                ldb #1                          ; initialize bit probe
+LA82E           lda CLSTSN                      ; get ending value of last cycle
+                sta PIA1                        ; set DA
+                ldy #LA85C                      ; point to sine wave table
+                bitb ,s                         ; is bit set?
+                bne LA848                       ; brif so - do high frequency
+LA83B           lda ,y+                         ; get next sample (use all for low frequency)
+                cmpy #LA85C+36                  ; end of table?
+                beq LA855                       ; brif so
+                sta PIA1                        ; set output sample
+                bra LA83B                       ; do another sample
+LA848           lda ,y++                        ; get next sample (use every other for high frequency)
+                cmpy #LA85C+36                  ; end of table?
+                beq LA855                       ; brif so
+                sta PIA1                        ; send output sample
+                bra LA848                       ; do another sample
+LA855           sta CLSTSN                      ; save last sample that *would* have been sent
+                lslb                            ; shift mask to next bit
+                bcc LA82E                       ; brif not done all 8 bits
+                puls a,pc                       ; get back original character and return
+; This is the sample table for the tape sine wave
+LA85C           fcb 0x82,0x92,0xaa,0xba,0xca,0xda
+                fcb 0xea,0xf2,0xfa,0xfa,0xfa,0xf2
+                fcb 0xea,0xda,0xca,0xba,0xaa,0x92
+                fcb 0x7a,0x6a,0x52,0x42,0x32,0x22
+                fcb 0x12,0x0a,0x02,0x02,0x02,0x0a
+                fcb 0x12,0x22,0x32,0x42,0x52,0x6a
+; SET command
+SET             bsr LA8C1                       ; get absolute screen position of graphics block
+                pshs x                          ; save character location
+                jsr LB738                       ; evaluate comma then expression in B
+                puls x                          ; get back character pointer
+                cmpb #8                         ; valid colour?
+                bhi LA8D5                       ; brif not
+                decb                            ; normalize colours
+                bmi LA895                       ; brif colour 0 (use current colour)
+                lda #0x10                       ; 16 patterns per colour
+                mul
+                bra LA89D                       ; go save the colour
+LA895           ldb ,x                          ; get current value
+                bpl LA89C                       ; brif not grahpic
+                andb #0x70                      ; keep only the colour
+                skip1
+LA89C           clrb                            ; reset block to all black
+LA89D           pshs b                          ; save colour
+                bsr LA90D                       ; force a )
+                lda ,x                          ; get current screen value
+                bmi LA8A6                       ; brif graphic block already
+                clra                            ; force all pixels off
+LA8A6           anda #0x0f                      ; keep only pixel data
+                ora GRBLOK                      ; set the desired pixel
+                ora ,s+                         ; merge with desired colour
+LA8AC           ora #0x80                       ; force it to be a graphic block
+                sta ,x                          ; put new block on screen
+                rts
+; RESET command
+RESET           bsr LA8C1                       ; get address of desired block
+                bsr LA90D                       ; force a )
+                clra                            ; zero block (no pixels)
+                ldb ,x                          ; is it graphics?
+                bpl LA8AC                       ; brif not - just blank the block
+                com GRBLOK                      ; invert pixel data
+                andb GRBLOK                     ; turn off the desired pixel
+                stb ,x                          ; put new pixel data on screen
+                rts
+; Parse SET/RESET/POINT coordinates except for closing )
+LA8C1           jsr LB26A                       ; make sure it starts with (
+LA8C4           jsr RVEC21                      ; do the RAM hook dance
+                jsr EVALEXPB                    ; get first coordinate
+                cmpb #63                        ; valid horizontal coordinate
+                bhi LA8D5                       ; brif out of range
+                pshs b                          ; save horizontal coordinate
+                jsr LB738                       ; look for , followed by vertical coordinate
+                cmpb #31                        ; in range for vertical?
+LA8D5           bhi LA948                       ; brif not
+                pshs b                          ; save vertical coordinate
+                lsrb                            ; divide by two (two blocks per row)
+                lda #32                         ; 32 bytes per row
+                mul                             ; now we have the offset into video RAM
+                ldx #VIDRAM                     ; point to start of screen
+                leax d,x                        ; now X points to the correct character row
+                ldb 1,s                         ; get horizontal coordinate
+                lsrb                            ; divide by two (two per character cell)
+                abx                             ; now we're pointing to the correct character cell
+                puls a,b                        ; get back coordinates (vertical in A)
+                anda #1                         ; keep only row offset of vertical
+                rorb                            ; get column offset of horizontal to C
+                rola                            ; now we have "row * 2 + col" in A
+                ldb #0x10                       ; make a bit mask (one bit left of first pixel)
+LA8EE           lsrb                            ; move mask right
+                deca                            ; at the right pixel?
+                bpl LA8EE                       ; brif not
+                stb GRBLOK                      ; save graphics block mask
+                rts
+; POINT function
+POINT           bsr LA8C4                       ; evaluate coordinates
+                ldb #0xff                       ; default colour value is -1 (not graphics)
+                lda ,x                          ; get character
+                bpl LA90A                       ; brif not graphics
+                anda GRBLOK                     ; is desired pixel set?
+                beq LA909                       ; brif not - return 0 for "black"
+                ldb ,x                          ; get graphics data
+                lsrb                            ; shift right 4 to get colour in low bits
+                lsrb
+                lsrb
+                lsrb
+                andb #7                         ; lose the graphics block bias
+LA909           incb                            ; shift colours into 1 to 8 range
+LA90A           jsr LA5E8                       ; convert B to floating point
+LA90D           jmp LB267                       ; make sure we have a ) and return
+; CLS command
+CLS             jsr RVEC22                      ; do the RAM hook dance
+LA913           beq LA928                       ; brif no colour - just do a basic screen clear
+                jsr EVALEXPB                    ; evaluate colour number
+                cmpb #8                         ; valid colour?
+                bhi LA937                       ; brif not - do the easter egg
+                tstb                            ; color 0?
+                beq LA925                       ; brif so
+                decb                            ; normalize to 0 based colour numbers
+                lda #0x10                       ; 16 blocks per colour
+                mul                             ; now we have the base code for that colour
+                orb #0x0f                       ; set all pixels
+LA925           orb #0x80                       ; make it a graphics block
+                skip2
+LA928           ldb #0x60                       ; VDG screen space character
+                ldx #VIDRAM                     ; point to start of screen
+LA92D           stx CURPOS                      ; set cursor position
+LA92F           stb ,x+                         ; blank a character
+                cmpx #VIDRAM+511                ; end of screen?
+                bls LA92F                       ; brif not
+                rts
+LA937           bsr LA928                       ; clear te screen
+                ldx #LA166-1                    ; point to the easter egg
+                jmp STRINOUT                    ; go display it
+; Evaluate an expression to B, prefixed by a comma, and do FC error if 0
+LA93F           jsr SYNCOMMA                    ; force a comma
+LA942           jsr EVALEXPB                    ; evaluate expression to B
+                tstb                            ; is it 0?
+                bne LA984                       ; brif not - return
+LA948           jmp LB44A                       ; raise FC error
+; SOUND command
+SOUND           bsr LA942                       ; evaluate frequency
+                stb SNDTON                      ; save it
+                bsr LA93F                       ; evaluate duration (after a comma)
+LA951           lda #4                          ; constant factor for duration (each increment is 1/15 of a second)
+                mul
+                std SNDDUR                      ; save length of sound (IRQ will count it down)
+                lda PIA0+3                      ; enable 60 Hz interrupt
+                ora #1
+                sta PIA0+3
+                clr ARYDIS                      ; clear array disable flag for some reason
+                bsr LA9A2                       ; connect DAC to MUX output
+                bsr LA976                       ; turn on sound
+LA964           bsr LA985                       ; store mid range output value and delay
+                lda #0xfe                       ; store high value and delay
+                bsr LA987
+                bsr LA985                       ; store mid range value and delay
+                lda #2                          ; store low value and delay
+                bsr LA987
+                ldx SNDDUR                      ; has timer expired?
+                bne LA964                       ; brif not, do another wave
+; Disable sound output
+LA974           clra                            ; bit 3 to 0 will disable output
+                skip2
+; Enable sound output
+LA976           lda #8                          ; bit 3 set to enable output
+                sta ,-s                         ; save desired value
+                lda PIA1+3                      ; get control register value
+                anda #0xf7                      ; reset value
+                ora ,s+                         ; set to desired value
+                sta PIA1+3                      ; set new sound output status
+LA984           rts
+LA985           lda #0x7e                       ; mid range value for DAC
+LA987           sta PIA1                        ; set DAC output value
+                lda SNDTON                      ; get frequency
+LA98C           inca                            ; increment it (gives shorter count with higher values, so higher frequencies work)
+                bne LA98C                       ; brif not done yet
+                rts
+; AUDIO command
+AUDIO           tfr a,b                         ; save ON/OFF token
+                jsr GETNCH                      ; munch the ON/OFF token
+                cmpb #0xaa                      ; OFF?
+                beq LA974                       ; brif so
+                subb #0x88                      ; ON?
+                jsr LA5C9                       ; do SN error if not
+                incb                            ; now B is 1 - cassette sound source
+                bsr LA9A2                       ; set MUX input to tape
+                bra LA976                       ; enable sound
+; Set MUX source to value in B
+LA9A2           ldu #PIA0+1                     ; point to PIA0 control register A
+                bsr LA9A7                       ; program bit 0 then fall through for bit 1
+LA9A7           lda ,u                          ; get control register value
+                anda #0xf7                      ; reset mux control bit
+                asrb                            ; shift desired value to C
+                bcc LA9B0                       ; brif this bit is clear
+                ora #8                          ; set the bit
+LA9B0           sta ,u++                        ; set register value and move to next register
+                rts
+; IRQ service routine
+BIRQSV          lda PIA0+3                      ; check for VSYNC interrupt
+                bpl LA9C5                       ; brif not - return. BUG: should clear HSYNC interrupt status first
+                lda PIA0+2                      ; clear VSYNC interrupt status
+LA9BB           ldx >SNDDUR                     ; are we counting down for SOUND? (force extended in case DP is modified)
+                beq LA9C5                       ; brif not
+                leax -1,x                       ; count down one tick
+                stx >SNDDUR                     ; save new count (forced extended in case DP is modified)
+LA9C5           rti
+; JOYSTK function
+JOYSTK          jsr LB70E                       ; evaluate which joystick axis is desired
+                cmpb #3                         ; valid axis?
+                lbhi LB44A                      ; brif not
+                tstb                            ; want axis 0?
+                bne LA9D4                       ; brif not
+                bsr GETJOY                      ; read axis data if axis 0
+LA9D4           ldx #POTVAL                     ; point to axis values
+                ldb FPA0+3                      ; get desired axis
+                ldb b,x                         ; get axis value
+                jmp LB4F3                       ; return value
+; Read all four joystick axes. Note that this routine will try 10 times to get a value that matches
+; the value obtained during the *previous call to this routine*. Thus, if the axis value has changed,
+; this routine will do the read *ten times* before just returning the last value. This is assininely
+; slow and probably a bug since it seems more logical to look for two matching reads in a row. Note
+; also that this routine should be using PSHS and PULS but it doesn't.
+GETJOY          bsr LA974                       ; turn off sound
+                ldx #POTVAL+4                   ; point to the end of the axis data (we'll work backwards)
+                ldb #3                          ; start with axis 3
+LA9E5           lda #10                         ; 10 tries to see if we match *the last call* to this routine
+                std ,--s                        ; save retry counter and axis number
+                bsr LA9A2                       ; set MUX for the correct axis
+LA9EB           ldd #0x4080                     ; set initial trial value to mid range and the next difference to add/subtract to half
+LA9EE           sta ,-s                         ; store the add/subtract value
+                orb #2                          ; keep rs232 output marking
+                stb PIA1                        ; set DAC output to the trial value
+                eorb #2                         ; remove RS232 output value
+                lda PIA0                        ; read the comparator
+                bmi LA9FF                       ; brif comparator output is high (DAC is lower than the axis value)
+                subb ,s                         ; subtract next bit value (split the difference toward 0)
+                skip2
+LA9FF           addb ,s                         ; add next bit value (split the different toward infinity)
+                lda ,s+                         ; get bit value back
+                lsra                            ; cut in half
+                cmpa #1                         ; have we done that last value for the DAC?
+                bne LA9EE                       ; brif not
+                lsrb                            ; normalize the axis value
+                lsrb
+                cmpb -1,x                       ; does it match the read from the last call to this routine?
+                beq LAA12                       ; brif so
+                dec ,s                          ; are we out of retries?
+                bne LA9EB                       ; brif not - try again
+LAA12           stb ,-x                         ; save new value and move pointer back
+                ldd ,s++                        ; get axis counter and clean up retry counter
+                decb                            ; move to next axis
+                bpl LA9E5                       ; brif still more axes to do
+                rts
+; This is the "bottom half" of the character fetching routines.
+BROMHK          cmpa #'9+1                      ; is it >= colon?
+                bhs LAA28                       ; brif so Z set if colon, C clear.
+                cmpa #0x20                      ; space?
+                bne LAA24                       ; brif not
+                jmp GETNCH                      ; move on to another character if space
+LAA24           suba #'0                        ; normalize ascii digit to 0-9; we already handled above digit 9
+                suba #-'0                       ; this will cause a carry for any value that was already positive
+LAA28           rts
+; Jump table for functions
+LAA29           fdb SGN                         ; SGN 0x80
+                fdb INT                         ; INT 0x81
+                fdb ABS                         ; ABS 0x82
+                fdb USRJMP                      ; USR 0x83
+                fdb RND                         ; RND 0x84
+                fdb SIN                         ; SIN 0x85
+                fdb PEEK                        ; PEEK 0x86
+                fdb LEN                         ; LEN 0x87
+                fdb STR                         ; STR$ 0x88
+                fdb VAL                         ; VAL 0x89
+                fdb ASC                         ; ASC 0x8a
+                fdb CHR                         ; CHR$ 0x8b
+                fdb EOF                         ; EOF 0x8c
+                fdb JOYSTK                      ; JOYSTK 0x8d
+                fdb LEFT                        ; LEFT$ 0x8e
+                fdb RIGHT                       ; RIGHT$ 0x8f
+                fdb MID                         ; MID$ 0x90
+                fdb POINT                       ; POINT 0x91
+                fdb INKEY                       ; INKEY$ 0x92
+                fdb MEM                         ; MEM 0x93
+; Operator precedence and jump table (binary ops except relational)
+LAA51           fcb 0x79                        ; +
+                fdb LB9C5
+                fcb 0x79                        ; -
+                fdb LB9BC
+                fcb 0x7b                        ; *
+                fdb LBACC
+                fcb 0x7b                        ; /
+                fdb LBB91
+                fcb 0x7f                        ; ^ (exponentiation)
+                fdb EXPJMP
+                fcb 0x50                        ; AND
+                fdb LB2D5
+                fcb 0x46                        ; OR
+                fdb LB2D4
+; Reserved words table for commands
+LAA66           fcs 'FOR'                       ; 0x80
+                fcs 'GO'                        ; 0x81
+                fcs 'REM'                       ; 0x82
+                fcs "'"                         ; 0x83
+                fcs 'ELSE'                      ; 0x84
+                fcs 'IF'                        ; 0x85
+                fcs 'DATA'                      ; 0x86
+                fcs 'PRINT'                     ; 0x87
+                fcs 'ON'                        ; 0x88
+                fcs 'INPUT'                     ; 0x89
+                fcs 'END'                       ; 0x8a
+                fcs 'NEXT'                      ; 0x8b
+                fcs 'DIM'                       ; 0x8c
+                fcs 'READ'                      ; 0x8d
+                fcs 'RUN'                       ; 0x8e
+                fcs 'RESTORE'                   ; 0x8f
+                fcs 'RETURN'                    ; 0x90
+                fcs 'STOP'                      ; 0x91
+                fcs 'POKE'                      ; 0x92
+                fcs 'CONT'                      ; 0x93
+                fcs 'LIST'                      ; 0x94
+                fcs 'CLEAR'                     ; 0x95
+                fcs 'NEW'                       ; 0x96
+                fcs 'CLOAD'                     ; 0x97
+                fcs 'CSAVE'                     ; 0x98
+                fcs 'OPEN'                      ; 0x99
+                fcs 'CLOSE'                     ; 0x9a
+                fcs 'LLIST'                     ; 0x9b
+                fcs 'SET'                       ; 0x9c
+                fcs 'RESET'                     ; 0x9d
+                fcs 'CLS'                       ; 0x9e
+                fcs 'MOTOR'                     ; 0x9f
+                fcs 'SOUND'                     ; 0xa0
+                fcs 'AUDIO'                     ; 0xa1
+                fcs 'EXEC'                      ; 0xa2
+                fcs 'SKIPF'                     ; 0xa3
+                fcs 'TAB('                      ; 0xa4
+                fcs 'TO'                        ; 0xa5
+                fcs 'SUB'                       ; 0xa6
+                fcs 'THEN'                      ; 0xa7
+                fcs 'NOT'                       ; 0xa8
+                fcs 'STEP'                      ; 0xa9
+                fcs 'OFF'                       ; 0xaa
+                fcs '+'                         ; 0xab
+                fcs '-'                         ; 0xac
+                fcs '*'                         ; 0xad
+                fcs '/'                         ; 0xae
+                fcs '^'                         ; 0xaf
+                fcs 'AND'                       ; 0xb0
+                fcs 'OR'                        ; 0xb1
+                fcs '>'                         ; 0xb2
+                fcs '='                         ; 0xb3
+                fcs '<'                         ; 0xb4
+; Reserved word list for functions
+LAB1A           fcs 'SGN'                       ; 0x80
+                fcs 'INT'                       ; 0x81
+                fcs 'ABS'                       ; 0x82
+                fcs 'USR'                       ; 0x83
+                fcs 'RND'                       ; 0x84
+                fcs 'SIN'                       ; 0x85
+                fcs 'PEEK'                      ; 0x86
+                fcs 'LEN'                       ; 0x87
+                fcs 'STR$'                      ; 0x88
+                fcs 'VAL'                       ; 0x89
+                fcs 'ASC'                       ; 0x8a
+                fcs 'CHR$'                      ; 0x8b
+                fcs 'EOF'                       ; 0x8c
+                fcs 'JOYSTK'                    ; 0x8d
+                fcs 'LEFT$'                     ; 0x8e
+                fcs 'RIGHT$'                    ; 0x8f
+                fcs 'MID$'                      ; 0x90
+                fcs 'POINT'                     ; 0x91
+                fcs 'INKEY$'                    ; 0x92
+                fcs 'MEM'                       ; 0x93
+; Jump table for commands
+LAB67           fdb FOR                         ; 0x80 FOR
+                fdb GO                          ; 0x81 GO
+                fdb REM                         ; 0x82 REM
+                fdb REM                         ; 0x83 '
+                fdb REM                         ; 0x84 ELSE
+                fdb IFTOK                       ; 0x85 IF
+                fdb DATA                        ; 0x86 DATA
+                fdb PRINT                       ; 0x87 PRINT
+                fdb ON                          ; 0x88 ON
+                fdb INPUT                       ; 0x89 INPUT
+                fdb ENDTOK                      ; 0x8a END
+                fdb NEXT                        ; 0x8b NEXT
+                fdb DIM                         ; 0x8c DIM
+                fdb READ                        ; 0x8d READ
+                fdb RUN                         ; 0x8e RUN
+                fdb RESTOR                      ; 0x8f RESTORE
+                fdb RETURN                      ; 0x90 RETURN
+                fdb STOP                        ; 0x91 STOP
+                fdb POKE                        ; 0x92 POKE
+                fdb CONT                        ; 0x93 CONT
+                fdb LIST                        ; 0x94 LIST
+                fdb CLEAR                       ; 0x95 CLEAR
+                fdb NEW                         ; 0x96 NEW
+                fdb CLOAD                       ; 0x97 CLOAD
+                fdb CSAVE                       ; 0x98 CSAVE
+                fdb OPEN                        ; 0x99 OPEN
+                fdb CLOSE                       ; 0x9a CLOSE
+                fdb LLIST                       ; 0x9b LLIST
+                fdb SET                         ; 0x9c SET
+                fdb RESET                       ; 0x9d RESET
+                fdb CLS                         ; 0x9e CLS
+                fdb MOTOR                       ; 0x9f MOTOR
+                fdb SOUND                       ; 0xa0 SOUND
+                fdb AUDIO                       ; 0xa1 AUDIO
+                fdb EXEC                        ; 0xa2 EXEC
+                fdb SKIPF                       ; 0xa3 SKIPF
+; Error message table
+LABAF           fcc 'NF'                        ; 0 NEXT without FOR
+                fcc 'SN'                        ; 1 Syntax error
+                fcc 'RG'                        ; 2 RETURN without GOSUB
+                fcc 'OD'                        ; 3 Out of data
+                fcc 'FC'                        ; 4 Illegal function call
+                fcc 'OV'                        ; 5 Overflow
+                fcc 'OM'                        ; 6 Out of memory
+                fcc 'UL'                        ; 7 Undefined line number
+                fcc 'BS'                        ; 8 Bad subscript
+                fcc 'DD'                        ; 9 Redimensioned array
+                fcc '/0'                        ; 10 Division by 0
+                fcc 'ID'                        ; 11 Illegal direct statement
+                fcc 'TM'                        ; 12 Type mismatch
+                fcc 'OS'                        ; 13 Out of string space
+                fcc 'LS'                        ; 14 String too long
+                fcc 'ST'                        ; 15 String formula too complex
+                fcc 'CN'                        ; 16 Can't continue
+                fcc 'FD'                        ; 17 Bad file data
+                fcc 'AO'                        ; 18 File already open
+                fcc 'DN'                        ; 19 Device number error
+                fcc 'IO'                        ; 20 Input/output error
+                fcc 'FM'                        ; 21 Bad file mode
+                fcc 'NO'                        ; 22 File not open
+                fcc 'IE'                        ; 23 Input past end of file
+                fcc 'DS'                        ; 24 Direct statement in file
+LABE1           fcn ' ERROR'
+LABE8           fcn ' IN '
+LABED           fcb 0x0d
+LABEE           fcc 'OK'
+                fcb 0x0d,0x00
+LABF2           fcb 0x0d
+                fcn 'BREAK'
+; Search stack for a FOR/NEXT stack frame. Stop search when something that isn't a FOR/NEXT
+; stack frame is found. Enter with the index variable descriptor pointer in VARDES, or NULL
+; for the first match.
+;
+; NOTE: this routine can be reworked to avoid needed two temporaries by taking advantage of the
+; 6809's registers. This requires some minor tweaks where the routine is called. Further, the
+; use of B is completely pointless and, even if B is going to be used, why is it reloaded on
+; every loop?
+LABF9           leax 4,s                        ; skip past our caller and the main command loop return address
+LABFB           ldb #18                         ; each FOR/NEXT frame is 18 bytes
+                stx TEMPTR                      ; save current search pointer
+                lda ,x                          ; get first byte of this frame
+                suba #0x80                      ; set to 0 if FOR/NEXT
+                bne LAC1A                       ; brif not FOR/NEXT (we hit the end of the stack for a GOSUB frame)
+                ldx 1,x                         ; get index variable descriptor
+                stx TMPTR1                      ; save it
+                ldx VARDES                      ; get desired index descriptor
+                beq LAC16                       ; brif NULL - we found something
+                cmpx TMPTR1                     ; does this one match?
+                beq LAC1A                       ; brif so
+                ldx TEMPTR                      ; get back frame pointer
+                abx                             ; move to next entry
+                bra LABFB                       ; check next block of data
+LAC16           ldx TMPTR1                      ; get index variable of this frame
+                stx VARDES                      ; set it as the one found
+LAC1A           ldx TEMPTR                      ; get matching frame pointer
+                tsta                            ; set Z if FOR/NEXT
+                rts
+; This is a block copy routine which copies from top to bottom. It's not clear that the use of
+; this routine actually saves any ROM space compared to just implementing the copies directly
+; once all the marshalling to set up the parameter variables is taken into account.
+LAC1E           bsr LAC37                       ; check to see if stack collides with D
+LAC20           ldu V41                         ; point to destination
+                leau 1,u                        ; offset for pre-dec
+                ldx V43                         ; point to source
+                leax 1,x                        ; offset for pre-dec
+LAC28           lda ,-x                         ; get source byte
+                pshu a                          ; store at destination (sta ,-u would be less weird)
+                cmpx V47                        ; at the bottom of the copy?
+                bne LAC28                       ; brif not
+                stu V45                         ; save final destination address
+LAC32           rts
+; Check for 2*B (0 <= B <= 127) bytes for free memory
+LAC33           clra                            ; zero extend
+                aslb                            ; times 2 (loses bit 7 of B)
+                addd ARYEND                     ; add to top of used memory
+LAC37           addd #STKBUF                    ; add a fudge factor for interpreter operation
+                bcs LAC44                       ; brif >65535!
+                sts BOTSTK                      ; get current stack pointer
+                cmpd BOTSTK                     ; is our new address above that?
+                blo LAC32                       ; brif not - no error
+LAC44           ldb #6*2                        ; raise OM error
+; The error servicing routine
+LAC46           jsr RVEC16                      ; do the RAM hook dance (ON ERROR reserved hook)
+LAC49           jsr RVEC17                      ; do the RAM hook dance again
+                jsr LA7E9                       ; turn off tape
+                jsr LA974                       ; disable sound
+                jsr LAD33                       ; reset stack, etc.
+                clr DEVNUM                      ; reset output to screen
+                jsr LB95C                       ; do a newline
+                jsr LB9AF                       ; send a ?
+                ldx #LABAF                      ; point to error table
+LAC60           abx                             ; offset to correct message
+                bsr LACA0                       ; send a char from X
+                bsr LACA0                       ; send another char from X
+LAC65           ldx #LABE1-1                    ; point to "ERROR" message
+LAC68           jsr STRINOUT                    ; print ERROR message (or BREAK)
+                lda CURLIN                      ; are we in immediate mode?
+                inca
+                beq LAC73                       ; brif not - go to immediate mode
+                jsr LBDC5                       ; print "IN ****"
+; This is the immediate mode loop
+LAC73           jsr LB95C                       ; do a newline if needed
+LAC76           ldx #LABEE-1                    ; point to prompt (without leading CR)
+                jsr STRINOUT                    ; show prompt
+LAC7C           jsr LA390                       ; read an input line
+                ldu #0xffff                     ; flag immediate mode
+                stu CURLIN
+                bcs LAC7C                       ; brif we ended on BREAK - just go for another line
+                tst CINBFL                      ; EOF?
+                lbne LA4BF                      ; brif so
+                stx CHARAD                      ; save start of input line as input pointer
+                jsr GETNCH                      ; get character from input line
+                beq LAC7C                       ; brif no input
+                bcs LACA5                       ; brif numeric - adding or removing a line number
+                ldb #2*24                       ; code for "direct statement in file"
+                tst DEVNUM                      ; keyboard input?
+                bne LAC46                       ; brif not - complain about direct statement
+                jsr LB821                       ; go tokenize the input line
+LAC9D           jmp LADC0                       ; go execute the newly tokenized line
+LACA0           lda ,x+                         ; get character and advance pointer
+                jmp LB9B1                       ; output it
+LACA5           jsr LAF67                       ; convert line number to binary
+LACA8           ldx BINVAL                      ; get converted number
+                stx LINHDR                      ; put it before the line we just read
+                jsr LB821                       ; tokenize the input line
+                stb TMPLOC                      ; save line length
+                bsr LAD01                       ; find where the line should be in the program
+                bcs LACC8                       ; brif the line number isn't already present
+                ldd V47                         ; get address where the line is in the program
+                subd ,x                         ; get the difference between here and the end of the line (negative)
+                addd VARTAB                     ; subtract line length from the end of the program
+                std VARTAB                      ; save new end of program address
+                ldu ,x                          ; get start of next line
+LACC0           pulu a                          ; get source byte (lda ,u+ would be less weird)
+                sta ,x+                         ; move it down
+                cmpx VARTAB                     ; have we moved everything yet?
+                bne LACC0                       ; brif not
+LACC8           lda LINBUF                      ; see if there is actually a line to input
+                beq LACE9                       ; brif not - we just needed to remove the line
+                ldd VARTAB                      ; get current end of program
+                std V43                         ; set as source pointer
+                addb TMPLOC                     ; add in the length of the new line
+                adca #0
+                std V41                         ; save destination pointer
+                jsr LAC1E                       ; make sure there's enough room and then make a hole for the new line
+                ldu #LINHDR-2                   ; point to the line (well, 4 bytes before it, incl line number and fake next line pointer)
+LACDD           pulu a                          ; get byte from new line (lda ,u+ would be less weird)
+                sta ,x+                         ; stow it
+                cmpx V45                        ; at the end of the hole we just made?
+                bne LACDD                       ; brif not
+                ldx V41                         ; get save new top of program address
+                stx VARTAB
+LACE9           bsr LAD21                       ; reset variables, etc.
+                bsr LACEF                       ; adjust next line pointers
+                bra LAC7C                       ; go read another input line
+; Recompute next line pointers
+LACEF           ldx  TXTTAB                     ; point to start of program
+LACF1           ldd ,x                          ; get address of next line
+                beq LAD16                       ; brif end of program
+                leau 4,x                        ; move past pointer and line number
+LACF7           lda ,u+                         ; are we at the end of the line?
+                bne LACF7                       ; brif not
+                stu ,x                          ; save new next line pointer
+                ldx ,x                          ; point to next line
+                bra LACF1                       ; process the next line
+; Find a line in the program
+LAD01           ldd BINVAL                      ; get desired line number
+                ldx TXTTAB                      ; point to start of program
+LAD05           ldu ,x                          ; get address of next line
+                beq LAD12                       ; brif end of program
+                cmpd 2,x                        ; do we have a match?
+                bls LAD14                       ; brif our search number is <= the number here
+                ldx ,x                          ; move to next line
+                bra LAD05                       ; check another line
+LAD12           orcc #1                         ; set C for not found
+LAD14           stx V47                         ; save address of matching line *or* line just after where it would have been
+LAD16           rts
+; NEW command
+; This routine has multiple entry points used for various "levels" of NEW
+NEW             bne LAD14                       ; brif there was input given; should be LAD16!
+LAD19           ldx TXTTAB                      ; point to start of program
+                clr ,x+                         ; blank out program (with NULL next line pointer)
+                clr ,x+
+                stx VARTAB                      ; save end of program
+LAD21           ldx TXTTAB                      ; get start of program
+                jsr LAEBB                       ; put input pointer there
+LAD26           ldx MEMSIZ                      ; reset string space
+                stx STRTAB
+                jsr RESTOR                      ; reset DATA pointer
+                ldx VARTAB                      ; clear out scalars and arrays
+                stx ARYTAB
+                stx ARYEND
+LAD33           ldx #STRSTK                     ; reset the string stack
+                stx TEMPPT
+                ldx ,s                          ; get return address (we're going to reset the stack)
+                lds FRETOP                      ; reset the stack to top of memory
+                clr ,-s                         ; put stopper so FOR/NEXT search will actually stop here
+LAD3F           clr OLDPTR                      ; reset "CONT" state
+                clr OLDPTR+1
+LAD43           clr ARYDIS                      ; un-disable arrays
+                jmp ,x                          ; return to original caller
+; FOR command
+FOR             lda #0x80                       ; disable array parsing
+                sta ARYDIS
+                jsr LET                         ; assign start value to index
+                jsr LABF9                       ; search stack for matching FOR/NEXT frame
+                leas 2,s                        ; lose return address
+                bne LAD59                       ; brif variable not already being used
+                ldx TEMPTR                      ; get address of matched data
+                leas b,x                        ; move stack pointer to the end of it (B is set to 18 in the stack search)
+LAD59           ldb #9                          ; is there room for 18 bytes in memory?
+                jsr LAC33
+                jsr LAEE8                       ; get address of the end of this statement in X
+                ldd CURLIN                      ; get line number
+                pshs x,b,a                      ; save next line address and current line number
+                ldb #0xa5                       ; make sure we have TO
+                jsr LB26F
+                jsr LB143                       ; make sure we have a numeric index
+                jsr LB141                       ; evaluate terminal condition value
+                ldb FP0SGN                      ; pack FPA0 in place
+                orb #0x7f
+                andb FPA0
+                stb FPA0
+                ldy #LAD7F                      ; where to come back to
+                jmp LB1EA                       ; stash terminal condition on the stack
+LAD7F           ldx #LBAC5                      ; point to FP 1.0 (default step)
+                jsr LBC14                       ; unpack it to FPA0
+                jsr GETCCH                      ; get character after the terminal
+                cmpa #0xa9                      ; is it STEP?
+                bne LAD90                       ; brif not
+                jsr GETNCH                      ; eat STEP
+                jsr LB141                       ; evaluate step condition
+LAD90           jsr LBC6D                       ; get "status" of FPA0
+                jsr LB1E6                       ; stash FPA0 on the stack (for step value)
+                ldd VARDES                      ; get variable descriptor pointer
+                pshs d                          ; put that on the stack too
+                lda #0x80                       ; flag the frame as a FOR/NEXT frame
+                pshs a
+; Main command interpretation loop
+LAD9E           jsr RVEC20                      ; do the RAM hook dance
+                andcc #0xaf                     ; make sure interrupts are running
+                bsr LADEB                       ; check for BREAK/pause
+                ldx CHARAD                      ; get input pointer
+                stx TINPTR                      ; save input pointer for start of line
+                lda ,x+                         ; get current input character
+                beq LADB4                       ; brif end of line - move to another line
+                cmpa #':                        ; end of statement?
+                beq LADC0                       ; brif so - keep processing
+LADB1           jmp LB277                       ; raise a syntax error
+LADB4           lda ,x++                        ; get MSB of next line pointer and skip past pointer
+                sta ENDFLG
+                beq LAE15                       ; brif MSB of next line address is 0 (do END)
+                ldd ,x+                         ; get line number but only advance one
+                std CURLIN                      ; set current line number
+                stx CHARAD                      ; set input pointer to one before line text
+LADC0           jsr GETNCH                      ; move past statement separator or to first character in line
+                bsr LADC6                       ; process a command
+LADC4           bra LAD9E                       ; handle next statement or line
+LADC6           beq LAE40                       ; return if end of statement
+                tsta                            ; is it a token?
+                lbpl LET                        ; brif not - do a LET
+                cmpa #0xa3                      ; above SKIPF?
+                bhi LADDC                       ; brif so
+                ldx COMVEC+3                    ; point to jump table
+LADD4           lsla                            ; two bytes per entry (loses the token bias)
+                tfr a,b                         ; put it in B for unsigned ABX
+                abx
+                jsr GETNCH                      ; move past token
+                jmp [,x]                        ; transfer control to the handler (which will return to the main loop)
+LADDC           cmpa #0xb4                      ; is it a non-executable token?
+                bls LADB1                       ; brif so
+                jmp [COMVEC+13]                 ; transfer control to ECB command handler
+; RESTORE command
+RESTOR          ldx TXTTAB                      ; point to beginning of the program
+                leax -1,x                       ; move back one (to compensate for "GETNCH")
+LADE8           stx DATPTR                      ; save as new data pointer
+                rts
+; BREAK check
+LADEB           jsr LA1C1                       ; read keyboard
+                beq LADFA                       ; brif no key down
+LADF0           cmpa #3                         ; BREAK?
+                beq STOP                        ; brif so - do a STOP
+LADF4           cmpa #0x13                      ; pause (SHIFT-@)?
+                beq LADFB                       ; brif so
+                sta IKEYIM                      ; cache key for later INKEY$ so break check doesn't break INKEY$
+LADFA           rts
+LADFB           jsr KEYIN                       ; read keyboard
+                beq LADFB                       ; brif no key down
+                bra LADF0                       ; process pressed key in case BREAK or SHIFT-@ again
+; END command
+ENDTOK          jsr LA426                       ; close files
+                jsr GETCCH                      ; re-get input character
+                bra LAE0B
+; STOP command
+STOP            orcc #1                         ; flag "STOP"
+LAE0B           bne LAE40                       ; brif not end of statement
+                ldx CHARAD                      ; save current input pointer
+                stx TINPTR
+LAE11           ror ENDFLG                      ; save END/STOP flag (C)
+                leas 2,s                        ; lose return address
+LAE15           ldx CURLIN                      ; get current input line (end of program comes here)
+                cmpx #0xffff                    ; immediate mode?
+                beq LAE22                       ; brif so
+                stx OLDTXT                      ; save line where we stopped executing
+                ldx TINPTR                      ; get input pointer
+                stx OLDPTR                      ; save location where we stopped executing
+LAE22           clr DEVNUM                      ; reset to screen/keyboard
+                ldx #LABF2-1                    ; point to BREAK message
+                tst ENDFLG                      ; are we doing "BREAK"?
+                lbpl LAC73                      ; brif not
+                jmp LAC68                       ; go do the BREAK message and return to main loop
+; CONT command
+CONT            bne LAE40                       ; brif not end of statement
+                ldb #2*16                       ; code for can't continue
+                ldx OLDPTR                      ; get saved execution pointer
+                lbeq LAC46                      ; brif no saved pointer - raise CN error
+                stx CHARAD                      ; reset input pointer
+                ldx OLDTXT                      ; reset current line number
+                stx CURLIN
+LAE40           rts
+; CLEAR command
+CLEAR           beq LAE6F                       ; brif no argument
+                jsr LB3E6                       ; evaluate string space size
+                pshs d                          ; save it
+                ldx MEMSIZ                      ; get memory size (top of memory)
+                jsr GETCCH                      ; is there anything after the string space size?
+                beq LAE5A                       ; brif not
+                jsr SYNCOMMA                    ; force a comma
+                jsr LB73D                       ; get top of memory value in X
+                leax -1,x                       ; move back one (top of cleared space)
+                cmpx TOPRAM                     ; is it within the memory available?
+                bhi LAE72                       ; brif higher than top of memory - OM error
+LAE5A           tfr x,d                         ; so we can do math for checking memory usage
+                subd ,s++                       ; subtract out string space value
+                bcs LAE72                       ; brif less than 0
+                tfr d,u                         ; U is bottom of cleared space
+                subd #STKBUF                    ; also account for slop space
+                bcs LAE72                       ; brif less than 0
+                subd VARTAB                     ; is there still room for the program?
+                blo LAE72                       ; brif not
+                stu FRETOP                      ; set top of free memory
+                stx MEMSIZ                      ; set size of usable memory
+LAE6F           jmp LAD26                       ; erase variables, etc.
+LAE72           jmp LAC44                       ; raise OM error
+; RUN command
+RUN             jsr RVEC18                      ; do the RAM hook dance
+                jsr LA426                       ; close any open files
+                jsr GETCCH                      ; is there a line number
+                lbeq LAD21                      ; brif no line number - start from beginning
+                jsr LAD26                       ; clear variables, etc.
+                bra LAE9F                       ; "GOTO" the line number
+; GO command (GOTO and GOSUB)
+GO              tfr a,b                         ; save TO/SUB
+LAE88           jsr GETNCH                      ; eat the TO/SUB token
+                cmpb #0xa5                      ; TO?
+                beq LAEA4                       ; brif GOTO
+                cmpb #0xa6                      ; SUB?
+                bne LAED7                       ; brif not
+                ldb #3                          ; room for 6 bytes?
+                jsr LAC33
+                ldu CHARAD                      ; get input pointer
+                ldx CURLIN                      ; get line number
+                lda #0xa6                       ; flag for GOSUB frame
+                pshs u,x,a                      ; set stack frame
+LAE9F           bsr LAEA4                       ; do "GOTO"
+                jmp LAD9E                       ; go back to main loop
+; Actual GOTO is here
+LAEA4           jsr GETCCH                      ; get current input
+                jsr LAF67                       ; convert number to binary
+                bsr LAEEB                       ; move input pointer to end of statement
+                leax 1,x                        ; point to start of next line
+                ldd BINVAL                      ; get desired line number
+                cmpd CURLIN                     ; is it beyond here?
+                bhi LAEB6                       ; brif so
+                ldx TXTTAB                      ; start search at beginning of program
+LAEB6           jsr LAD05                       ; find line number
+                bcs LAED2                       ; brif not found
+LAEBB           leax -1,x                       ; move to just before start of line
+                stx CHARAD                      ; reset input pointer
+LAEBF           rts
+; RETURN command
+RETURN          bne LAEBF                       ; exit if argument given
+                lda #0xff                       ; set VARDES to an illegal value so we ignore FOR frames
+                sta VARDES
+                jsr LABF9                       ; look for a GOSUB frame
+                tfr x,s                         ; reset stack
+                cmpa #0xa6-0x80                 ; is it a GOSUB frame?
+                beq LAEDA                       ; brif so
+                ldb #2*2                        ; code for RETURN without GOSUB
+                skip2
+LAED2           ldb #7*2                        ; code for undefined line number
+                jmp LAC46                       ; raise error
+LAED7           jmp LB277                       ; raise syntax error
+LAEDA           puls a,x,u                      ; get back saved line number and input pointer
+                stx CURLIN                      ; reset line number
+                stu CHARAD                      ; reset input pointer
+; DATA command
+DATA            bsr LAEE8                       ; move input pointer to end of statement
+                skip2
+; REM command (also ELSE)
+REM             bsr LAEEB                       ; move input pointer to end of line
+                stx CHARAD                      ; save new input pointer
+LAEE7           rts
+; Return end of statement (LAEE8) or line (AEEB) in X
+LAEE8           ldb #':                         ; colon is statement terminator
+                skip1lda
+LAEEB           clrb                            ; make main terminator NUL
+                stb CHARAC                      ; save terminator
+                clrb                            ; end of line - always terminates
+                ldx CHARAD                      ; get input pointer
+LAEF1           tfr b,a                         ; save secondary terminator
+                ldb CHARAC                      ; get main terminator
+                sta CHARAC                      ; save secondary
+LAEF7           lda ,x                          ; get input character
+                beq LAEE7                       ; brif end of line
+                pshs b                          ; save terminator
+                cmpa ,s+                        ; does it match?
+                beq LAEE7                       ; brif so - bail
+                leax 1,x                        ; move pointer ahead
+                cmpa #'"                        ; start of string?
+                beq LAEF1                       ; brif so
+                inca                            ; functon token?
+                bne LAF0C                       ; brif not
+                leax 1,x                        ; skip second part of function token
+LAF0C           cmpa #0x85+1                    ; IF?
+                bne LAEF7                       ; brif not
+                inc IFCTR                       ; bump "IF" count
+                bra LAEF7                       ; get check another input character
+; IF command
+IFTOK           jsr LB141                       ; evaluate condition
+                jsr GETCCH                      ; find out what's after the conditin
+                cmpa #0x81                      ; GO?
+                beq LAF22                       ; treat same as THEN
+                ldb #0xa7                       ; make sure we have a THEN
+                jsr LB26F
+LAF22           lda FP0EXP                      ; get true/false (false is 0)
+                bne LAF39                       ; brif condition true
+                clr IFCTR                       ; reset IF counter
+LAF28           bsr DATA                        ; skip over statement
+                tsta                            ; end of line?
+                beq LAEE7                       ; brif so
+                jsr GETNCH                      ; get start of this statement
+                cmpa #0x84                      ; ELSE?
+                bne LAF28                       ; brif not
+                dec IFCTR                       ; is it a matching ELSE?
+                bpl LAF28                       ; brif not - keep looking
+                jsr GETNCH                      ; eat the ELSE
+LAF39           jsr GETCCH                      ; get current input
+                lbcs LAEA4                      ; brif numeric - to a GOTO
+                jmp LADC6                       ; let main loop interpret the next command
+; ON command
+ON              jsr EVALEXPB                    ; evaluate index expression
+LAF45           ldb #0x81                       ; make sure we have "GO"
+                jsr LB26F
+                pshs a                          ; save TO/SUB
+                cmpa #0xa6                      ; SUB?
+                beq LAF54                       ; brif so
+                cmpa #0xa5                      ; TO?
+LAF52           bne LAED7                       ; brif not
+LAF54           dec FPA0+3                      ; are we at the right index?
+                bne LAF5D                       ; brif not
+                puls b                          ; get TO/SUB token
+                jmp LAE88                       ; go do GOTO or GOSUB
+LAF5D           jsr GETNCH                      ; munch a character
+                bsr LAF67                       ; parse line number
+                cmpa #',                        ; is there another line following?
+                beq LAF54                       ; brif so - see if we're there yet
+                puls b,pc                       ; clean up TO/SUB token and return - we fell through
+; Parse a line number
+LAF67           ldx ZERO                        ; initialize line number accumulator to 0
+                stx BINVAL
+LAF6B           bcc LAFCE                       ; brif not numeric
+                suba #'0                        ; adjust to actual value of digit
+                sta CHARAC                      ; save digit
+                ldd BINVAL                      ; get accumulated number
+                cmpa #24                        ; will this overflow?
+                bhi LAF52                       ; brif so - raise syntax error
+                aslb                            ; times 2
+                rola
+                aslb                            ; times 4
+                rola
+                addd BINVAL                     ; times 5
+                aslb                            ; times 10
+                rola
+                addb CHARAC                     ; add in digit
+                adca #0
+                std BINVAL                      ; save new accumulated number
+                jsr GETNCH                      ; fetch next character
+                bra LAF6B                       ; process next digit
+; LET command (the LET keyword requires Extended Basic)
+LET             jsr LB357                       ; evaluate destination variable
+                stx VARDES                      ; save descriptor pointer
+                ldb #0xb3                       ; make sure we have =
+                jsr LB26F
+                lda VALTYP                      ; get destination variable type
+                pshs a                          ; save it for later
+                jsr LB156                       ; evaluate the expression to assign
+                puls a                          ; get back original variable type
+                rora                            ; put type in C
+                jsr LB148                       ; make sure the current result matches the type
+                lbeq LBC33                      ; bri fnumeric - copy FPA0 to variable
+LAFA4           ldx FPA0+2                      ; point to descriptor of replacement string
+                ldd FRETOP                      ; get bottom of string space
+                cmpd 2,x                        ; is the string already in string space?
+                bhs LAFBE                       ; brif so
+                cmpx VARTAB                     ; is the descriptor in variable space?
+                blo LAFBE                       ; brif not
+LAFB1           ldb ,x                          ; get length of string
+                jsr LB50D                       ; allocate space for this string
+                ldx V4D                         ; get descriptor pointer back
+                jsr LB643                       ; copy string into string space
+                ldx #STRDES                     ; point to temporary string descriptor
+LAFBE           stx V4D                         ; save descriptor pointer
+                jsr LB675                       ; remove string from string stack if appropriate
+                ldu V4D                         ; get back replacement descriptor
+                ldx VARDES                      ; get target descriptor
+                pulu a,b,y                      ; get string length (A) and data pointer (Y)
+                sta ,x                          ; save new length
+                sty 2,x                         ; save new pointer
+LAFCE           rts
+; READ and INPUT commands.
+LAFCF           fcc '?REDO'                     ; The ?REDO message
+                fcb 0x0d,0x00
+LAFD6           ldb #2*17                       ; bad file data code
+                tst DEVNUM                      ; are we reading from the keyboard?
+                beq LAFDF                       ; brif so
+LAFDC           jmp LAC46                       ; raise the error
+LAFDF           lda INPFLG                      ; are we doing INPUT?
+                beq LAFEA                       ; brif so
+                ldx DATTXT                      ; get line number where the DATA statement happened
+                stx CURLIN                      ; set current line number to that so can report the correct location
+                jmp LB277                       ; raise a syntax error on bad data
+LAFEA           ldx #LAFCF-1                    ; show the ?REDO if we're doing INPUT
+                jsr STRINOUT
+                ldx TINPTR                      ;* reset input pointer to start of statement (this will cause the
+                stx CHARAD                      ;* INPUT statement to be re-executed
+                rts
+INPUT           ldb #11*2                       ; code for illegal direct statement
+                ldx CURLIN                      ; are we in immediate mode?
+                leax 1,x
+                beq LAFDC                       ; brif so - raise ID error
+                bsr LB002                       ; go do the INPUT thing
+                clr DEVNUM                      ; reset device to screen/keyboard
+                rts
+LB002           cmpa #'#                        ; is there a device number?
+                bne LB00F                       ; brif not
+                jsr LA5A5                       ; parse device number
+                jsr LA3ED                       ; make sure it's valid for input
+                jsr SYNCOMMA                    ; make sure we have a comma after the device number
+LB00F           cmpa #'"                        ; is there a prompt string?
+                bne LB01E                       ; brif not
+                jsr LB244                       ; parse the prompt string
+                ldb #';                         ; make sure we have a semicolon after the prompt
+                jsr LB26F
+                jsr LB99F                       ; print the prompt
+LB01E           ldx #LINBUF                     ; point to line input buffer
+                clr ,x                          ; NUL first byte to indicate no data
+                tst DEVNUM                      ; is it keyboard input?
+                bne LB049                       ; brif not
+                bsr LB02F                       ; read a line from the keyboard
+                ldb #',                         ; put a comma at the start of the buffer
+                stb ,x
+                bra LB049                       ; go process some input
+LB02F           jsr LB9AF                       ; send a ?
+                jsr LB9AC                       ; send a space
+LB035           jsr LA390                       ; read input from the keyboard
+                bcc LB03F                       ; brif not BREAK
+                leas 4,s                        ; clean up stack
+LB03C           jmp LAE11                       ; go process BREAK
+LB03F           ldb #2*23                       ; input past end of file error code
+                tst CINBFL                      ; was it EOF?
+                bne LAFDC                       ; brif so - raise the error
+                rts
+READ            ldx DATPTR                      ; fetch current DATA pointer
+                skip1lda                        ; set A to nonzero (for READ)
+LB049           clra                            ; set A to zero (for INPUT)
+                sta INPFLG                      ; record whether we're doing READ or INPUT
+                stx DATTMP                      ; save current input location
+LB04E           jsr LB357                       ; evaluate a variable (destination of data)
+                stx VARDES                      ; save descriptor
+                ldx CHARAD                      ; save interpreter input pointer
+                stx BINVAL
+                ldx DATTMP                      ; get data pointer
+                lda ,x                          ; is there anything to read?
+                bne LB069                       ; brif so
+                lda INPFLG                      ; is it INPUT?
+                bne LB0B9                       ; brif not
+                jsr RVEC10                      ; do the RAM hook dance
+                jsr LB9AF                       ; send a ? (so subsequent lines get ??)
+                bsr LB02F                       ; go read an input line
+LB069           stx CHARAD                      ; save data pointer
+                jsr GETNCH                      ; fetch next data character
+                ldb VALTYP                      ; do we want a number?
+                beq LB098                       ; brif so
+                ldx CHARAD                      ; get input pointer
+                sta CHARAC                      ; save initial character as the delimiter
+                cmpa #'"                        ; do we have a string delimiter?
+                beq LB08B                       ; brif so - use " as both delimiters
+                leax -1,x                       ; back up input if we don't have a delimiter
+                clra                            ; set delimiter to NUL (end of line)
+                sta CHARAC
+                jsr LA35F                       ; set up print parameters
+                tst PRTDEV                      ; is it a file type device?
+                bne LB08B                       ; brif so - use two NULs
+                lda #':                         ; use colon as one delimiter
+                sta CHARAC
+                lda #',                         ; and use comma as the other
+LB08B           sta ENDCHR                      ; save second terminator
+                jsr LB51E                       ; parse out the string
+                jsr LB249                       ; move input pointer past the string
+                jsr LAFA4                       ; assign the string to the variable
+                bra LB09E                       ; go see if there's more to read
+LB098           jsr LBD12                       ; parse a numeric string
+                jsr LBC33                       ; assign the numbe to the variable
+LB09E           jsr GETCCH                      ; get current input character
+                beq LB0A8                       ; brif end of line
+                cmpa #',                        ; check for comma
+                lbne LAFD6                      ; brif not - we have bad data
+LB0A8           ldx CHARAD                      ; get current data pointer
+                stx DATTMP                      ; save the data pointer
+                ldx BINVAL                      ; restore the interpreter input pointer
+                stx CHARAD
+                jsr GETCCH                      ; get current input from program
+                beq LB0D5                       ; brif end of statement
+                jsr SYNCOMMA                    ; make sure there's a comma between variables
+                bra LB04E                       ; go read another item
+LB0B9           stx CHARAD                      ; reset input pointer
+                jsr LAEE8                       ; search for end of statement
+                leax 1,x                        ; move past end of statement
+                tsta                            ; was it end of line?
+                bne LB0CD                       ; brif not
+                ldb #2*3                        ; code for out of data
+                ldu ,x++                        ; get pointer to next line
+                beq LB10A                       ; brif end of program - raise OD error
+                ldd ,x++                        ; get line number
+                std DATTXT                      ; record it for raising errors in DATA statements
+LB0CD           lda ,x                          ; do we have a DATA statement?
+                cmpa #0x86
+                bne LB0B9                       ; brif not - keep scanning
+                bra LB069                       ; go process the input
+LB0D5           ldx DATTMP                      ; get data pointer
+                ldb INPFLG                      ; were we doing READ?
+                lbne LADE8                      ; brif so - save DATA pointer
+                lda ,x                          ; is there something after the input in the input buffer?
+                beq LB0E7                       ; brif not - we consumed everything
+                ldx #LB0E8-1                    ; print the ?EXTRA IGNORED message
+                jmp STRINOUT
+LB0E7           rts
+LB0E8           fcc '?EXTRA IGNORED'
+                fcb 0x0d,0x00
+; NEXT command
+NEXT            bne LB0FE                       ; brif argument given
+                ldx ZERO                        ; set to NULL descriptor pointer
+                bra LB101                       ; go process "any index will do"
+LB0FE           jsr LB357                       ; evaluate the variable
+LB101           stx VARDES                      ; save the index we're looking for
+                jsr LABF9                       ; search the stack for the matching frame
+                beq LB10C                       ; brif we found a matching frame
+                ldb #0                          ; code for NEXT without FOR
+LB10A           bra LB153                       ; raise the error
+LB10C           tfr x,s                         ; reset the stack to the start of the stack frame
+                leax 3,x                        ; point to the STEP value
+                jsr LBC14                       ; copy the value to FPA0
+                lda 8,s                         ; get step direction
+                sta FP0SGN                      ; save as sign of FPA0
+                ldx VARDES                      ; point to index variable
+                jsr LB9C2                       ; add (X) to FPA0 (steps the index)
+                jsr LBC33                       ; save new value to the index
+                leax 9,s                        ; point to terminal condition
+                jsr LBC96                       ; compare the new index value with the terminal
+                subb 8,s                        ; set B=0 if we hit the terminal (or passed it with nonzero step)
+                beq LB134                       ; brif loop complete
+                ldx 14,s                        ; restore line number and input pointer to start of loop
+                stx CURLIN
+                ldx 16,s
+                stx CHARAD
+LB131           jmp LAD9E                       ; return to interpretation loop
+LB134           leas 18,s                       ; remove the frame from the stack
+                jsr GETCCH                      ; get character after the index
+                cmpa #',                        ; do we have more indexes?
+                bne LB131                       ; brif not
+                jsr GETNCH                      ; munch the comma
+                bsr LB0FE                       ; go process another value
+; NOTE: despite the BSR on the preceding line, execution of the NEXT command will not fall
+; through this point, nor will the stack grow without bound. The BSR is required to make sure
+; the stack is aligned properly for the stack search for the subsequent index variable.
+;
+; The following is the expression evaluation system. It has various entry points including for type
+; checking. This really consists of two co-routines, one for evaluating operators and one for individual
+; terms. However, it does some rather confusing stack operations so it's a bit difficult to follow
+; just how some of this works.
+;
+; Evaluate numeric expression
+LB141           bsr LB156                       ; evaluate an expression
+; TM error if string
+LB143           andcc #0xfe                     ; clear C to indicate we want a number
+                skip2keepc
+; TM error if numeric
+LB146           orcc #1                         ; set C to indicate we want a string
+; TM error if: C = 1 and number, OR C = 0 and string
+LB148           tst VALTYP                      ; set flags on the current value to (doesn't change C)
+                bcs LB14F                       ; brif we want a string
+                bpl LB0E7                       ; brif we have a number (we want a number)
+                skip2
+LB14F           bmi LB0E7                       ; brif we have a string (we want a string)
+LB151           ldb #12*2                       ; code for TM error
+LB153           jmp LAC46                       ; raise the error
+; The general expression evaluation entry point
+LB156           bsr LB1C6                       ; back up input pointer to compensate for GETNCH below
+LB158           clra                            ; set operator precedence to 0 (no previous operator)
+                skip2
+LB15A           pshs b                          ; save relational operator flags
+                pshs a                          ; save previous operator precedence
+                ldb #1                          ; make sure we aren't overflowing the stack
+                jsr LAC33
+                jsr LB223                       ; go evaluate the first term
+LB166           clr TRELFL                      ; flag no relational operators seen
+LB168           jsr GETCCH                      ; get input character
+LB16A           suba #0xb2                      ; token for > (lowest relational operator)
+                blo LB181                       ; brif below relational operators
+                cmpa #3                         ; there are three relational operators, is it one?
+                bhs LB181                       ; brif not
+                cmpa #1                         ; set C if >
+                rola                            ; shift C into bit 0 (4: <, 2: =, 1: >)
+                eora TRELFL                     ; flip the bit for this operator
+                cmpa TRELFL                     ; did the result get lower?
+                blo LB1DF                       ; brif so - we have a duplicate so raise an error
+                sta TRELFL                      ; save new operator flags
+                jsr GETNCH                      ; munch the operator
+                bra LB16A                       ; go see if we have another one
+LB181           ldb TRELFL                      ; do we have a relational comparison?
+                bne LB1B8                       ; brif so
+                lbcc LB1F4                      ; brif the token is above the relational operators
+                adda #7                         ; put operators starting at 0
+                bhs LB1F4                       ; brif we're above 0 - it's an operator, Jim
+                adca VALTYP                     ; add carry, numeric flag, and modified token number
+                lbeq LB60F                      ; brif we have string and A is + - do concatenation
+                adca #-1                        ; restore operator number
+                pshs a                          ; save operator number
+                asla                            ; times 2
+                adda ,s+                        ; and times 3 (3 bytes per entry)
+                ldx #LAA51                      ; point to operator pecedence and jump table
+                leax a,x                        ; point to correct entry
+LB19F           puls a                          ; get precedence of previous operation
+                cmpa ,x                         ; is hit higher (or same) than the current one?
+                bhs LB1FA                       ; brif so - we need to process that operator
+                bsr LB143                       ; TM error if we have a string
+LB1A7           pshs a                          ; save previous operation precedence
+                bsr LB1D4                       ; push operator handler address and FPA0 onto the stack
+                ldx RELPTR                      ; get pointer to arithmetic/logical table entry for last operation
+                puls a                          ; get back precedence
+                bne LB1CE                       ; brif we had a relational operation
+                tsta                            ; check precedence of previous operation
+                lbeq LB220                      ; brif end of expression
+                bra LB203                       ; go handle operation
+LB1B8           asl VALTYP                      ; get type of value to C
+                rolb                            ; mix it in to bit 0 of relational flags
+                bsr LB1C6                       ; back up input pointer
+                ldx #LB1CB                      ; point to relational operator precedence and handler
+                stb TRELFL                      ; save relational comparison flags
+                clr VALTYP                      ; result will be numeric
+                bra LB19F                       ; to process the operation
+LB1C6           ldx CHARAD                      ; get input pointer
+                jmp LAEBB                       ; back it up one and put it back
+LB1CB           fcb 0x64                        ; precedence of relational comparison
+                fdb LB2F4                       ; handler address for relational comparison
+LB1CE           cmpa ,x                         ; is last done operation higher (or same) precedence?
+                bhs LB203                       ; brif so - go process it
+                bra LB1A7                       ; go push things on the stack and process this operation otherwise
+LB1D4           ldd 1,x                         ; get address of operatorroutine
+                pshs d                          ; save it
+                bsr LB1E2                       ; push FPA0 onto the stack
+                ldb TRELFL                      ; get back relational operator flags
+                lbra LB15A                      ; go evaluate another operation
+LB1DF           jmp LB277                       ; raise a syntax error
+LB1E2           ldb FP0SGN                      ; get sign of FPA0
+                lda ,x                          ; get precedence of this operation
+LB1E6           puls y                          ; get back original caller
+                pshs b                          ; save sign
+LB1EA           ldb FP0EXP                      ; get exponent
+                ldx FPA0                        ; get mantissa
+                ldu FPA0+2
+                pshs u,x,b                      ; stow FPA0 sign and mantissa
+                jmp ,y                          ; return to caller
+LB1F4           ldx ZERO                        ; point to dummy value
+                lda ,s+                         ; get precedence of previous operation (and set flags)
+                beq LB220                       ; brif end of expression
+LB1FA           cmpa #0x64                      ; relational operation?
+                beq LB201                       ; brif so
+                jsr LB143                       ; type mismatch if string
+LB201           stx RELPTR                      ; save pointer to operator routine
+LB203           puls b                          ; get relational flags
+                cmpa #0x5a                      ; NOT operation?
+                beq LB222                       ; brif so (it was unary)
+                cmpa #0x7d                      ; unary negation?
+                beq LB222                       ; brif so
+                lsrb                            ; shift value type flag out of relational flags
+                stb RELFLG                      ; save relational operator flag
+                puls a,x,u                      ; get FP value back
+                sta FP1EXP                      ; set exponent and mantissa in FPA1
+                stx FPA1
+                stu FPA1+2
+                puls b                          ; and the sign
+                stb FP1SGN
+                eorb FP0SGN                     ; set RESSGN if the two operand signs differ
+                stb RESSGN
+LB220           ldb FP0EXP                      ; get exponent of FPA0
+LB222           rts                             ; return or transfer control to operator handler routine
+LB223           jsr RVEC15                      ; do the RAM hook dance
+                clr VALTYP                      ; set type to numeric
+                jsr GETNCH                      ; get first character in the term
+                bcc LB22F                       ; brif not numeric
+LB22C           jmp LBD12                       ; parse a number (and return)
+LB22F           jsr LB3A2                       ; set carry if not alpha
+                bcc LB284                       ; brif alpha character (variable)
+                cmpa #'.                        ; decimal point?
+                beq LB22C                       ; brif so - evaluate number
+                cmpa #0xac                      ; minus?
+                beq LB27C                       ; brif so - process unary negation
+                cmpa #0xab                      ; plus?
+                beq LB223                       ; brif so - ignore unary "posation"
+                cmpa #'"                        ; string delimiter?
+                bne LB24E                       ; brif not
+LB244           ldx CHARAD                      ; get input pointer
+                jsr LB518                       ; go parse the string
+LB249           ldx COEFPT                      ; get address of end of string
+                stx CHARAD                      ; move input pointer past string
+                rts
+LB24E           cmpa #0xa8                      ; NOT?
+                bne LB25F                       ; brif not
+                lda #0x5a                       ; precedence of unary NOT
+                jsr LB15A                       ; process the operand of NOT
+                jsr INTCNV                      ; convert to integer in D
+                coma                            ; do a bitwise complement
+                comb
+                jmp GIVABF                      ; resturn the result
+LB25F           inca                            ; is it a function token?
+                beq LB290                       ; brif so
+LB262           bsr LB26A                       ; only other legal thing must be a (expr)
+                jsr LB156                       ; evaluate parentheticized expression
+LB267           ldb #')                         ; force a )
+                skip2
+LB26A           ldb #'(                         ; force a (
+                skip2
+SYNCOMMA        ldb #',                         ; force a ,
+LB26F           cmpb [CHARAD]                   ; does character match?
+                bne LB277                       ; brif not
+                jmp GETNCH                      ; each the character and return the next
+LB277           ldb #2*1                        ; raise syntax error
+                jmp LAC46
+LB27C           lda #0x7d                       ; unary negation precedence
+                jsr LB15A                       ; evaluate argument
+                jmp LBEE9                       ; flip sign of FPA0 and return
+LB284           jsr LB357                       ; evaluate variable
+LB287           stx FPA0+2                      ; save descriptor address in FPA0
+                lda VALTYP                      ; test variable type
+                bne LB222                       ; brif string - we're done
+                jmp LBC14                       ; copy FP number from (X) into FPA0
+LB290           jsr GETNCH                      ; get the actual token number
+                tfr a,b                         ; save it (for offsetting X)
+                lslb                            ; two bytes per jump table entry (and lose high bit)
+                jsr GETNCH                      ; eat the token byte
+                cmpb #2*19                      ; is it a valid token for Color Basic?
+                bls LB29F                       ; brif so
+                jmp [COMVEC+18]                 ; transfer control to Extended Basic if not
+LB29F           pshs b                          ; save jump table offset
+                cmpb #2*14                      ; does it expect a numeric argument?
+                blo LB2C7                       ; brif so
+                cmpb #2*18                      ; does it need no arguments?
+                bhs LB2C9                       ; brif so
+                bsr LB26A                       ; force a (
+                lda ,s                          ; get token value
+                cmpa #2*17                      ; is it POINT?
+                bhs LB2C9                       ; brif so
+                jsr LB156                       ; evaluate first argument string
+                bsr SYNCOMMA                    ; force a comma
+                jsr LB146                       ; TM error if string
+                puls a                          ; get token value
+                ldu FPA0+2                      ; get string descriptor
+                pshs u,a                        ; now we save the first string argument and the token value
+                jsr EVALEXPB                    ; evaluate first numeric argument
+                puls a                          ; get back token value
+                pshs b,a                        ; save second argument and token value
+                fcb 0x8e                        ; opcode of LDX immediate (skips two bytes)
+LB2C7           bsr LB262                       ; force a (
+LB2C9           puls b                          ; get offset
+                ldx COMVEC+8                    ; get jump table pointer
+LB2CE           abx                             ; add offset into table
+                jsr [,x]                        ; go process function
+                jmp LB143                       ; make sure result is numeric
+; operator OR
+LB2D4           skip1lda                        ; set flag to nonzero to signal OR
+; operator AND
+LB2D5           clra                            ; set flag to zero to signal AND
+                sta TMPLOC                      ; save AND/OR flag
+                jsr INTCNV                      ; convert second argument to intenger
+                std CHARAC                      ; save it
+                jsr LBC4A                       ; move first argument to FPA0
+                jsr INTCNV                      ; convert first argument to integer
+                tst TMPLOC                      ; is it AND or OR?
+                bne LB2ED                       ; brif OR
+                anda CHARAC                     ; do the bitwise AND
+                andb ENDCHR
+                bra LB2F1                       ; finish up
+LB2ED           ora CHARAC                      ; do the bitwise OR
+                orb ENDCHR
+LB2F1           jmp GIVABF                      ; return integer result
+; relational comparision operators
+LB2F4           jsr LB148                       ; TM error if type mismatch
+                BNE LB309                       ; brif we have a string comparison
+                lda FP1SGN                      ; pack FPA1
+                ora #0x7f
+                anda FPA1
+                sta FPA1
+                ldx #FP1EXP                     ; point to packed FPA1
+                jsr LBC96                       ; compare FPA0 to FPA1
+                bra LB33F                       ; handle truth comparison
+LB309           clr VALTYP                      ; the result of a comparison is always a number
+                dec TRELFL                      ; remove the string flag from the comparison data
+                jsr LB657                       ; get string details for second argument
+                stb STRDES                      ; save them in the temporary string descriptor
+                stx STRDES+2
+                ldx FPA1+2                      ; get pointer to first argument descriptor
+                jsr LB659                       ; get string details for second argument
+                lda STRDES                      ; get length of second argument
+                pshs b                          ; save length of first argument
+                suba ,s+                        ; now A is the difference in string lengths
+                beq LB328                       ; brif string lengths are equal
+                lda #1                          ; flag for second argument is longer than first
+                bcc LB328                       ; brif second string is longer than first
+                ldb STRDES                      ; get length of second string (shorter)
+                nega                            ; invert default comparison result
+LB328           sta FP0SGN                      ; save default truth flag
+                ldu STRDES+2                    ; get pointer to start of second string
+                incb                            ; compensate for DECB
+LB32D           decb                            ; have we compared everything?
+                bne LB334                       ; brif not
+                ldb FP0SGN                      ; get default truth value
+                bra LB33F                       ; decide comparison truth
+LB334           lda ,x+                         ; get byte from first argument
+                cmpa ,u+                        ; compare with second argument
+                beq LB32D                       ; brif equal - keep comparing
+                ldb #0xff                       ; negative if first string is > second
+                bcc LB33F                       ; brif string A > string B
+                negb                            ; invert result
+LB33F           addb #1                         ; convert to 0,1,2
+                rolb                            ; shift left - now it's 4,2,1 for <, =, >
+                andb RELFLG                     ; keep only the truth we care about
+                beq LB348                       ; brif no matching bits - it's false
+                ldb #0xff                       ; set true
+LB348           jmp LBC7C                       ; convert result to FP and return it
+; DIM command
+LB34B           jsr SYNCOMMA                    ; make sure there's a comma between variables
+DIM             ldb #1                          ; flag that we're dimensioning
+                bsr LB35A                       ; go allocate the variable
+                jsr GETCCH                      ; are we done?
+                bne LB34B                       ; brif not
+                rts
+; This routine parses a variable. For scalars, it will return a NULL string or 0 value number
+; if it is called from "evaluate term". Otherwise, it allocates the variable. For arrays, it will
+; allocate a default sized array if dimensioning is not underway and then attempt to look up
+; the requested coordinates in that array. Otherwise, it will allocate an array based on the
+; specified dimension values.
+LB357           clrb                            ; flag that we're not setting up an array
+                jsr GETCCH
+LB35A           stb DIMFLG                      ; save dimensioning flag
+LB35C           sta VARNAM                      ; save first character of variable name
+                jsr GETCCH                      ; get input character (why? we already have it)
+                bsr LB3A2                       ; set carry if not alpha
+                lbcs LB277                      ; brif our variable doesn't start with a letter
+                clrb                            ; default second variable character to NUL
+                stb VALTYP                      ; set value type to numeric
+                jsr GETNCH                      ; get second character
+                bcs LB371                       ; brif numeric - numbers are allowed
+                bsr LB3A2                       ; set carry if not alpha
+                bcs LB37B                       ; brif not alpha
+LB371           tfr a,b                         ; save set second character of variable name
+LB373           jsr GETNCH                      ; get an input character
+                bcs LB373                       ; brif numeric - still in variable name
+                bsr LB3A2                       ; set carry if not alpha
+                bcc LB373                       ; brif alpha - still in variable name
+LB37B           cmpa #'$                        ; do we have the string sigil?
+                bne LB385                       ; brif not
+                com VALTYP                      ; set value type to string
+                addb #0x80                      ; set bit 7 of second variable character to indicate string
+                jsr GETNCH                      ; eat the sigil
+LB385           stb VARNAM+1                    ; save second variable name character
+                ora ARYDIS                      ; merge array disable flag (will set bit 7 of input character if no arrays)
+                suba #'(                        ; do we have a subscript?
+                lbeq LB404                      ; brif so
+                clr ARYDIS                      ; disable the array disable flag - it's single use
+                ldx VARTAB                      ; point to the start of the variable table
+                ldd VARNAM                      ; get variable name
+LB395           cmpx ARYTAB                     ; are we at the top of the variable table?
+                beq LB3AB                       ; brif so
+                cmpd ,x++                       ; does the variable name match (and move pointer to variable data)
+                beq LB3DC                       ; brif so
+                leax 5,x                        ; move to next table entry
+                bra LB395                       ; see if we have a match
+; Set carry if not upper case alpha
+LB3A2           cmpa #'A                        ; set C if less than A
+                bcs LB3AA                       ; brif less than A
+                suba #'Z+1                      ; set C if greater than Z
+                suba #-('Z+1)
+LB3AA           rts
+LB3AB           ldx #ZERO                       ; point to empty location (NULL/0 value)
+                ldu ,s                          ; get caller address
+                cmpu #LB287                     ; coming from "evaluate term"?
+                beq LB3DE                       ; brif so - don't allocate
+                ldd ARYEND                      ; get end of arrays
+                std V43                         ; save as top of source block
+                addd #7                         ; 7 bytes per scalar entry
+                std V41                         ; save as top of destination block
+                ldx ARYTAB                      ; get bottom of arrays
+                stx V47                         ; save as bottom of source block
+                jsr LAC1E                       ; move the arrays up to make a hole
+                ldx V41                         ; get new top of arrays
+                stx ARYEND                      ; set new end of arrays
+                ldx V45                         ; get bottom of destination block
+                stx ARYTAB                      ; set as new start of arrays
+                ldx V47                         ; get old end of variables
+                ldd VARNAM                      ; get name of variable
+                std ,x++                        ; set variable name and advance X to the value
+                clra                            ; zero out the variable value
+                clrb
+                std ,x
+                std 2,x
+                sta 4,x
+LB3DC           stx VARPTR                      ; save descriptor address of return value
+LB3DE           rts
+; Various integer conversion routines
+LB3DF           fcb 0x90,0x80,0x00,0x00,0x00    ; FP constant -32768
+LB3E4           jsr GETNCH                      ; fetch input character
+LB3E6           jsr LB141                       ; evaluate numeric expression
+LB3E9           lda FP0SGN                      ; get sign of value
+                bmi LB44A                       ; brif negative (raise FC error)
+INTCNV          jsr LB143                       ; TM error if string
+                lda FP0EXP                      ; get exponent
+                cmpa #0x90                      ; is it within the range for a 16 bit integer?
+                blo LB3FE                       ; brif smaller than 32768
+                ldx #LB3DF                      ; point to -32678 constant
+                jsr LBC96                       ; is FPA0 equal to -32768?
+                bne LB44A                       ; brif not - magnitude is too far negative
+LB3FE           jsr LBCC8                       ; move binary point to the right of FPA0 and correct sign
+                ldd FPA0+2                      ; get the resulting integer
+                rts
+LB404           ldd DIMFLG                      ; get dimensioning flag and variable type
+                pshs b,a                        ; save them (to avoid issues while evaluating dimension values)
+                nop                             ; dead space caused by 1.2 revision
+                clrb                            ; reset dimension counter
+LB40A           ldx VARNAM                      ; get variable name
+                pshs x,b                        ; save dimension counter and variable name
+                bsr LB3E4                       ; evaluate a dimension value (and skip either ( or ,)
+                puls b,x,y                      ; get variable name, dimension counter, and dimensioning/type flag
+                stx VARNAM                      ; restore variable name
+                ldu FPA0+2                      ; get dimension size/index
+                pshs u,y                        ; save dimension size and dimensioning/type flag
+                incb                            ; bump dimension counter
+                jsr GETCCH                      ; get what's after the dimension count
+                cmpa #',                        ; do we have another dimension?
+                beq LB40A                       ; brif so - parse it
+                stb TMPLOC                      ; save dimension counter
+                jsr LB267                       ; make sure we have a )
+                puls a,b                        ; get back variable type and dimensioning flag
+                std DIMFLG                      ; restore variable type and dimensioning flag
+                ldx ARYTAB                      ; get start of arrays
+LB42A           cmpx ARYEND                     ; are we at the end of the array table
+                beq LB44F                       ; brif so
+                ldd VARNAM                      ; get variable name
+                cmpd ,x                         ; does it match?
+                beq LB43B                       ; brif so
+                ldd 2,x                         ; get length of this array
+                leax d,x                        ; move to next array
+                bra LB42A                       ; go check another entry
+LB43B           ldb #2*9                        ; code for redimensioned array error
+                lda DIMFLG                      ; are we dimensioning?
+                bne LB44C                       ; brif so - raise error
+                ldb TMPLOC                      ; get number of dimensions given
+                cmpb 4,x                        ; does it match?
+                beq LB4A0                       ; brif so
+LB447           ldb #8*2                        ; raise "bad subscript"
+                skip2
+LB44A           ldb #4*2                        ; raise "illegal function call"
+LB44C           jmp LAC46                       ; raise error
+LB44F           ldd #5                          ; 5 bytes per array entry
+                std COEFPT                      ; initialize array size to entry size
+                ldd VARNAM                      ; get variable name
+                std ,x                          ; set array name
+                ldb TMPLOC                      ; get dimension count
+                stb 4,x                         ; set dimension count
+                jsr LAC33                       ; make sure we haven't overflowed memory
+                stx V41                         ; save array descriptor address
+LB461           ldb #11                         ; default dimension value (zero-based, gives max index of 10)
+                clra                            ; zero extend (??? why not LDD above?)
+                tst DIMFLG                      ; are we dimensioning?
+                beq LB46D                       ; brif not
+                puls a,b                        ; get dimension size
+                addd #1                         ; account for zero based indexing
+LB46D           std 5,x                         ; save dimension size
+                bsr LB4CE                       ; multiply by accumulated array size
+                std COEFPT                      ; save new array size
+                leax 2,x                        ; move to next dimension
+                dec TMPLOC                      ; have we done all dimensions?
+                bne LB461                       ; brif not
+                stx TEMPTR                      ; save end of array descriptor (minus 5)
+                addd TEMPTR                     ; add total size of array to address of descriptor
+                lbcs LAC44                      ; brif it overflows memory
+                tfr d,x                         ; save end of array for later
+                jsr LAC37                       ; does array fit in memory?
+                subd #STKBUF-5                  ; subtract out the "stack fudge factor" but add 5 to the result
+                std ARYEND                      ; save new end of arrays
+                clra                            ; set up for clearing
+LB48C           leax -1,x                       ; move back one
+                sta 5,x                         ; blank out a byte in the array data
+                cmpx TEMPTR                     ; have we reached the array header?
+                bne LB48C                       ; brif not
+                ldx V41                         ; get address of start of descriptor
+                lda ARYEND                      ; get MSB of end of array back (B still has LSB)
+                subd V41                        ; subtract start of descriptor
+                std 2,x                         ; save length of array in array header
+                lda DIMFLG                      ; are we dimensioning?
+                bne LB4CD                       ; brif so - we're done
+LB4A0           ldb 4,x                         ; get number of dimensions
+                stb TMPLOC                      ; initialize counter
+                clra                            ; initialize accumulated offset
+                clrb
+LB4A6           std COEFPT                      ; save accumulated offset
+                puls a,b                        ; get desired index
+                std FPA0+2                      ; save it
+                cmpd 5,x                        ; is it in range for this dimension?
+                bhs LB4EB                       ; brif not
+                ldu COEFPT                      ; get accumulated offset
+                beq LB4B9                       ; brif first dimension
+                bsr LB4CE                       ; multiply accumulated offset by dimension length
+                addd FPA0+2                     ; add in offset into this dimension
+LB4B9           leax 2,x                        ; move to next dimension in header
+                dec TMPLOC                      ; done all dimensions?
+                bne LB4A6                       ; brif not
+                std ,--s                        ; save D for multiply by 5 (should be pshs d)
+                aslb                            ; times 2
+                rola
+                aslb                            ; times 4
+                rola
+                addd ,s++                       ; times 5
+                leax d,x                        ; add in offset from start of array data
+                leax 5,x                        ; offset to end of header
+                stx VARPTR                      ; save pointer to element data
+LB4CD           rts
+; multiply 16 bit number at 5,x by the 16 bit number in COEFPT; return result in D; BS error if carry
+LB4CE           lda #16                         ; 16 shifts to do a multiply
+                sta V45                         ; save shift counter
+                ldd 5,x                         ; get multiplier
+                std BOTSTK                      ; save it
+                clra                            ; zero out product
+                clrb
+LB4D8           aslb                            ; shift product left
+                rola
+                bcs LB4EB                       ; brif we have a carry
+                asl COEFPT+1                    ; shift other factor left
+                rol COEFPT
+                bcc LB4E6                       ; brif no carry - this bit position is 0
+                addd BOTSTK                     ; add in multiplier at this bit position
+                bcs LB4EB                       ; brif carry - do an error
+LB4E6           dec V45                         ; have we done all 16 bits?
+                bne LB4D8                       ; brif not
+                rts
+LB4EB           jmp LB447                       ; raise a BS error
+; MEM function
+; BUG: this doesn't account for the STKBUF fudge factor used for memory availability checks
+MEM             tfr s,d                         ; get stack pointer where we can do math
+                subd ARYEND                     ; calculate number of bytes between the stack and the top of arrays
+                skip1                           ; return result
+; Convert unsigned value in B to FP
+LB4F3           clra                            ; zero extend
+; Convert signed value in D to FP
+GIVABF          clr VALTYP                      ; set value type to numeric
+                std FPA0                        ; save value in FPA0
+                ldb #0x90                       ; exponent for top two bytes to be an integer
+                jmp LBC82                       ; finish conversion to integer
+; STR$ function
+STR             jsr LB143                       ; make sure we have a number
+                ldu #STRBUF+2                   ; convert FP number to string in temporary string buffer
+                jsr LBDDC
+                leas 2,s                        ; don't return to the function evaluator (which will do a numeric type check)
+                ldx #STRBUF+1                   ; point to number string
+                bra LB518                       ; to stash the string in string space and return to the "evaluate term" caller
+; Reserve B bytes of string space. Return start in X and FRESPC
+LB50D           stx V4D                         ; save X somewhere in case the caller needs it
+LB50F           bsr LB56D                       ; allocate string space
+LB511           stx STRDES+2                    ; save pointer to allocated space in the temporary descriptor
+                stb STRDES                      ; save length in the temporary descriptor
+                rts
+LB516           leax -1,x                       ; move pointer back one (to compensate for the increment below)
+; Scan from X until either NUL or one of the string terminators is found
+LB518           lda #'"                         ; set terminator to be string delimiter
+LB51A           sta CHARAC                      ; set both delimiters
+                sta ENDCHR
+LB51E           leax 1,x                        ; move to next character        
+                stx RESSGN                      ; save start of string
+                stx STRDES+2                    ; save start of string in the temporary string descriptor
+                ldb #-1                         ; initialize length counter to -1 (compensate for initial INCB)
+LB526           incb                            ; bump string length
+                lda ,x+                         ; get character from string
+                beq LB537                       ; brif end of line
+                cmpa CHARAC                     ; is it delimiter #1?
+                beq LB533                       ; brif so
+                cmpa ENDCHR                     ; is it delimiter #2?
+                bne LB526                       ; brif not - keep scanning
+LB533           cmpa #'"                        ; string delimiter?
+                beq LB539                       ; brif so - don't move pointer back
+LB537           leax -1,x                       ; move pointer back (so we don't consume the delimiter)
+LB539           stx COEFPT                      ; save end of string address
+                stb STRDES                      ; save string length
+                ldu RESSGN                      ; get start of string
+                cmpu #STRBUF+2                  ; is it at the start of the string buffer?
+                bhi LB54C                       ; brif so - don't copy it to string space
+                bsr LB50D                       ; allocate string space
+                ldx RESSGN                      ; point to beginning of the string
+                jsr LB645                       ; copy string data (B bytes) from (X) to (FRESPC)
+; Put temporary string descriptor on the string stack
+LB54C           ldx TEMPPT                      ; get top of string stack
+                cmpx #CFNBUF                    ; is the string stack full?
+                bne LB558                       ; brif not
+                ldb #15*2                       ; code for "string formula too complex"
+LB555           jmp LAC46                       ; raise error
+LB558           lda STRDES                      ; get string length
+                sta 0,x                         ; save it in the string stack descriptor
+                ldd STRDES+2                    ; get string data pointer
+                std 2,x                         ; save in string stack descriptor
+                lda #0xff                       ; set value type to string
+                sta VALTYP
+                stx LASTPT                      ; set pointer to last used entry on the string stack
+                stx FPA0+2                      ; set pointer to descriptor in the current evaluation value
+                leax 5,x                        ; advance string stack pointer
+                stx TEMPPT
+                rts
+; Reserve B bytes in string space. If there isn't enough space, try compacting string space and
+; then try the allocation again. If it still fails, raise OS error.
+LB56D           clr GARBFL                      ; flag that compaction not yet done
+LB56F           clra                            ; zero extend the length
+                pshs d                          ; save requested string length
+                ldd STRTAB                      ; get current bottom of strings
+                subd ,s+                        ; calculate new bottom of strings and remove zero extension
+                cmpd FRETOP                     ; does the string fit?
+                blo LB585                       ; brif not - try compaction
+                std STRTAB                      ; save new bottom of strings
+                ldx STRTAB                      ; get bottom of strings
+                leax 1,x                        ; now X points to the real start of the allocated space
+                stx FRESPC                      ; save the string pointer
+                puls b,pc                       ; restore length and return
+LB585           ldb #2*13                       ; code for out of string space
+                com GARBFL                      ; have we compacted string space yet?
+                beq LB555                       ; brif so - raise error
+                bsr LB591                       ; compact string space
+                puls b                          ; get back string length
+                bra LB56F                       ; go try allocation again
+; Compact string space
+; This is an O(n^2) algorithm. It first searches all extant strings for the highest address data pointer
+; that hasn't already been moved into the freshly compacted string space. If then moves that string data
+; up to the highest address it can go to. It repeats this process over and over until it finds no string
+; that isn't already in the compacted space. While doing this, it has to search all strings on the string
+; stack (this is why the string stack is needed - so we can track anonymous strings), all scalar string
+; variables, and *every* entry in every string array.
+LB591           ldx MEMSIZ                      ; get to of string space
+LB593           stx STRTAB                      ; save top of uncompacted stringspace
+                clra                            ; zero out D and reset pointer to discovered variable to NULL
+                clrb
+                std V4B
+                ldx FRETOP                      ; point to bottom of string space
+                stx V47                         ; save as lowest match address (match will be higher)
+                ldx #STRSTK                     ; point to start of string stack
+LB5A0           cmpx TEMPPT                     ; are we at the top of the string stack?
+                beq LB5A8                       ; brif so - done with the string stack
+                bsr LB5D8                       ; check for string in uncompacted space (and advance pointer)
+                bra LB5A0                       ; check another on the string stack
+LB5A8           ldx VARTAB                      ; point to start of scalar variables
+LB5AA           cmpx ARYTAB                     ; end of scalars?
+                beq LB5B2                       ; brif so
+                bsr LB5D2                       ; check for string in uncompacted space and advance pointer
+                bra LB5AA                       ; check another variable
+LB5B2           stx V41                         ; save address of end of variables (address of first array)
+LB5B4           ldx V41                         ; get start of the next array
+LB5B6           cmpx ARYEND                     ; end of arrays?
+                beq LB5EF                       ; brif so
+                ldd 2,x                         ; get length of array
+                addd V41                        ; add to start of array
+                std V41                         ; save address of next array
+                lda 1,x                         ; get second character of variable name
+                bpl LB5B4                       ; brif numeric
+                ldb 4,x                         ; get number of dimensions
+                aslb                            ; two bytes per dimension size
+                addb #5                         ; add in fixed overhead for array descriptor
+                abx                             ; now X points to first array element
+LB5CA           cmpx V41                        ; at the start of the next array?
+                beq LB5B6                       ; brif so - go handle another array
+                bsr LB5D8                       ; check for string in uncompacted space (and advance pointer)
+                bra LB5CA                       ; process next array element
+LB5D2           lda 1,x                         ; get second character of variable name
+                leax 2,x                        ; move to variable data
+                bpl LB5EC                       ; brif numeric
+LB5D8           ldb ,x                          ; get length of string
+                beq LB5EC                       ; brif NULL - don't need to check data pointer
+                ldd 2,x                         ; get data pointer
+                cmpd STRTAB                     ; is it in compacted string space?
+                bhi LB5EC                       ; brif so
+                cmpd V47                        ; is it better match than previous best?
+                bls LB5EC                       ; brif not
+                stx V4B                         ; save descriptor address of best match
+                std V47                         ; save new best data pointer match
+LB5EC           leax 5,x                        ; move to next descriptor
+LB5EE           rts
+LB5EF           ldx V4B                         ; get descriptor address of the matched string
+                beq LB5EE                       ; brif we didn't find one - we're done
+                clra                            ; zero extend length
+                ldb ,x                          ; get string length
+                decb                            ; subtract one (we won't have a NULL string here)
+                addd V47                        ; now D points to the address of the end of the string data
+                std V43                         ; save as top address of move
+                ldx STRTAB                      ; set top of uncompacted space as destination
+                stx V41
+                jsr LAC20                       ; move string to top of uncompactedspace
+                ldx V4B                         ; point to string descriptor
+                ldd V45                         ; get new data pointer address
+                std 2,x                         ; update descriptor
+                ldx V45                         ; get bottom of copy destination
+                leax -1,x                       ; move back below it
+                jmp LB593                       ; go search for another string to move (and set new bottom of string space)
+; Concatenate two strings. We come here directly from the operator handler rather than via a JSR.
+LB60F           ldd FPA0+2                      ; get string descriptor for the first string
+                pshs d                          ; save it
+                jsr LB223                       ; evaluate a second string (concatenation is left associative)
+                jsr LB146                       ; make sure we have a string
+                puls x                          ; get back first string descriptor
+                stx RESSGN                      ; save it
+                ldb ,x                          ; get length of first string
+                ldx FPA0+2                      ; get pointer to second string
+                addb ,x                         ; add length of second string
+                bcc LB62A                       ; brif combined length is OK
+                ldb #2*14                       ; raise string too long error
+                jmp LAC46
+LB62A           jsr LB50D                       ; reserve room for new string
+                ldx RESSGN                      ; get descriptor address of the first string
+                ldb ,x                          ; get length of first string
+                bsr LB643                       ; copy it to string space
+                ldx V4D                         ; get descriptor address of second string
+                bsr LB659                       ; get string details for second string
+                bsr LB645                       ; copy second string into new string space
+                ldx RESSGN                      ; get pointer to first string
+                bsr LB659                       ; remove it from the string stack if possible
+                jsr LB54C                       ; put new string on the string stack
+                jmp LB168                       ; return to expression evaluator
+; Copy B bytes to space pointed to by FRESPC
+LB643           ldx 2,x                         ; get source address from string descriptor
+LB645           ldu FRESPC                      ; get destination address
+                incb                            ; compensate for decb
+                bra LB64E                       ; do the copy
+LB64A           lda ,x+                         ; copy a byte
+                sta ,u+
+LB64E           decb                            ; done yet?
+                bne LB64A                       ; brif not
+                stu FRESPC                      ; save destination pointer
+                rts
+; Fetch details of string in FPA0+2 and remove from the string stack if possible
+LB654           jsr LB146                       ; make sure we have a string
+LB657           ldx FPA0+2                      ; get descriptor pointer
+LB659           ldb ,x                          ; get length of string
+                bsr LB675                       ; see if it's at the top of the string stack and remove it if so
+                bne LB672                       ; brif not removed
+                ldx 5+2,x                       ; get start address of string just removed
+                leax -1,x                       ; move pointer down 1
+                cmpx STRTAB                     ; is it at the bottom of string space?
+                bne LB66F                       ; brif not
+                pshs b                          ; save length
+                addd STRTAB                     ; add length to start of strings (A was cleared previously)
+                std STRTAB                      ; save new string space start (deallocated space for this string)
+                puls b                          ; get back string length
+LB66F           leax 1,x                        ; restore pointer to pointing at the actual string data
+                rts
+LB672           ldx 2,x                         ; get data pointer for the string
+                rts
+; Remove string pointed to by X from the string stack if it is at the top of the stack; return with
+; A clear and Z set if string removed
+LB675           cmpx LASTPT                     ; is it at the top of the string stack?
+                bne LB680                       ; brif not - do nothing
+                stx TEMPPT                      ; save new top of stack
+                leax -5,x                       ; move the "last" pointer back as well
+                stx LASTPT
+                clra                            ; flag string removed
+LB680           rts
+; LEN function
+LEN             bsr LB686                       ; get string details
+LB683           jmp LB4F3                       ; return unsigned length in B
+LB686           bsr LB654                       ; get string details and remove from string stack
+                clr VALTYP                      ; set value type to numeric
+                tstb                            ; set flags according to length
+                rts
+; CHR$ function
+CHR             jsr LB70E                       ; get 8 bit unsigned integer to B
+LB68F           ldb #1                          ; allocate a one byte string
+                jsr LB56D
+                lda FPA0+3                      ; get character code
+                jsr LB511                       ; save reserved string details in temp descriptor
+                sta ,x                          ; put character in string
+LB69B           leas 2,s                        ; don't go back to function handler - avoid numeric type check
+LB69D           jmp LB54C                       ; return temporary string on string stack
+; ASC function
+ASC             bsr LB6A4                       ; get first character of argument
+                bra LB683                       ; return unsigned code in B
+LB6A4           bsr LB686                       ; fetch string details
+                beq LB706                       ; brif NULL string
+                ldb ,x                          ; get character at start of string
+                rts
+; LEFT$ function
+LEFT            bsr LB6F5                       ; get arguments from the stack
+LB6AD           clra                            ; clear pointer offset (set to start of string)
+LB6AE           cmpb ,x                         ; are we asking for more characters than there are in the string?
+                bls LB6B5                       ; brif not
+                ldb ,x                          ; only return the number that are in the string
+                clra                            ; force starting offset to be the start of the string
+LB6B5           pshs b,a                        ; save offset and length
+                jsr LB50F                       ; reserve space in string space
+                ldx V4D                         ; point to original string descriptor
+                bsr LB659                       ; get string details
+                puls b                          ; get string offset
+                abx                             ; now X points to the start of the data to copy
+                puls b                          ; get length of copy
+                jsr LB645                       ; copy the data to the allocated space
+                bra LB69D                       ; return temp string on string stack
+; RIGHT$ function
+RIGHT           bsr LB6F5                       ; get arguments from stack
+                suba ,x                         ; subtract length of original string from desired length
+                nega                            ; now A is offset into old string where we start copying
+                bra LB6AE                       ; go handle everything else
+; MID$ function
+MID             ldb #255                        ; default length is the whole string
+                stb FPA0+3                      ; save it
+                jsr GETCCH                      ; see what we have after offset
+                cmpa #')                        ; end of function?
+                beq LB6DE                       ; brif so - no length
+                jsr SYNCOMMA                    ; force a comma
+                bsr EVALEXPB                    ; get length parameter
+LB6DE           bsr LB6F5                       ; get string and offset parameters from the stack
+                beq LB706                       ; brif we have a 0 offset requested (string offsets are 1-based)
+                clrb                            ; clear length counter
+                deca                            ; subtract one from position parameter (we work on 0-based, param is 1-based)
+                cmpa ,x                         ; is start greater than length of string?
+                bhs LB6B5                       ; brif so - return NULL string
+                tfr a,b                         ; save absolute position parameter
+                subb ,x                         ; now B is postition less length
+                negb                            ; now B is amount of string to copy
+                cmpb FPA0+3                     ; is it less than the length requested?
+                bls LB6B5                       ; brif so
+                ldb FPA0+3                      ; set length to the requested length
+                bra LB6B5                       ; go finish up copying the substring
+; Common routine for LEFT$, RIGHT$, MID$ - check for ) and fetch string data and first parameter
+; from the stack. These were evaluated in the function evaluation handler. (It's not clear that doing
+; it that way is actually beneficial. However, this is what the ROM designers did, so here we are.)
+LB6F5           jsr LB267                       ; make sure we have )
+                ldu ,s                          ; get return address - we're going to mess with the stack
+                ldx 5,s                         ; get address of string descriptor
+                stx V4D                         ; save descriptor adddress
+                lda 4,s                         ; get first numeric parameter in both A and B
+                ldb 4,s
+                leas 7,s                        ; clean up stack
+                tfr u,pc                        ; return to original caller
+LB706           jmp LB44A                       ; raise FC error
+; Evaluate an unsigned 8 bit expression to B
+LB709           jsr GETNCH                      ; move to next character
+EVALEXPB        jsr LB141                       ; evaluate a numeric expression
+LB70E           jsr LB3E9                       ; convert to integer in D
+                tsta                            ; are we negative or > 255?
+                bne LB706                       ; brif so - FC error
+                jmp GETCCH                      ; fetch current input character and return
+; VAL function
+VAL             jsr LB686                       ; get string details
+                lbeq LBA39                      ; brif NULL string - return 0
+                ldu CHARAD                      ; get input pointer so we can replace it later
+                stx CHARAD                      ; point interpreter at string data
+                abx                             ; calculate end address of the string
+                lda ,x                          ; get byte after the end of the string
+                pshs u,x,a                      ; save end of string address, input pointer, and character after end of string
+                clr ,x                          ; put a NUL after the string (stops the number interpreter)
+                jsr GETCCH                      ; get input character at start of string
+                jsr LBD12                       ; evaluate numeric expression in string
+                puls a,x,u                      ; get back saved character and pointers
+                sta ,x                          ; restore byte after string
+                stu CHARAD                      ; restore interpeter's input pointer
+                rts
+; Evaluate unsigned expression to BINVAL, then evaluate an unsigned expression to B
+LB734           bsr LB73D                       ; evaluate expression
+                stx BINVAL                      ; save result
+LB738           jsr SYNCOMMA                    ; make sure there's a comma
+                bra EVALEXPB                    ; evaluate unsigned expression to B
+; Evaluate unsigned expression in X
+LB73D           jsr LB141                       ; evaluate numeric expression
+LB740           lda FP0SGN                      ; is it negative?
+                bmi LB706                       ; brif so
+                lda FP0EXP                      ; get exponent
+                cmpa #0x90                      ; largest possible exponent for 16 bits
+                bhi LB706                       ; brif too large
+                jsr LBCC8                       ; move binary point to right of FPA0
+                ldx FPA0+2                      ; get resulting unsigned value
+                rts
+; PEEK function
+PEEK            bsr LB740                       ; get address to X
+                ldb ,x                          ; get the value at that address
+                jmp LB4F3                       ; return B as unsigned value
+; POKE function
+POKE            bsr LB734                       ; evaluate address and byte value
+                ldx BINVAL                      ; get address
+                stb ,x                          ; put value there
+                rts
+; LLIST command
+LLIST           ldb #-2                         ; set output device to printer
+                stb DEVNUM
+                jsr GETCCH                      ; reset flags for input character and fall through to LIST
+; LIST command
+LIST            pshs cc                         ; save zero flag (end of statement)
+                jsr LAF67                       ; parse line number
+                jsr LAD01                       ; find address of that line
+                stx LSTTXT                      ; save that address as the start of the list
+                puls cc                         ; get back ent of statement flag
+                beq LB784                       ; brif end of line - list whole program
+                jsr GETCCH                      ; are we at the end of the line (one number)?
+                beq LB789                       ; brif end of line
+                cmpa #0xac                      ; is it "-"?
+                bne LB783                       ; brif not
+                jsr GETNCH                      ; eat the "-"
+                beq LB784                       ; brif no second number - list to end of program
+                jsr LAF67                       ; evaluate the second number
+                beq LB789                       ; brif illegal number
+LB783           rts
+LB784           ldu #0xffff                     ; this will cause listing to do the entire program
+                stu BINVAL
+LB789           leas 2,s                        ; don't return to the caller - we'll jump back to the main loop
+                ldx LSTTXT                      ; get address of line to list
+LB78D           jsr LB95C                       ; do a newline if needed
+                jsr LA549                       ; do a break check
+                ldd ,x                          ; get address of next line
+                bne LB79F                       ; brif not end of program
+LB797           jsr LA42D                       ; close output file
+                clr DEVNUM                      ; reset device to screen
+                jmp LAC73                       ; go back to immediate mode
+LB79F           stx LSTTXT                      ; save new line address
+                ldd 2,x                         ; get line number of this line
+                cmpd BINVAL                     ; is it above the end line?
+                bhi LB797                       ; brif so - return
+                jsr LBDCC                       ; display line number
+                jsr LB9AC                       ; put a space after it
+                ldx LSTTXT                      ; get line address
+                bsr LB7C2                       ; detokenize the line
+                ldx [LSTTXT]                    ; get pointer to next line
+                ldu #LINBUF+1                   ; point to start of detokenized line
+LB7B9           lda ,u+                         ; get byte from detokenized line
+                beq LB78D                       ; brif end of line
+                jsr LB9B1                       ; output character
+                bra LB7B9                       ; handle next character
+; Detokenize a line from (X) to the line input buffer
+LB7C2           jsr RVEC24                      ; do the RAM hook dance
+                leax 4,x                        ; move past next line pointer and line number
+                ldy #LINBUF+1                   ; point to line input buffer (destination)
+LB7CB           lda ,x+                         ; get character from tokenized line
+                beq LB820                       ; brif end of input
+                bmi LB7E6                       ; brif it's a token
+                cmpa #':                        ; colon?
+                bne LB7E2                       ; brif not
+                ldb ,x                          ; get what's after the colon
+                cmpb #0x84                      ; ELSE?
+                beq LB7CB                       ; brif so - suppress the colon
+                cmpb #0x83                      ; '?
+                beq LB7CB                       ; brif so - suppress the colon
+                skip2
+LB7E0           lda #'!                         ; placeholder for unknown token
+LB7E2           bsr LB814                       ; stow output character
+                bra LB7CB                       ; go process another input character
+LB7E6           ldu #COMVEC-10                  ; point to command interptation table
+                cmpa #0xff                      ; is it a function?
+                bne LB7F1                       ; brif not
+                lda ,x+                         ; get function token
+                leau 5,u                        ; shift to the function half of the interpretation tables
+LB7F1           anda #0x7f                      ; remove token bias
+LB7F3           leau 10,u                       ; move to next command/function table
+                tst ,u                          ; is this table active?
+                beq LB7E0                       ; brif not - use place holder
+LB7F9           suba ,u                         ; subtract number of tokens handled by this table entry
+                bpl LB7F3                       ; brif this token isn't handled here
+                adda ,u                         ; undo extra subtraction
+                ldu 1,u                         ; get reserved word list for this table
+LB801           deca                            ; are we at the right entry?
+                bmi LB80A                       ; brif so
+LB804           tst ,u+                         ; end of entry?
+                bpl LB804                       ; brif not
+                bra LB801                       ; see if we're there yet
+LB80A           lda ,u                          ; get character from wordlist
+                bsr LB814                       ; put character in the buffer
+                tst ,u+                         ; end of word?
+                bpl LB80A                       ; brif not
+                bra LB7CB                       ; go handle another input character
+LB814           cmpy #LINBUF+LBUFMX             ; is there room?
+                bhs LB820                       ; brif not
+                anda #0x7f                      ; lose bit 7
+                sta ,y+                         ; save character in output
+                clr ,y                          ; make sure there's always a NUL terminator
+LB820           rts
+; Tokenize the line that the input pointer is pointing to; put result in the line input buffer; return
+; length in D
+LB821           jsr RVEC23                      ; do the RAM hook dance
+                ldx CHARAD                      ; get input pointer
+                ldu #LINBUF                     ; set destination pointer
+LB829           clr V43                         ; clear alpha string flag
+                clr V44                         ; clear DATA flag
+LB82D           lda ,x+                         ; get input character
+                beq LB852                       ; brif end of input
+                tst V43                         ; are we handling an alphanumeric string?
+                beq LB844                       ; brif not
+                jsr LB3A2                       ; set carry if not alpha
+                bcc LB852                       ; brif alpha
+                cmpa #'0                        ; is it below the digits?
+                blo LB842                       ; brif so
+                cmpa #'9                        ; is it within the digits?
+                bls LB852                       ; brif so
+LB842           clr V43                         ; flag that we're past the alphanumeric string
+LB844           cmpa #0x20                      ; space?
+                beq LB852                       ; brif so - keep it
+                sta V42                         ; save scan delimiter
+                cmpa #'"                        ; string delimiter?
+                beq LB886                       ; brif so - copy until another "
+                tst V44                         ; doing "DATA"?
+                beq LB86B                       ; brif not
+LB852           sta ,u+                         ; put character in output
+                beq LB85C                       ; brif end of input
+                cmpa #':                        ; colon?
+                beq LB829                       ; brif so - reset DATA and alpha string flags
+LB85A           bra LB82D                       ; go process another input character
+LB85C           clr ,u+                         ; put a double NUL at the end
+                clr ,u+
+                tfr u,d                         ; calculate length of result (includes double NUL and an extra two bytes)
+                subd #LINHDR
+                ldx #LINBUF-1                   ; point to one before the output
+                stx CHARAD                      ; set input pointer there
+                rts
+LB86B           cmpa #'?                        ; print abbreviation?
+                bne LB873                       ; brif not
+                lda #0x87                       ; token for PRINT
+                bra LB852                       ; go stash it
+LB873           cmpa #''                        ; REM abbreviation?
+                bne LB88A                       ; brif not
+                ldd #0x3a83                     ; colon plus ' token
+                std ,u++                        ; put it in the output
+LB87C           clr V42                         ; set delimiter to NUL
+LB87E           lda ,x+                         ; get input
+                beq LB852                       ; brif end of line
+                cmpa V42                        ; at the delimiter?
+                beq LB852                       ; brif so
+LB886           sta ,u+                         ; save in output
+                bra LB87E                       ; keep scanning for delimiter
+LB88A           cmpa #'0                        ; is it below digits?
+                blo LB892                       ; brif so
+                cmpa #';+1                      ; is it digit, colon, or semicolon?
+                blo LB852                       ; brif so
+LB892           leax -1,x                       ; move input pointer back one (to point at this input character)
+                pshs u,x                        ; save input and output pointers
+                clr V41                         ; set token type to 0 (command)
+                ldu #COMVEC-10                  ; point to command interpretation table
+LB89B           clr V42                         ; set token counter to 0 (0x80)
+LB89D           leau 10,u                       ; 
+                lda ,u                          ; get number of reserved words
+                beq LB8D4                       ; brif this table isn't active
+                ldy 1,u                         ; point to reserved words list
+LB8A6           ldx ,s                          ; get input pointer
+LB8A8           ldb ,y+                         ; get character from reserved word table
+                subb ,x+                        ; compare with input character
+                beq LB8A8                       ; brif exact match
+                cmpb #0x80                      ; brif it was the last character in word and exact match
+                bne LB8EA                       ; brif not
+                leas 2,s                        ; remove original input pointer from stack
+                puls u                          ; get back output pointer
+                orb V42                         ; create token value (B has 0x80 from above)
+                lda V41                         ; get token type
+                bne LB8C2                       ; brif function
+                cmpb #0x84                      ; is it ELSE?
+                bne LB8C6                       ; brif not
+                lda #':                         ; silently add a colon before ELSE
+LB8C2           std ,u++                        ; put two byte token into output
+                bra LB85A                       ; go handle more input
+LB8C6           stb ,u+                         ; save single byte token
+                cmpb #0x86                      ; DATA?
+                bne LB8CE                       ; brif not
+                inc V44                         ; set DATA flag
+LB8CE           cmpb #0x82                      ; REM?
+                beq LB87C                       ; brif so - skip over rest of line
+LB8D2           bra LB85A                       ; go handle more input
+LB8D4           ldu #COMVEC-5                   ; point to interpretation table, function style
+LB8D7           com V41                         ; invert token flag
+                bne LB89B                       ; brif we haven't already done functions
+                puls x,u                        ; restore input and output pointers
+                lda ,x+                         ; copy first character
+                sta ,u+
+                jsr LB3A2                       ; set C if not alpha
+                bcs LB8D2                       ; brif not alpha - it isn't a variable
+                com V43                         ; set alphanumeric string flag
+                bra LB8D2                       ; process more input
+LB8EA           inc V42                         ; bump token number
+                deca                            ; checked all in this table?
+                beq LB89D                       ; brif so
+                leay -1,y                       ; unconsume last compared character
+LB8F1           ldb ,y+                         ; end of entry?
+                bpl LB8F1                       ; brif not
+                bra LB8A6                       ; check next reserved word
+; PRINT command
+PRINT           beq LB958                       ; brif no argument - do a newline
+                bsr LB8FE                       ; process print options
+                clr DEVNUM                      ; reset output to screen
+                rts
+LB8FE           cmpa #'@                        ; is it PRINT @?
+                bne LB907                       ; brif not
+LB902           jsr LA554                       ; move cursor to correct location
+LB905           bra LB911                       ; handle some more
+LB907           cmpa #'#                        ; device number specified?
+                bne LB918                       ; brif not
+                jsr LA5A5                       ; parse device number
+                jsr LA406                       ; check for valid output file
+LB911           jsr GETCCH                      ; get input character
+                beq LB958                       ; brif nothing - do newline
+                jsr SYNCOMMA                    ; need comma after @ or #
+LB918           jsr RVEC9                       ; do the RAM hook boogaloo
+LB91B           beq LB965                       ; brif end of input
+LB91D           cmpa #0xa4                      ; TAB(?
+                beq LB97E                       ; brif so
+                cmpa #',                        ; comma (next tab field)?
+                beq LB966                       ; brif so
+                cmpa #';                        ; semicolon (do not advance print position)
+                beq LB997                       ; brif so
+                jsr LB156                       ; evaluate expression
+                lda VALTYP                      ; get type of value
+                pshs a                          ; save it
+                bne LB938                       ; brif string
+                jsr LBDD9                       ; convert FP number to string
+                jsr LB516                       ; parse a string and put on string stack
+LB938           bsr LB99F                       ; print string
+                puls b                          ; get back variable type
+                jsr LA35F                       ; set up print parameters
+                tst PRTDEV                      ; is it a display device?
+                beq LB949                       ; brif so
+                bsr LB958                       ; do a newline
+                jsr GETCCH                      ; get input
+                bra LB91B                       ; process more print stuff
+LB949           tstb                            ; set flags on print position
+                bne LB954                       ; brif not at start of line
+                jsr GETCCH                      ; get current input
+                cmpa #',                        ; comma?
+                beq LB966                       ; skip to next tab field if so
+                bsr LB9AC                       ; send a space
+LB954           jsr GETCCH                      ; get input character
+                bne LB91D                       ; brif not end of statement
+LB958           lda #0x0d                       ; carriage return
+                bra LB9B1                       ; send it to output
+LB95C           jsr LA35F                       ; set up print parameters
+LB95F           beq LB958                       ; brif width is 0
+                lda DEVPOS                      ; get line position
+                bne LB958                       ; brif not at start of line
+LB965           rts
+LB966           jsr LA35F                       ; set up print parameters
+                beq LB975                       ; brif line width is 0
+                ldb DEVPOS                      ; get line position
+                cmpb DEVLCF                     ; at or past last comma field?
+                blo LB977                       ; brif so
+                bsr LB958                       ; move to next line
+                bra LB997                       ; handle more stuff
+LB975           ldb DEVPOS                      ; get line position
+LB977           subb DEVCFW                     ; subtract a comma field width
+                bhs LB977                       ; brif we don't have a remainder yet
+                negb                            ; now B is number of of spaces needed
+                bra LB98E                       ; go advance
+LB97E           jsr LB709                       ; evaluate TAB distance
+                cmpa #')                        ; closing )?
+                lbne LB277                      ; brif not
+                jsr LA35F                       ; set up print parameters
+                subb DEVPOS                     ; subtract print position from desired position
+                bls LB997                       ; brif we're already past it
+LB98E           tst PRTDEV                      ; is it a display device?
+                bne LB997                       ; brif not
+LB992           bsr LB9AC                       ; output a space
+                decb                            ; done enough?
+                bne LB992                       ; brif not
+LB997           jsr GETNCH                      ; get input character
+                jmp LB91B                       ; process more items
+; cpoy string from (X-1) to output
+STRINOUT        jsr LB518                       ; parse the string
+LB99F           jsr LB657                       ; get string details
+LB9A2           incb                            ; compensate for decb
+LB9A3           decb                            ; done all of the string?
+                beq LB965                       ; brif so
+                lda ,x+                         ; get character from string
+                bsr LB9B1                       ; send to output
+                bra LB9A3                       ; go do another character
+LB9AC           lda #0x20                       ; space character
+                skip2
+LB9AF           lda #'?                         ; question mark character
+LB9B1           jmp PUTCHR                      ; output character
+; The floating point math package and related functions and operations follow from here
+; to the end of the Color Basic ROM area
+LB9B4           ldx #LBEC0                      ; point to FP constant 0.5
+                bra LB9C2                       ; add 0.5 to FPA0
+LB9B9           jsr LBB2F                       ; unpack FP data from (X) to FPA1
+; subtraction operator
+LB9BC           com FP0SGN                      ; invert sign of FPA0 (subtracting is adding the negative)
+                com RESSGN                      ; that also inverts the sign differential
+                bra LB9C5                       ; go add the negative of FPA0 to FPA1
+LB9C2           jsr LBB2F                       ; unpack FP data from (X) to FPA1
+; addition operator
+LB9C5           tstb                            ; check exponent of FPA0
+                lbeq LBC4A                      ; copy FPA1 to FPA0 if FPA0 is 0
+                ldx #FP1EXP                     ; point X to FPA1 (first operand) as the operand to denormalize
+LB9CD           tfr a,b                         ; put exponent of FPA1 into B
+                tstb                            ; is FPA1 0?
+                beq LBA3E                       ; brif exponent is 0 - no-op; adding 0 to FPA0
+                subb FP0EXP                     ; get difference in exponents - number of bits to shift the smaller mantissa
+                beq LBA3F                       ; brif exponents are equal - no need to denormalize
+                blo LB9E2                       ; brif FPA0 > FPA1
+                sta FP0EXP                      ; replace result exponent with FPA1's (FPA1 is bigger)
+                lda FP1SGN                      ; also copy sign over
+                sta FP0SGN
+                ldx #FP0EXP                     ; point to FPA0 (we need to denormalize the smaller number)
+                negb                            ; invert the difference - this is the number of bits to shift the mantissa
+LB9E2           cmpb #-8                        ; do we have to shift by a whole byte?
+                ble LBA3F                       ; brif so start by shifting whole bytes to the right
+                clra                            ; clear overflow byte
+                lsr 1,x                         ; shift high bit of mantissa right (LSR will force a zero into the high bit)
+                jsr LBABA                       ; shift remainder of mantissa right -B times
+LB9EC           ldb RESSGN                      ; get the sign flag
+                bpl LB9FB                       ; brif signs are the same (we add the mantissas then)
+                com 1,x                         ; complement the mantissa and extra precision bytes
+                com 2,x
+                com 3,x
+                com 4,x
+                coma
+                adca #0                         ; add one to A (COM sets C); this may cause a carry to enter the ADD below
+LB9FB           sta FPSBYT                      ; save extra precision byte
+                lda FPA0+3                      ; add the main mantissa bytes (and propage carry from above)
+                adca FPA1+3
+                sta FPA0+3
+                lda FPA0+2
+                adca FPA1+2
+                sta FPA0+2
+                lda FPA0+1
+                adca FPA1+1
+                sta FPA0+1
+                lda FPA0
+                adca FPA1
+                sta FPA0
+                tstb                            ; were signs the same?
+                bpl LBA5C                       ; brif so - number may have gotten bigger so normalize if needed
+LBA18           bcs LBA1C                       ; brif we had a carry - result is positive?)
+                bsr LBA79                       ; do a proper negation of FPA0 mantissa
+LBA1C           clrb                            ; clear temporary exponent accumulator
+LBA1D           lda FPA0                        ; test high byte of mantissa
+                bne LBA4F                       ; brif not 0 - we need to do bit shifting
+                lda FPA0+1                      ; shift left 8 bits
+                sta FPA0
+                lda FPA0+2
+                sta FPA0+1
+                lda FPA0+3
+                sta FPA0+2
+                lda FPSBYT
+                sta FPA0+3
+                clr FPSBYT
+                addb #8                         ; account for 8 bits shifted
+                cmpb #5*8                       ; shifted 5 bytes worth?
+                blt LBA1D                       ; brif not
+LBA39           clra                            ; zero out exponent and sign - result is 0
+LBA3A           sta FP0EXP                      ; set exponent and sign
+                sta FP0SGN
+LBA3E           rts
+LBA3F           bsr LBAAE                       ; shift FPA0 mantissa to the right
+                clrb                            ; clear carry
+                bra LB9EC                       ; get on with adding
+LBA44           incb                            ; account for one bit shift
+                asl FPSBYT                      ; shift mantissa and extra precision left
+                rol FPA0+3
+                rol FPA0+2
+                rol FPA0+1
+                rol FPA0
+LBA4F           bpl LBA44                       ; brif we haven't got a 1 in bit 7
+                lda FP0EXP                      ; get exponent of result
+                pshs b                          ; subtract shift count from exponent
+                suba ,s+
+                sta FP0EXP                      ; save adjusted exponent
+                bls LBA39                       ; brif we underflowed - set result to 0
+	skip2
+LBA5C           bcs LBA66                       ; brif mantissa overflowed
+                asl FPSBYT                      ; get bit 7 of expra precision to C (used for round off)
+                lda #0                          ; set to 0 without affecting C
+                sta FPSBYT                      ; clear out extra precision bits
+                bra LBA72                       ; go round off result
+LBA66           inc FP0EXP                      ; bump exponent (for a right shift to bring carry in)
+                beq LBA92                       ; brif we overflowed
+                ror FPA0                        ; shift carry into mantissa, shift right
+                ror FPA0+1
+                ror FPA0+2
+                ror FPA0+3
+LBA72           bcc LBA78                       ; brif no round-off needed
+                bsr LBA83                       ; add one to mantissa
+                beq LBA66                       ; brif carry - need to shift right again
+LBA78           rts
+LBA79           com FP0SGN                      ; invert sign of value
+LBA7B           com FPA0                        ; first do a one's copmlement
+                com FPA0+1
+                com FPA0+2
+                com FPA0+3
+LBA83           ldx FPA0+2                      ; add one to mantissa (after one's complement gives two's complement)
+                leax 1,x                        ; bump low word
+                stx FPA0+2
+                bne LBA91                       ; brif no carry from low word
+                ldx FPA0                        ; bump high word
+                leax 1,x
+                stx FPA0
+LBA91           rts
+LBA92           ldb #2*5                        ; code for overflow
+                jmp LAC46                       ; raise error
+LBA97           ldx #FPA2-1                     ; point to FPA2
+LBA9A           lda 4,x                         ; shift mantissa right by 8 bits
+                sta FPSBYT
+                lda 3,x
+                sta 4,x
+                lda 2,x
+                sta 3,x
+                lda 1,x
+                sta 2,x
+                lda FPCARY                      ; and handle extra precision on the left
+                sta 1,x
+LBAAE           addb #8                         ; account for 8 bits shifted
+                ble LBA9A                       ; brif more shifts needed
+                lda FPSBYT                      ; get sub byte (extra precision)
+                subb #8                         ; undo the 8 added above
+                beq LBAC4                       ; brif difference is 0
+LBAB8           asr 1,x                         ; shift mantissa and sub byte one bit (keep mantissa high bit set)
+LBABA           ror 2,x
+                ror 3,x
+                ror 4,x
+                rora
+                incb                            ; account for one shift
+                bne LBAB8                       ; brif not enought shifts yet
+LBAC4           rts
+LBAC5           fcb 0x81,0x00,0x00,0x00,0x00    ; packed FP 1.0
+LBACA           bsr LBB2F                       ; unpack FP value from (X) to FPA1
+; multiplication operator
+LBACC           beq LBB2E                       ; brif exponent of FPA0 is 0 (result is 0)
+                bsr LBB48                       ; calculate exponent of product
+LBAD0           lda #0                          ; zero out mantissa of FPA2
+                sta FPA2
+                sta FPA2+1
+                sta FPA2+2
+                sta FPA2+3
+                ldb FPA0+3                      ; multiply FPA1 by LSB of FPA0
+                bsr LBB00
+                ldb FPSBYT                      ; save extra precision byte
+                stb VAE
+                ldb FPA0+2
+                bsr LBB00                       ; again for next byte of FPA0
+                ldb FPSBYT
+                stb VAD
+                ldb FPA0+1                      ; again for next byte of FPA0
+                bsr LBB00
+                ldb FPSBYT
+                stb VAC
+                ldb FPA0                        ; and finally for the high byte
+                bsr LBB02
+                ldb FPSBYT
+                stb VAB
+                jsr LBC0B                       ; copy mantissa from FPA2 to FPA0 (result)
+                jmp LBA1C                       ; normalize
+LBB00           beq LBA97                       ; brif multiplier is 0 - just shift, don't multiply
+LBB02           coma                            ; set carry
+LBB03           lda FPA2                        ; get FPA2 MS byte
+                rorb                            ; data bit to carry; will be 0 when all shifts done
+                beq LBB2E                       ; brif 8 shifts done
+                bcc LBB20                       ; brif data bit is 0 - no addition
+                lda FPA2+3                      ; add mantissa of FPA1 and FPA2
+                adda FPA1+3
+                sta FPA2+3
+                lda FPA2+2
+                adca FPA1+2
+                sta FPA2+2
+                lda FPA2+1
+                adca FPA1+1
+                sta FPA2+1
+                lda FPA2
+                adca FPA1
+LBB20           rora                            ; shift carry into FPA2
+                sta FPA2
+                ror FPA2+1
+                ror FPA2+2
+                ror FPA2+3
+                ror FPSBYT
+                clra                            ; clear carry
+                bra LBB03
+LBB2E           rts
+; Unpack FP value from (X) to FPA1
+LBB2F           ldd 1,x                         ; copy mantissa (and sign)
+                sta FP1SGN                      ; save sign bit
+                ora #0x80                       ; make sure mantissa has bit 7 set
+                std FPA1
+                ldb FP1SGN                      ; get sign
+                eorb FP0SGN                     ; set if FPA0 sign differs
+                stb RESSGN
+                ldd 3,x                         ; copy remainder of mantissa
+                std FPA1+2
+                lda ,x                          ; and exponent
+                sta FP1EXP
+                ldb FP0EXP                      ; fetch FPA0 exponent and set flags
+                rts
+; Calculate eponent for product of FPA0 and FPA1
+LBB48           tsta                            ; is FPA1 zero?
+                beq LBB61                       ; brif so
+                adda FP0EXP                     ; add to exponent of FPA0 (this is how scientific notation works)
+                rora                            ; set V if we *don't* have an overflow
+                rola
+                bvc LBB61                       ; brif exponent too larger or small
+                adda #0x80                      ; restore the bias
+                sta FP0EXP                      ; set result exponent
+                beq LBB63                       ; brif 0 - clear FPA0
+                lda RESSGN                      ; the result sign (negative if signs differ) is the result sign
+                sta FP0SGN                      ; so set it as such
+                rts
+LBB5C           lda FP0SGN                      ; get sign of FPA0
+                coma                            ; invert sign
+                bra LBB63                       ; zero sign and exponent
+LBB61           leas 2,s                        ; don't go back to caller (mul/div) - return to previous caller
+LBB63           lbpl LBA39                      ; brif we underflowed - go zero things out
+LBB67           jmp LBA92                       ; raise overflow error
+; fast multiply by 10 - leave result in FPA0
+LBB6A           jsr LBC5F                       ; copy FPA0 to FPA1 (for addition later)
+                beq LBB7C                       ; brif exponent is 0 - it's a no-op then
+                adda #2                         ; this gives "times 4"
+                bcs LBB67                       ; raise overflow if required
+                clr RESSGN                      ; set result sign to "signs the same"
+                jsr LB9CD                       ; add FPA1 to FPA0 "times 5"
+                inc FP0EXP                      ; times 10
+                beq LBB67                       ; brif overflow
+LBB7C           rts
+LBB7D           fcb 0x84,0x20,0x00,0x00,0x00    ; packed FP constant 10.0
+; Divide by 10
+LBB82           jsr LBC5F                       ; move FPA0 to FPA1
+                ldx #LBB7D                      ; point to constant 10
+                clrb                            ; zero sign
+LBB89           stb RESSGN                      ; result will be positive or zero
+                jsr LBC14                       ; unpack constant 10 to FPA0
+                skip2                           ; fall through to division (divide FPA1 by 10)
+LBB8F           bsr LBB2F                       ; unpack FP number from (X) to FPA1
+; division operator
+LBB91           beq LBC06                       ; brif FPA0 is 0 - division by zero
+                neg FP0EXP                      ; get exponent of reciprocal of the divisor
+                bsr LBB48                       ; calculate exponent of quotient
+                inc FP0EXP                      ; bump exponent (due to division algorithm below)
+                beq LBB67                       ; brif overflow
+                ldx #FPA2                       ; point to temporary storage location
+                ldb #4                          ; do 5 bytes
+                stb TMPLOC                      ; save counter
+                ldb #1                          ; shift counter and quotient byte
+LBBA4           lda FPA0                        ; compare mantissa of FPA0 to FPA1, set C if FPA1 less
+                cmpa FPA1
+                bne LBBBD
+                lda FPA0+1
+                cmpa FPA1+1
+                bne LBBBD
+                lda FPA0+2
+                cmpa FPA1+2
+                bne LBBBD
+                lda FPA0+3
+                cmpa FPA1+3
+                bne LBBBD
+                coma                            ; set C if FPA0 = FPA1 (it "goes")
+LBBBD           tfr cc,a                        ; save "it goes" status
+                rolb                            ; rotate carry into quotient
+                bcc LBBCC                       ; brif carry clear - haven't done 8 shifts yet
+                stb ,x+                         ; save quotient byte
+                dec TMPLOC                      ; done enough bytes?
+                bmi LBBFC                       ; brif done all 5
+                beq LBBF8                       ; brif last byte
+                ldb #1                          ; reset shift counter and quotient byte
+LBBCC           tfr a,cc                        ; get back carry status
+                bcs LBBDE                       ; brif it "went"
+LBBD0           asl FPA1+3                      ; shift mantissa (dividend) left
+                rol FPA1+2
+                rol FPA1+1
+                rol FPA1
+                bcs LBBBD                       ; brif carry - it "goes" so we have to bump quotient
+                bmi LBBA4                       ; brif high order bit is set - compare mantissas
+                bra LBBBD                       ; otherwise, count a 0 bit and try next bit
+LBBDE           lda FPA1+3                      ; subtract mantissa of FPA0 from mantissa of FPA1
+                suba FPA0+3
+                sta FPA1+3
+                lda FPA1+2
+                sbca FPA0+2
+                sta FPA1+2
+                lda FPA1+1
+                sbca FPA0+1
+                sta FPA1+1
+                lda FPA1
+                sbca FPA0
+                sta FPA1
+                bra LBBD0                       ; go check for another go
+LBBF8           ldb #0x40                       ; only two bits in last byte (for rounding)
+                bra LBBCC                       ; go do the last byte
+LBBFC           rorb                            ; get low bits to bits 7,6 and C to bit 5
+                rorb
+                rorb
+                stb FPSBYT                      ; save result extra precision
+                bsr LBC0B                       ; move FPA2 mantissa to FPA0 (result)
+                jmp LBA1C                       ; go normalize the result
+LBC06           ldb #2*10                       ; division by zero
+                jmp LAC46                       ; raise error
+; Copy mantissa of FPA2 to FPA0
+LBC0B           ldx FPA2                        ; copy high word
+                stx FPA0
+                ldx FPA2+2                      ; copy low word
+                stx FPA0+2
+                rts
+; unpack FP number at (X) to FPA0
+LBC14           pshs a                          ; save register
+                ldd 1,x                         ; get mantissa high word and sign
+                sta FP0SGN                      ; set sign
+                ora #0x80                       ; make sure mantissa always has bit 7 set
+                std FPA0
+                clr FPSBYT                      ; clear extra precision
+                ldb ,x                          ; get exponent
+                ldx 3,x                         ; copy mantissa low word
+                stx FPA0+2
+                stb FP0EXP                      ; save exponent (and set flags)
+                puls a,pc                       ; restore register and return
+LBC2A           ldx #V45                        ; point to FPA4
+                bra LBC35                       ; pack FPA0 there
+LBC2F           ldx #V40                        ; point to FPA3
+                skip2                           ; fall through to pack FPA0 there
+LBC33           ldx VARDES                      ; get variable descriptor pointer
+; Pack FPA0 to (X)
+LBC35           lda FP0EXP                      ; get exponent
+                sta ,x                          ; save it
+                lda FP0SGN                      ; get sign
+                ora #0x7f                       ; force set low bits - only keep sign in high bit
+                anda FPA0                       ; merge in bits 6-0 of high byte of mantissa
+                sta 1,x                         ; save it
+                lda FPA0+1                      ; copy next highest byte
+                sta 2,x
+                ldu FPA0+2                      ; and the low word of the mantissa
+                stu 3,x
+                rts
+; Copy FPA1 to FPA0; return with sign in A
+LBC4A           lda FP1SGN                      ; copy sign
+LBC4C           sta FP0SGN
+                ldx FP1EXP                      ; copy exponent, mantissa high byte
+                stx FP0EXP
+                clr FPSBYT                      ; clear extra precision
+                lda FPA1+1                      ; copy mantissa second highest byte
+                sta FPA0+1
+                lda FP0SGN                      ; set sign for return
+                ldx FPA1+2                      ; copy low word of mantissa
+                stx FPA0+2
+                rts
+; Copy FPA0 to FPA1
+LBC5F           ldd FP0EXP                      ; copy exponent and high byte of mantissa
+                std FP1EXP
+                ldx FPA0+1                      ; copy middle bytes of mantissa
+                stx FPA1+1
+                ldx FPA0+3                      ; copy low byte of mantissa and sign
+                stx FPA1+3
+                tsta                            ; set flags on exponent
+                rts
+; check FPA0: return B = 0, if FPA0 is 0, 0xff if negative, and 0x01 if positive
+LBC6D           ldb FP0EXP                      ; get exponent
+                beq LBC79                       ; brif 0
+LBC71           ldb FP0SGN                      ; get sign
+LBC73           rolb                            ; get sign to C
+                ldb #0xff                       ; set for negative result
+                bcs LBC79                       ; brif negative
+                negb                            ; set to 1 for positive
+LBC79           rts
+; SGN function
+SGN             bsr LBC6D                       ; get sign of FPA0
+LBC7C           stb FPA0                        ; save result
+                clr FPA0+1                      ; clear next lower 8 bits
+                ldb #0x88                       ; exponent if mantissa is 8 bit integer
+LBC82           lda FPA0                        ; get high bits of mantissa
+                suba #0x80                      ; set C if mantissa was positive (will cause a negation if it was negative)
+LBC86           stb FP0EXP                      ; set exponent
+                ldd ZERO                        ; clear out low word
+                std FPA0+2
+                sta FPSBYT                      ; clear extra precision
+                sta FP0SGN                      ; set sign to positive
+                jmp LBA18                       ; normalize the result
+; ABS function
+ABS             clr FP0SGN                      ; force FPA0 to be positive (yes, it's that simple)
+                rts
+; Compare packed FP number at (X) to FPA0
+; Return with B = -1, 0, 1 for FPA0 <, =, > (X) and flags set based on that
+LBC96           ldb ,x                          ; get exponent of (X)
+                beq LBC6D                       ; brif (X) is 0
+                ldb 1,x                         ; get MS byte of mantissa of (X)
+                eorb FP0SGN                     ; set bit 7 if signs of (X) and FPA0 differ
+                bmi LBC71                       ; brif signs differ - no need to compare the magnitude
+LBCA0           ldb FP0EXP                      ; compare exponents and brif different
+                cmpb ,x
+                bne LBCC3
+                ldb 1,x                         ; compare mantissa (but we have to pack the FPA0 bits first
+                orb #0x7f                       ; keep only sign bit (note: signs are the same)
+                andb FPA0                       ; merge in the mantissa bits from FPA0
+                cmpb 1,x                        ; do the packed versions match?
+                bne LBCC3                       ; brif not
+                ldb FPA0+1                      ; compare second byte of mantissas
+                cmpb 2,x
+                bne LBCC3
+                ldb FPA0+2                      ; compare third byte of mantissas
+                cmpb 3,x
+                bne LBCC3
+                ldb FPA0+3                      ; compare low byte of mantissas, but use subtraction so B = 0 on match
+                subb 4,x
+                bne LBCC3
+                rts                             ; return B = 0 if (X) = FPA0
+LBCC3           rorb                            ; shift carry to bit 7 (C set if FPA0 < (X))
+                eorb FP0SGN                     ; invert the comparision sense if the signs are negative
+                bra LBC73                       ; interpret comparison result
+; Shift mantissa of FPA0 until the binary point is immediately to the right of the mantissa and set up the
+; result as a two's complement value.
+LBCC8           ldb FP0EXP                      ; get exponent of FPA0
+                beq LBD09                       ; brif FPA0 is zero - we don't have to do anything, just blank it
+                subb #0xa0                      ; calculate number of shifts to get to the correct exponent (binary point to the right)
+                lda FP0SGN                      ; do we have a positive number?
+                bpl LBCD7                       ; brif so
+                com FPCARY                      ; negate the mantissa and set extra inbound precision to the correct sign
+                jsr LBA7B
+LBCD7           ldx #FP0EXP                     ; point to FPA0
+                cmpb #-8                        ; moving by whole bytes?
+                bgt LBCE4                       ; brif not
+                jsr LBAAE                       ; do bit shifting
+                clr FPCARY                      ; clear carry in byte
+                rts
+LBCE4           clr FPCARY                      ; clear the extra carry in precision
+                lda FP0SGN                      ; get sign of value
+                rola                            ; get sign to carry (so rotate repeats the sign)
+                ror FPA0                        ; shift the first bit
+                jmp LBABA                       ; do the shifting dance
+; INT function
+INT             ldb FP0EXP                      ; get exponent
+                cmpb #0xa0                      ; is the number big enough that there can be no fractional part?
+                bhs LBD11                       ; brif so - we don't have to do anything
+                bsr LBCC8                       ; go shift binary point to the right of the mantissa
+                stb FPSBYT                      ; save extra precision bits
+                lda FP0SGN                      ; get original sign
+                stb FP0SGN                      ; force result to be positive
+                suba #0x80                      ; set C if we had a positive result
+                lda #0xa0                       ; set exponent to match denormalized result
+                sta FP0EXP
+                lda FPA0+3                      ; save low byte
+                sta CHARAC
+                jmp LBA18                       ; go normalize (this will correct for the two's complement representation of negatives)
+LBD09           stb FPA0                        ; replace mantissa of FPA0 with contents of B
+                stb FPA0+1
+                stb FPA0+2
+                stb FPA0+3
+LBD11           rts
+; Convert ASCII string to FP
+; BUG: no overflow is checked on the decimal exponent in exponential notation.
+LBD12           ldx ZERO                        ; zero out FPA0 and temporaries
+                stx FP0SGN
+                stx FP0EXP
+                stx FPA0+1
+                stx FPA0+2
+                stx V47
+                stx V45
+                bcs LBD86                       ; brif input character is numeric
+                jsr RVEC19                      ; do the RAM hook dance
+                cmpa #'-                        ; regular negative sign
+                bne LBD2D                       ; brif not
+                com COEFCT                      ; invert sign
+                bra LBD31                       ; process stuff after the sign
+LBD2D           cmpa #'+                        ; regular plus?
+                bne LBD35                       ; brif not
+LBD31           jsr GETNCH                      ; get character after sign
+                bcs LBD86                       ; brif numeric
+LBD35           cmpa #'.                        ; decimal point?
+                beq LBD61                       ; brif so
+                cmpa #'E                        ; scientific notation
+                bne LBD65                       ; brif not
+                jsr GETNCH                      ; eat the "E"
+                bcs LBDA5                       ; brif numeric
+                cmpa #0xac                      ; negative sign (token)?
+                beq LBD53                       ; brif so
+                cmpa #'-                        ; regular negative?
+                beq LBD53                       ; brif so
+                cmpa #0xab                      ; plus sign (token)?
+                beq LBD55                       ; brif so
+                cmpa #'+                        ; regular plus?
+                beq LBD55
+                bra LBD59                       ; brif no sign found
+LBD53           com V48                         ; set exponent sign to negative
+LBD55           jsr GETNCH                      ; eat the sign
+                bcs LBDA5                       ; brif numeric
+LBD59           tst V48                         ; is the exponent sign negatvie?
+                beq LBD65                       ; brif not
+                neg V47                         ; negate base 10 exponent
+                bra LBD65
+LBD61           com V46                         ; toggle decimal point flag
+                bne LBD31                       ; brif we haven't seen two decimal points
+LBD65           lda V47                         ; get base 10 exponent
+                suba V45                        ; subtract number of places to the right
+                sta V47                         ; we now have a complete decimal exponent
+                beq LBD7F                       ; brif we have no base 10 shifting required
+                bpl LBD78                       ; brif positive exponent
+LBD6F           jsr LBB82                       ; divide FPA0 by 10 (shift decimal point left)
+                inc V47                         ; bump exponent
+                bne LBD6F                       ; brif we haven't reached 0 yet
+                bra LBD7F                       ; return result
+LBD78           jsr LBB6A                       ; multiply by 10
+                dec V47                         ; downshift the exponent
+                bne LBD78                       ; brif not at 0 yet
+LBD7F           lda COEFCT                      ; get desired sign
+                bpl LBD11                       ; brif it will be positive - no need to do anything
+                jmp LBEE9                       ; flip the sign of FPA0
+LBD86           ldb V45                         ; get the decimal count
+                subb V46                        ; (if decimal seen, will add one; otherwise it does nothing)
+                stb V45
+                pshs a                          ; save new digit
+                jsr LBB6A                       ; multiply partial result by 10
+                puls b                          ; get back digit
+                subb #'0                        ; remove ASCII bias
+                bsr LBD99                       ; add B to FPA0
+                bra LBD31                       ; go process another digit
+LBD99           jsr LBC2F                       ; save FPA0 to FPA3
+                jsr LBC7C                       ; convert B to FP number
+                ldx #V40                        ; point to FPA3
+                jmp LB9C2                       ; add FPA3 and FPA0
+LBDA5           ldb V47                         ; get exponent value
+                aslb                            ; times 2
+                aslb                            ; times 4
+                addb V47                        ; times 5
+                aslb                            ; times 10
+                suba #'0                        ; remove ASCII bias
+                pshs b                          ; save acculated result
+                adda ,s+                        ; add new digit to accumulated result
+                sta V47                         ; save new accumulated decimal exponent
+                bra LBD55                       ; interpret another exponent character
+LBDB6           fcb 0x9b,0x3e,0xbc,0x1f,0xfd    ; packed FP: 99999999.9
+LBDBB           fcb 0x9e,0x6e,0x6b,0x27,0xfd    ; packed FP: 999999999
+LBDC0           fcb 0x9e,0x6e,0x6b,0x28,0x00    ; pakced FP: 1E9
+LBDC5           ldx #LABE8-1                    ; point to "IN" message
+                bsr LBDD6                       ; output the string
+                ldd CURLIN                      ; get basic line number
+LBDCC           std FPA0                        ; save 16 bit unsigned integer
+                ldb #0x90                       ; exponent for upper 16 bits of FPA0 to be an integer
+                coma                            ; set C (force normalization to treat as positive)
+                jsr LBC86                       ; zero bottom half, save exponent, and normalize
+                bsr LBDD9                       ; convert FP number to ASCII string
+LBDD6           jmp STRINOUT                    ; output string
+; Convert FP number to ASCII string
+LBDD9           ldu #STRBUF+3                   ; point to buffer address that will not cause string to go to string space
+LBDDC           lda #0x20                       ; default sign is a space character
+                ldb FP0SGN                      ; get sign of value
+                bpl LBDE4                       ; brif positive
+                lda #'-                         ; use negative sign
+LBDE4           sta ,u+                         ; save sign
+                stu COEFPT                      ; save output buffer pointer
+                sta FP0SGN                      ; save sign character
+                lda #'0                         ; result is 0 if exponent is 0
+                ldb FP0EXP                      ; get exponent
+                lbeq LBEB8                      ; brif FPA0 is 0
+                clra                            ; base 10 exponent is 0 for > 1
+                cmpb #0x80                      ; is number > 1?
+                bhi LBDFF                       ; brif so
+                ldx #LBDC0                      ; point to 1E+09
+                jsr LBACA                       ; shift decimal to the right by 9 spaces
+                lda #-9                         ; account for shift
+LBDFF           sta V45                         ; save base 10 exponent
+LBE01           ldx #LBDBB                      ; point to 999999999
+                jsr LBCA0                       ; are we above that?
+                bgt LBE18                       ; brif so
+LBE09           ldx #LBDB6                      ; point to 99999999.9
+                jsr LBCA0                       ; are we above that?
+                bgt LBE1F                       ; brif in range
+                jsr LBB6A                       ; multiply by 10 (we were small)
+                dec V45                         ; account for shift
+                bra LBE09                       ; see if we've come into range
+LBE18           jsr LBB82                       ; divide by 10
+                inc V45                         ; account for shift
+                bra LBE01                       ; see if we've come into range
+LBE1F           jsr LB9B4                       ; add 0.5 to FPA0 (rounding)
+                jsr LBCC8                       ; do the integer dance
+                ldb #1                          ; default decimal flag (force immediate decimal)
+                lda V45                         ; get base 10 exponent
+                adda #10                        ; account for "unormalized" number
+                bmi LBE36                       ; brif number < 1.0
+                cmpa #11                        ; do we have more than 9 places?
+                bhs LBE36                       ; brif so - do scientific notation
+                deca
+                tfr a,b
+                lda #2                          ; force no scientific notation
+LBE36           deca                            ; subtract wo without affecting carry
+                deca
+                sta V47                         ; save exponent - 0 is do not display in scientific notation
+                stb V45                         ; save number of places to left of decimal
+                bgt LBE4B                       ; brif >= 1
+                ldu COEFPT                      ; point to string buffer
+                lda #'.                         ; put decimal
+                sta ,u+
+                tstb                            ; is there anything to left of decimal?
+                beq LBE4B                       ; brif not
+                lda #'0                         ; store a zero
+                sta ,u+
+LBE4B           ldx #LBEC5                      ; point to powers of 10
+                ldb #0x80                       ; set digit counter to 0x80
+LBE50           lda FPA0+3                      ; add mantissa to power of 10
+                adda 3,x
+                sta FPA0+3
+                lda FPA0+2
+                adca 2,x
+                sta FPA0+2
+                lda FPA0+1
+                adca 1,x
+                sta FPA0+1
+                lda FPA0
+                adca ,x
+                sta FPA0
+                incb                            ; add one to digit counter
+                rorb                            ; put carry into bit 7
+                rolb                            ; set V if carry and sign differ
+                bvc LBE50                       ; brif positive mantissa or carry is 0 and negative mantissa
+                bcc LBE72                       ; brif negative mantissa
+                subb #10+1                      ; take 9's complement if adding mantissa
+                negb
+LBE72           addb #'0-1                      ; add ASCII bias
+                leax 4,x                        ; move to next power of 10
+                tfr b,a                         ; save digit
+                anda #0x7f                      ; remove add/subtract flag
+                sta ,u+                         ; put in output
+                dec V45                         ; do we need a decimal yet?
+                bne LBE84                       ; brif not
+                lda #'.                         ; put decimal
+                sta ,u+
+LBE84           comb                            ; toggle bit 7 (add/sub flag)
+                andb #0x80                      ; only keep bit 7
+                cmpx #LBEC5+9*4                 ; done all places?
+                bne LBE50                       ; brif not
+LBE8C           lda ,-u                         ; get last character
+                cmpa #'0                        ; was it 0?
+                beq LBE8C                       ; brif so
+                cmpa #'.                        ; decimal?
+                bne LBE98                       ; brif not
+                leau -1,u                       ; move past decimal if it isn't needed
+LBE98           lda #'+                         ; plus sign
+                ldb V47                         ; get scientific notation exponent
+                beq LBEBA                       ; brif not scientific notation
+                bpl LBEA3                       ; brif positive exponent
+                lda #'-                         ; negative sign for base 10 exponent
+                negb                            ; switch to positive exponent
+LBEA3           sta 2,u                         ; put sign
+                lda #'E                         ; put "E"
+                sta 1,u
+                lda #'0-1                       ; init to ASCII 0 (compensate for INC)
+LBEAB           inca                            ; bump digit
+                subb #10                        ; have we hit the correct one yet?
+                bcc LBEAB                       ; brif not
+                addb #'9+1                      ; convert units digit to ASCII
+                std 3,u                         ; put exponent in output
+                clr 5,u                         ; put trailing NUL
+                bra LBEBC                       ; go reset pointer
+LBEB8           sta ,u                          ; store last character
+LBEBA           clr 1,u                         ; put NUL at the end
+LBEBC           ldx #STRBUF+3                   ; point to start of string
+                rts
+LBEC0           fcb 0x80,0x00,0x00,0x00,0x00    ; packed FP 0.5
+LBEC5           fqb -100000000
+                fqb 10000000
+                fqb -1000000
+                fqb 100000
+                fqb -10000
+                fqb 1000
+                fqb -100
+                fqb 10
+                fqb -1
+LBEE9           lda FP0EXP                      ; get exponent of FPA0
+                beq LBEEF                       ; brif 0 - don't flip sign
+                com FP0SGN                      ; flip sign
+LBEEF           rts
+; Expand a polynomial of the form
+; AQ+BQ^3+CQ^5+DQ^7..... where Q is FPA0 and X points to a table
+LBEF0           stx COEFPT                      ; save coefficient table pointer
+                jsr LBC2F                       ; copy FPA0 to FPA3
+                bsr LBEFC                       ; multiply FPA3 by FPA0
+                bsr LBF01                       ; expand polynomial
+                ldx #V40                        ; point to FPA3
+LBEFC           jmp LBACA                       ; multiply FPA0 by FPA3
+LBEFF           stx COEFPT                      ; save coefficient table counter
+LBF01           jsr LBC2A                       ; move FPA0 to FPA4
+                ldx COEFPT                      ; get the current coefficient
+                ldb ,x+                         ; get the number of entries
+                stb COEFCT                      ; save as counter
+                stx COEFPT                      ; save new pointer
+LBF0C           bsr LBEFC                       ; multiply (X) and FPA0
+                ldx COEFPT                      ; get this coefficient
+                leax 5,x                        ; move to next one
+                stx COEFPT                      ; save new pointer
+                jsr LB9C2                       ; add (X) to FPA0
+                ldx #V45                        ; point X to FPA4
+                dec COEFCT                      ; done all coefficients?
+                bne LBF0C                       ; brif more left
+                rts
+; RND function
+RND             jsr LBC6D                       ; set flags on FPA0
+                bmi LBF45                       ; brif negative - set seed
+                beq LBF3B                       ; brif 0 - do random between 0 and 1
+                bsr LBF38                       ; convert to integer
+                jsr LBC2F                       ; save range value
+                bsr LBF3B                       ; get random number
+                ldx #V40                        ; point to FPA3
+                bsr LBEFC                       ; multply (X) by FPA0
+                ldx #LBAC5                      ; point to FP 1.0
+                jsr LB9C2                       ; add 1 to FPA0
+LBF38           jmp INT                         ; return integer value
+LBF3B           ldx RVSEED+1                    ; move variable random number seed to FPA0
+                stx FPA0
+                ldx RVSEED+3
+                stx FPA0+2
+LBF45           ldx RSEED                       ; move fixed seed to FPA1
+                stx FPA1
+                ldx RSEED+2
+                stx FPA1+2
+                jsr LBAD0                       ; multiply them
+                ldd VAD                         ; get lowest order  product bytes
+                addd #0x658b                    ; add a constant
+                std RVSEED+3                    ; save it as new seed
+                std FPA0+2                      ; save in result
+                ldd VAB                         ; get high order extra product bytes
+                adcb #0xb0                      ; add upper bytes of constant
+                adca #5
+                std RVSEED+1                    ; save as new seed
+                std FPA0                        ; save as result
+                clr FP0SGN                      ; set result to positive
+                lda #0x80                       ; set exponent to 0 < FPA0 < 1
+                sta FP0EXP
+                lda FPA2+2                      ; get a byte from FPA2
+                sta FPSBYT                      ; save as extra precision
+                jmp LBA1C                       ; go normalize FPA0
+RSEED           fqb 0x40e64dab                  ; constant random number generator seed
+; SIN function
+SIN             jsr LBC5F                       ; copy FPA0 to FPA1
+                ldx #LBFBD                      ; point to 2*pi
+                ldb FP1SGN                      ; get sign of FPA1
+                jsr LBB89                       ; divide FPA0 by 2*pi
+                jsr LBC5F                       ; copy FPA0 to FPA1
+                bsr LBF38                       ; convert FPA0 to an integer
+                clr RESSGN                      ; set result to positive
+                lda FP1EXP                      ; get exponent of FPA1
+                ldb FP0EXP                      ; get exponent of FPA0
+                jsr LB9BC                       ; subtract FPA0 from FPA1
+                ldx #LBFC2                      ; point to FP 0.25
+                jsr LB9B9                       ; subtract FPA0 from 0.25 (pi/2)
+                lda FP0SGN                      ; get result sign
+                pshs a                          ; save it
+                bpl LBFA6                       ; brif positive
+                jsr LB9B4                       ; add 0.5 (pi) to FPA0
+                lda FP0SGN                      ; get sign of result
+                bmi LBFA9                       ; brif negative
+                com RELFLG                      ; if 3pi/2 >= arg >= pi/2
+LBFA6           jsr LBEE9                       ; flip sign of FPA0
+LBFA9           ldx #LBFC2                      ; point to 0.25
+                jsr LB9C2                       ; add 0.25 (pi/2) to FPA0
+                puls a                          ; get original sign
+                tsta                            ; was it positive
+                bpl LBFB7                       ; brif so
+                jsr LBEE9                       ; flip result sign
+LBFB7           ldx #LBFC7                      ; point to series coefficients
+                jmp LBEF0                       ; go calculate value
+LBFBD           fcb 0x83,0x49,0x0f,0xda,0xa2    ; 2*pi
+LBFC2           fcb 0x7f,0x00,0x00,0x00,0x00    ; 0.25
+; modified taylor series SIN coefficients
+LBFC7           fcb 6-1                         ; six coefficients
+                fcb 0x84,0xe6,0x1a,0x2d,0x1b    ; -((2pi)^11)/11!
+                fcb 0x86,0x28,0x07,0xfb,0xf8    ; ((2pi)^9)/9!
+                fcb 0x87,0x99,0x68,0x89,0x01    ; -((2pi)^7)/7!
+                fcb 0x87,0x23,0x35,0xdf,0xe1    ; ((2pi)^5)/5!
+                fcb 0x86,0xa5,0x5d,0xe7,0x28    ; -(2pi)^3)/3!
+                fcb 0x83,0x49,0x0f,0xda,0xa2    ; 2*pi
+; these 12 bytes are unused
+                fcb 0xa1,0x54,0x46,0x8f,0x13,0x8f,0x52,0x43
+                fcb 0x89,0xcd,0xa6,0x81
+; these are a copy of the interrupt vectors that live at the top of the ROM. It's not clear
+; why these vectors have been modified since they are not actually used.
+                fdb INT.SWI3                    ; SWI3
+                fdb INT.SWI2                    ; SWI2
+                fdb INT.FIRQ                    ; FIRQ
+                fdb INT.IRQ                     ; IRQ
+                fdb INT.SWI                     ; SWI
+                fdb INT.NMI                     ; NMI
+                fdb L8C1B                       ; RESET
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Coco3 internal ROM, upper 32K
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; This is the initialization code specific to the Coco3. This handles copying the ROMs to RAM and adding various patches in.
+; This sequence of code demonstrates clearly that the creators of the Coco3 additions were rushed and didn't have a clear
+; understanding of the Coco3 hardware or how Color Basic works. There is evidence of last minute adjustments along with code
+; that serves no purpose but which is still present.
+;
+; There is also a major bug. The F1 for burst phase invert enable is clearly supposed to be enabled for the HSCREEN graphics
+; modes. However, the code that enables it actually patches the wrong byte in the graphics mode initializers. Instead of enabling
+; the burst phase invert bit in FF98, it actually enables the FIRQ enable bit in FF90.
+SC000           orcc #0x50                      ; make sure interrupts are disabled
+                lds #0x5eff                     ; put the stack somewhere
+                lda #0x12                       ; nuclear green colour
+                ldb #16                         ; 16 palette registers
+                ldx #PALETREG                   ; point to palette registers
+SC00D           sta ,x+                         ; set a palette register to green
+                decb                            ; done?
+                bne SC00D                       ; brif not
+                ldx #MMUREG                     ; point to MMU registers
+                leay MMUIMAGE,pcr               ; point to MMU initializer
+                ldb #16                         ; there are 16 MMU registers
+SC01B           lda ,y+                         ; copy an MMU initializer
+                sta ,x+
+                decb                            ; done all?
+                bne SC01B                       ; brif not
+                lda #COCO+MMUEN+MC3+MC2+MC1     ; enable coco compatible, mmu, SCS, FExx, and 32K internal
+                sta INIT0
+                leax BEGMOVE,pcr                ; point to start of relocated initialization code
+                ldy #0x4000                     ; point to RAM address where it goes
+SC02F           ldd ,x++                        ; copy four bytes
+                ldu ,x++
+                std ,y++
+                stu ,y++
+                cmpx #ENDMOVE                   ; copied everything?
+                blo SC02F                       ; brif not
+                jmp 0x4000                      ; transfer control to code in RAM
+; The rest runs from RAM. This allows it to mess with the ROM mapping (for the ROM/RAM copy). Unfortunately,
+; this clobbers an 8K memory block *before* it determines that it isn't going to copy ROM to RAM which is
+; somewhat problematic for things that intercept a warm start.
+BEGMOVE         leas -1,s                       ; make a hole on the stack
+                nop                             ; space fillers; probably something removed at the eleventh hour
+                nop
+                nop
+                nop
+                nop
+                lda #0xff                       ; set GIME timer to maximum value and start it counting
+                sta V.TIMER
+                sta V.TIMER+1
+                leax VIDIMAGE,pcr               ; point to video mode initializer
+                ldy #VIDEOMOD                   ; point to video mode registers
+SC056           lda ,x+                         ; copy a byte
+                sta ,y+
+                cmpy #MMUREG                    ; done?
+                bne SC056                       ; brif not
+                ldx #PIA1                       ; point to PIA1
+                ldd #0xff34                     ; set up for initializing PIAs
+                clr 1,x                         ; set PIA1 DA to direction mode
+                clr 3,x                         ; set PIA1 DB to direction mode
+                deca
+                sta ,x                          ; set PIA1 DA bits 7-1 as output, 0 as input
+                lda #0xf8                       ; set PIA1 DB bits 7-3 as output, 2-0 as input
+                sta 2,x
+                stb 1,x                         ; set PIA1 DA to data mode
+                stb 3,x                         ; set PIA1 DB to data mode
+                clr 2,x                         ; set VDG to alpha-numeric
+                lda #2                          ; set RS232 to marking
+                sta ,x
+                lda #0xff
+                ldx #PIA0                       ; point to PIA0
+                clr 1,x                         ; set PIA0 DA to direction mode
+                clr 3,x                         ; set PIA0 DB to direction mode
+                clr ,x                          ; set PIA0 DA to input
+                sta 2,x                         ; set PIA0 DB to output
+                stb 1,x                         ; set PIA0 DA to direction mode
+                stb 3,x                         ; set PIA0 DB to direction mode
+                ldb #12                         ; there are 12 SAM bits to reset
+                ldu #SAMREG                     ; point to SAM register
+SC091           sta ,u++                        ; clear a bit
+                decb                            ; done all?
+                bne SC091                       ; brif not
+                sta SAMREG+9                    ; put VDG display at 0x400
+                tfr b,dp                        ; set direct page to 0
+                clr 2,x                         ; strobe all keyboard columns (pointless)
+                sta -3,u                        ; select RAM page 1 (also pointless)
+                ldx #PIA0                       ; point to PIA0 (unneeded - already points there)
+                ldb #0xdf                       ; column strobe for F1
+                stb 2,x                         ; strobe for F1
+                lda ,x                          ; get row data
+                coma                            ; set nonzero if F1 down
+                anda #0x40
+                sta ,s                          ; save F1 state for later
+                ldy #2                          ; check for two keys
+SC0B1           asrb                            ; shift strobe (why not just shift directly in the PIA?)
+                stb 2,x                         ; strobe new column
+                lda ,x                          ; get row data
+                coma                            ; set nonzero if CTRL or ALT is down
+                anda #0x40
+                beq SC0C2                       ; brif not - we don't have C-A-RESET
+                leay -1,y                       ; done both?
+                bne SC0B1                       ; brif not
+                lbra SC1F0                      ; go do easter egg picture if C-A-RESET
+SC0C2           lda #COCO+MMUEN+MC3+MC1         ; turn off standard SCS (why?)
+                sta INIT0
+; This checks if we have a valid warm start routine. If there is one, we don't do a ROM/RAM copy. This and
+; everything above could just as easily have been done from ROM.
+                lda INT.FLAG                    ; are the bounce vectors valid?
+                cmpa #0x55
+                bne SC0F6                       ; brif not - copy ROM to RAM
+                lda RSTFLG                      ; is the DP reset vector marked valid?
+                cmpa #0x55
+                bne NOWARM                      ; brif not
+                ldx RSTVEC                      ; does the vector point to NOP?
+                lda ,x
+                cmpa #0x12
+                lbeq SC18C                      ; brif so - don't do ROM/RAM copy
+NOWARM          clr MMUREG                      ; put bottom memory block in logical block 0 (replaces DP)
+                lda RSTFLG                      ; does this give us a valid reset vector?
+                cmpa #0x55
+                bne SC0F1                       ; brif not
+                ldx RSTVEC                      ; does this routine point to a NOP?
+                lda ,x
+                cmpa #0x12
+                lbeq SC18C                      ; brif so - don't do ROM/RAM copy and keep modified memory map
+SC0F1           lda #BLOCK7.0                   ; restore memory map
+                sta MMUREG
+SC0F6           ldx #DOSBAS                     ; point to the end of Color Basic
+                ldy #EXBAS                      ; point to start of Extended Basic
+                lbsr SC1AA                      ; copy them to RAM
+                leay PATCHTAB,pcr               ; point to patch table
+                lda ,y+                         ; get number of patches to be made
+SC106           pshs a                          ; save patch counter
+                ldx ,y++                        ; get address to patch
+                ldb ,y+                         ; get number of bytes in the patch
+SC10C           lda ,y+                         ; copy a byte
+                sta ,x+
+                decb                            ; done all in this patch?
+                bne SC10C
+                puls a                          ; get back patch counter
+                deca                            ; done all patches?
+                bne SC106                       ; brif not
+                clr TYCLR                       ; got back to ROM mode
+                lda #COCO+MMUEN+MC3             ; set up for 16K split mode
+                sta INIT0
+                ldd DOSBAS                      ; is there a Disk Basic ROM signature?
+                cmpa #'D                        ; (note that this should just be CMPD)
+                bne SC137
+                cmpb #'K
+                bne SC137
+                ldx #SUPERVAR                   ; point to end of Disk Basic ROM
+                ldy #DOSBAS                     ; point to start of Disk Basic ROM
+                bsr SC1AA                       ; copy it to RAM
+                lbsr SC322                      ; add patches to Disk Basic
+SC137           clr TYCLR                       ; go back to ROM mode
+                lda #COCO+MMUEN+MC3+MC1         ; set 32K internal mocde
+                sta INIT0
+                ldx #H.CRSLOC                   ; point to end of the Coco3 additions
+                ldy #SUPERVAR                   ; point to start of the Coco3 additions
+                bsr SC1AA                       ; copy it to RAM
+                lbsr SC1DE                      ; set up an easter egg
+                leay INTIMAGE,pcr               ; point to bounce vector initializer
+                ldx #INT.FLAG                   ; point to bounce vectors
+                ldb #19                         ; 19 bytes in bounce vectors
+                lbsr MOVE.XY                    ; initialize the bounce vectors
+                clr TYSET                       ; enable RAM mode (the ROM/RAM copy already did this)
+                tst ,s                          ; was F1 pressed?
+                beq SC180                       ; brif not
+                ldx #IM.TEXT                    ; point to text mode initializers
+                ldb #3                          ; there are three sets of them
+                leax 1,x                        ; move past the FF90 initializer
+SC165           lda ,x                          ; get video mode initializer
+                ora #0x20                       ; enable burst phase invert
+                sta ,x                          ; update initializer
+                leax 9,x                        ; move to next mode
+                decb                            ; done all of them?
+                bne SC165                       ; brif not
+                ldb #2                          ; two graphics mode initalizers
+                ldx #IM.GRAPH                   ; point to graphics mode initializers (should be +1; we're actually enabling GIME FIRQ)
+SC175           lda ,x                          ; get initializer
+                ora #0x20                       ; enable burst phase invert (or it would if X pointed to the right place)
+                sta ,x                          ; save modified initializer
+                leax 9,x                        ; move to next set
+                decb                            ; done all of them?
+                bne SC175                       ; brif not
+SC180           ldx #VIDRAM                     ; point to start of VDG text screen
+                lda #0x60                       ; VDG space character
+SC185           sta ,x+                         ; blank a character
+                cmpx #VIDRAM+512                ; end of screen?
+                blo SC185                       ; brif not
+SC18C           lda #COCO+MMUEN+MC3+MC2+MC1     ; turn the SCS back on
+                sta INIT0
+                tst ,s                          ; F1?
+                beq SC19A                       ; brif not
+                lda #0x20                       ; enable burst phase invert
+                sta VIDEOMOD
+SC19A           ldx #PALETREG                   ; point to palette registers
+                leay PALIMAGE,PCR               ; point to palette initializer
+                ldb #16                         ; do 16 palette registers
+                bsr MOVE.XY                     ; initialize palette
+                leas 1,s                        ; clean up stack (not much point since it will be reset anyway)
+                jmp RESVEC                      ; transfer control to the original Color Basic initialization routine
+SC1AA           stx 0x5f02                      ; save end copy address
+                sts 0x5f00                      ; save stack
+SC1B1           clr TYCLR                       ; go to ROM mode
+                ldd ,y                          ; grab 8 bytes
+                ldx 2,y
+                ldu 4,y
+                lds 6,y
+                clr TYSET                       ; go to RAM mode
+                std ,y                          ; save the 8 bytes
+                stx 2,y
+                stu 4,y
+                sts 6,y
+                leay 8,y                        ; move pointer forward
+                cmpy 0x5f02                     ; done yet?
+                blo SC1B1                       ; brif not
+                lds 0x5f00                      ; restore stack pointer
+                rts
+MOVE.XY         lda ,y+                         ; copy a byte
+                sta ,x+
+                decb                            ; done all?
+                bne MOVE.XY                     ; brif not
+                rts
+SC1DE           ldx #AUTHORMS                   ; point to author name easter egg
+                leay SC30D,pcr                  ; point to encoded names
+                ldb #21                         ; 21 bytes in names
+SC1E7           lda ,y+                         ; get encoded byte
+                coma                            ; decode (wow. one's complement encoding.)
+                sta ,x+                         ; put in copied ROM
+                decb                            ; done all?
+                bne SC1E7                       ; brif not
+                rts
+SC1F0           clra                            ; set up to mark things as invalid
+                sta INT.FLAG                    ; mark bounce vectors invalid
+                sta RSTFLG                      ; mark reset vector invalid
+                sta TYCLR                       ; go to ROM mode
+                ldb #9                          ; foreground colour for image
+                stb PALETREG+10
+                ldb #63                         ; white background
+                stb PALETREG+11
+                ldx #AUTHPIC                    ; point to author picture data
+                ldy #0xe00                      ; put picture at 0xe00 in memory
+SC20A           ldd ,x++                        ; copy four bytes
+                ldu ,x++
+                std ,y++
+                stu ,y++
+                cmpx #AUTHPICe                  ; at end of picture data?
+                blo SC20A                       ; brif not
+                lda #0xf9                       ; 256x192, CSS0 VDG mode
+                sta PIA1+2
+                clra                            ; this instruction is useless
+                ldx #SAMREG                     ; point to SAM register
+                sta ,x                          ; set SAM address to 0xe00 and video mode to 256x192
+                sta 3,x
+                sta 5,x
+                sta 7,x
+                sta 9,x
+                sta 11,x
+WAITLOOP        bra WAITLOOP                    ; freeze the system
+VIDIMAGE        fcb 0x00,0x00,0x00,0x00,0x0f,0xe0,0x00,0x00
+PALIMAGE        fcb 18,36,11,7,63,31,9,38,0,18,0,63,0,18,0,38
+MMUIMAGE        fcb BLOCK7.0,BLOCK7.1,BLOCK6.4,BLOCK7.3
+                fcb BLOCK7.4,BLOCK7.5,BLOCK7.6,BLOCK7.7
+                fcb BLOCK7.0,BLOCK6.0,BLOCK6.1,BLOCK6.2
+                fcb BLOCK6.3,BLOCK7.5,BLOCK6.5,BLOCK7.7
+PATCHTAB        fcb 27                          ; 27 patches to install
+; Patch #1: enable warm start routine after ROM/RAM copy
+patch1          fdb XBWMST
+                fcb patch2-*-1
+                nop
+; Patch #2: intercept tokenization routine
+patch2          fdb LB8D4
+                fcb patch3-*-1
+                jmp ALINK2
+; Patch #3: intercept detokenization routine
+patch3          fdb LB7F3
+                fcb patch4-*-1
+                jmp ALINK3
+; Patch #4: intercept Extended Basic's command interpretation handler
+patch4          fdb L8150
+                fcb patch5-*-1
+                jmp ALINK4
+                nop
+; Patch #5: intercept Extended Basic's function handler
+patch5          fdb L816C
+                fcb patch6-*-1
+                jmp ALINK5
+                nop
+; Patch #6 through patch #10 - extend &H and &O to allow 24 bit values
+patch6          fdb L8834
+                fcb patch7-*-1
+                jmp ALINK6A
+                clr FPA0+1
+                clr FPA0+2
+                clr FPA0+3
+                bra *-78
+                clr FPA0
+                bra *-47
+                jmp ALINK6B
+patch7          fdb L87EB
+                fcb patch8-*-1
+                bra *+76
+                nop
+                rts
+                ldx #FPA0+1
+patch8          fdb L880C
+                fcb patch9-*-1
+                bra *+55
+patch9          fdb L8826
+                fcb patch10-*-1
+                bcs *+25
+patch10         fdb L87E7
+                fcb patch11-*-1
+                bne *+7
+; Patch #11 is needed because the above removed an RTS used by this routine
+patch11         fdb L886A
+                fcb patch12-*-1
+                bne *-124
+; Patch #12 - intercept signon message display
+patch12         fdb L80B2
+                fcb patch13-*-1
+                jmp ALINK12
+; Patch #13 - remove one carriage return from signon message
+patch13         fdb L80E8+82
+                fcb patch14-*-1
+                fcb 0
+; Patch #14 - extend Extended Basic's graphics initialization routine
+patch14         fdb L9703
+                fcb patch15-*-1
+                jmp ALINK14
+; Patch #15 - intercept break check
+patch15         fdb LADF0
+                fcb patch16-*-1
+                jmp ALINK15
+                nop
+; Patch #16 - intercept break check when handling "line input"
+patch16         fdb LA3C2
+                fcb patch17-*-1
+                jmp ALINK16
+                nop
+; Patch #17 - cause INPUT to respond to ON BRK
+patch17         fdb LB03C+1
+                fcb patch18-*-1
+                fdb ALINK17
+; Patch #18 - intercept ON command
+patch18         fdb ON
+                fcb patch19-*-1
+                jmp ALINK18
+; Patch #19 - add on extra stuff to end of NEW
+patch19         fdb LAD3F
+                fcb patch20-*-1
+                jmp ALINK19
+                nop
+; Patch #20 - intercept error handler
+patch20         fdb LAC46
+                fcb patch21-*-1
+                jmp ALINK20
+; Patch #21 - intercept immediate mode loop
+patch21         fdb LAC73
+                fcb patch22-*-1
+                jmp ALINK21
+; Patch #22 - intercept character to screen routine
+patch22         fdb LA30A
+                fcb patch23-*-1
+                jmp L8C37
+; Patch #23 - intercept CLS
+patch23         fdb CLS
+                fcb patch24-*-1
+                jmp L8C46
+; Patch #24 - intercept waiting for keypress with cursor routine
+patch24         fdb LA1B1
+                fcb patch25-*-1
+                jmp LA0CE
+                nop
+                nop
+                nop
+                nop
+                nop
+; Patch #25 - intercept PRINT @
+patch25         fdb LB902
+                fcb patch26-*-1
+                jmp ALINK25
+; Patch #26 - intercept conditional newline routine
+patch26         fdb LB95C
+                fcb patch27-*-1
+                jmp ALINK26
+; Patch #27 - intercept CLEAR handling in line input routine
+patch27         fdb LA38D
+                fcb patch27e-*-1
+                jmp ALINK27
+patch27e        equ *
+; Names of the authors in one's complemented ASCII
+SC30D           fcb 0xab,0xd1,0xb7,0x9e,0x8d,0x8d,0x96,0x8c
+                fcb 0xdf,0xd9,0xdf,0xab,0xd1,0xba,0x9e,0x8d
+                fcb 0x93,0x9a,0x8c,0xf2,0xff
+SC322           lda DOSBAS+4                    ; get MSB of DSKCON vector
+                cmpa #0xd6                      ; is it 0xd6?
+                bne SC334                       ; brif not - we have Disk Basic 1.1
+                ldx #0xc0c6                     ; point to patch address in Disk Basic 1.0
+                leay SC355,pcr                  ; point to patch for Disk Basic 1.0
+                ldb ,y+                         ; get number of bytes to patch
+                bra SC349                       ; go patch it
+SC334           ldx #0xC8B4                     ; point to Disk Basic 1.1 keyboard check (in the interpretation loop handler)
+                lda #0x12                       ; NOP opcode
+                ldb #11                         ; clobber 11 bytes (which check for a key down before calling the break check)
+SC33B           sta ,x+                         ; put a NOP
+                decb                            ; done?
+                bne SC33B                       ; brif not
+                ldx #0xc0d9                     ; point to the Disk Basic 1.1 patch address
+                leay SC351,pcr                  ; point to patch for Disk Basic 1.1
+                ldb ,y+                         ; get number of bytes in patch
+SC349           lda ,y+                         ; put a byte from the patch
+                sta ,x+
+                decb                            ; done yet?
+                bne SC349                       ; brif not
+                rts
+; Copyright message patch for Disk Basic 1.1
+SC351           fcb SC355-*-1
+                jmp ALINK29
+; Copyright message patch for Disk Basic 1.0
+SC355           fcb SC355e-*-1
+                jmp ALINK28
+SC355e          equ *
+; This is the initializer for the bounce vector table. It sets up to transfer control to Color Basic's
+; interrupt vectors at 0x100. These really should be JMP instead of LBRA, if only because JMP is faster.
+INTIMAGE        fcb 0x55                        ; valid vector table flag
+                lbra (INTIMAGE+1)-(INT.JUMP)+SW3VEC             ; SWI3
+                lbra (INTIMAGE+1)-(INT.JUMP)+SW2VEC             ; SWI2
+                lbra (INTIMAGE+1)-(INT.JUMP)+FRQVEC             ; FIRQ
+                lbra (INTIMAGE+1)-(INT.JUMP)+IRQVEC             ; IRQ
+                lbra (INTIMAGE+1)-(INT.JUMP)+SWIVEC             ; SWI
+                lbra (INTIMAGE+1)-(INT.JUMP)+NMIVEC             ; NMI
+ENDMOVE         equ *
+; Unused bytes
+                fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x18,0x00,0x0E,0x00
+; This is the "pmode 4" author picture easter egg
+AUTHPIC         fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFB,0xEE,0xEF,0xFB,0xFF,0xBB,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xBB
+                fcb 0xBB,0xBB,0xBF,0xBB,0xBB,0xFF,0xBF,0xFF,0xFE,0xEF,0xFF,0xFF,0xFF,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBF,0xBB,0xFF,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xEE,0xEE,0xEF,0xFF,0xFE,0xFF,0xFE,0xEE,0xEE,0xFE,0xEE
+                fcb 0xEE,0xEE,0xEF,0xEE,0xEE,0xEE,0xEE,0xEE,0xFE,0xEE,0xEE,0xEE,0xEE,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xFF,0xBB,0xBB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBB,0xBB,0xBB,0xBB,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF6,0xAA,0xAE,0xAA,0xAE,0xAA,0xEA,0xBB,0xBB,0xFB,0xFF,0xBB,0xFF,0xBF,0xBF
+                fcb 0xFF,0xFB,0xBF,0xBB,0xBB,0xBB,0xBB,0xBB,0xBA,0xEA,0xAA,0xEE,0xAE,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xBF,0xBB,0xBB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBB,0xBB,0xBB,0xBB,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEF,0xFE,0xEF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFE,0xEF,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xBB,0xBB,0xBB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBB,0xBB,0xBB,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF6,0xAA,0xEE,0xAA,0xAA,0xAA,0xEA,0xAB,0xBB,0xBB,0xFF,0xBB,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFB,0xBF,0xFF,0xFF,0xBB,0xBB,0xEA,0xAE,0xAA,0xAA,0xAF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xBB,0xBF,0xFF,0xFB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBB,0xBB,0xBB,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xEF,0xEF,0xEE,0xEE,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xEE,0xFF,0xEF,0xEE,0xEE,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBB,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF7,0xEA,0xAA,0xBB,0xBB,0xBB,0xBB,0xBB,0xFB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFB,0xFB,0xBB,0xBB,0xBA,0xAA,0xAA,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBB,0xBB,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xFE,0xEE,0xEE,0xEE,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xEE,0xEF,0xFE,0xEE,0xEE,0xEE,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xBB,0xFB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBB,0xBB,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEA,0xAB,0xAA,0xAB,0xBB,0xBB,0xBF,0xBF,0xFF,0xFF,0xFF,0x80,0x00,0x7F
+                fcb 0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xFF,0xBB,0xBB,0xBF,0xAA,0xAA,0xAA,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBB,0xBB,0xBF,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xEF,0xEE,0xFF,0xFF,0xFF,0xEE,0xFF,0xFF,0x80,0x00,0x3F
+                fcb 0xFF,0xFF,0x80,0x00,0x3F,0xFF,0xFF,0xEE,0xFE,0xEE,0xEE,0xEE,0xEE,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBB,0xBB,0xBF,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xAB,0xAE,0xEB,0xBB,0xBF,0xFB,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x1F
+                fcb 0xFF,0xFF,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xBB,0xBB,0xAA,0xAA,0xBE,0xAB,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xBF,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFB,0xBB,0xBB,0xBF,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xEE,0xEE,0xEF,0xFE,0xEF,0xFF,0xFF,0xFF,0x80,0x00,0x0F
+                fcb 0xFF,0xFE,0x00,0x00,0x3F,0xFF,0xFF,0xEF,0xEF,0xEE,0xEE,0xEE,0xEE,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xBF,0xFB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0xFF,0xBB,0xBF,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEA,0xAB,0xBA,0xAB,0xBB,0xFB,0xFF,0xBF,0xFF,0xFF,0xFF,0x80,0x00,0x07
+                fcb 0xFF,0xFC,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xFB,0xAA,0xFF,0xFE,0xEA,0xAB,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xBF,0xFB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBF,0xFF,0xBB,0xBF,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0xFF,0xFE,0xEE,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x03
+                fcb 0xFF,0xF8,0x00,0x00,0x3F,0xFF,0xFF,0xFE,0xEE,0xEE,0xFF,0xFE,0xEE,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xBB,0xBF,0xFF,0xBB,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xAA,0xFB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x01
+                fcb 0xFF,0xF0,0x00,0x00,0x3F,0xFF,0xFF,0xBB,0xBB,0xAE,0xBB,0xBE,0xAF,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xFF,0xFF,0xBB,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x80,0x08,0x00
+                fcb 0xFF,0xE0,0x02,0x00,0x3F,0xFF,0xFF,0xFE,0xEF,0xEE,0xFF,0xEE,0xEF,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xBB,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xAA,0xBB,0xBB,0xFB,0xBB,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0x80,0x0C,0x00
+                fcb 0x7F,0xC0,0x06,0x00,0x3F,0xFF,0xFF,0xFF,0xBB,0xFF,0xFF,0xBF,0xEB,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0E,0x00
+                fcb 0x3F,0x80,0x0E,0x00,0x3F,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xEE,0xEE,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF3,0xEA,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0x00
+                fcb 0x1F,0x00,0x1E,0x00,0x3F,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xBF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xEE,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0x80
+                fcb 0x0E,0x00,0x3E,0x00,0x3F,0xFF,0xFF,0xEE,0xFF,0xFF,0xFF,0xFE,0xEF,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEA,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0xC0
+                fcb 0x00,0x00,0x7E,0x00,0x3F,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xBA,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0xE0
+                fcb 0x00,0x00,0xFE,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xEF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0xC0
+                fcb 0x00,0x00,0x3E,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xEB,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00
+                fcb 0x00,0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBA,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEF,0xFF,0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xFF,0xFF,0x80,0x0C,0x00
+                fcb 0x00,0x00,0x1E,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xEB,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFC,0x00,0x0F,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xAA,0x7F,0xFF
+                fcb 0xFF,0xF6,0xAB,0xBB,0xFF,0xFF,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0x80,0x0C,0x00
+                fcb 0x00,0x00,0x06,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x79,0x9F,0xFB,0xAB,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00
+                fcb 0x00,0x38,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x03,0xFE,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x4F,0xFF,0xFF,0xFF,0x80,0x00,0x00
+                fcb 0x01,0x7C,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0xFA,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x01,0xFF,0xFF,0xF0,0x00,0x00,0x00
+                fcb 0x03,0xFE,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x7E,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x80,0x00,0x00
+                fcb 0x0F,0xFF,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x3B,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0x00,0x00
+                fcb 0x2F,0xFF,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x0E,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFF,0x80,0x00,0x01
+                fcb 0xFF,0xFF,0x80,0x00,0x3F,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x07,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF0,0x00,0x00,0x03
+                fcb 0xFF,0xFF,0x40,0x00,0x03,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x03,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xFF,0xF0,0x00,0x00,0x00,0x01,0x00,0x1F,0xFF,0xFF,0x80,0x01,0x07
+                fcb 0xFF,0xFF,0xA0,0x00,0x3F,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x01,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x01,0x80,0x1F,0xFF,0xFF,0xFE,0x0E,0x2F
+                fcb 0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x65,0xE0,0x0F,0xFF,0xFF,0x80,0x0C,0x1F
+                fcb 0xFF,0xFF,0xE0,0x00,0x3F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3B,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xC0,0x00,0x00,0x0B,0xFF,0xF0,0x0F,0xFF,0xFC,0x00,0x18,0x0F
+                fcb 0xF8,0x00,0x60,0x00,0x07,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x0E,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xFF,0xC0,0x00,0x01,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0x80,0x00,0x01
+                fcb 0xF8,0x00,0x20,0x00,0x3F,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x1B,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x03,0x03
+                fcb 0xFF,0x7F,0xF0,0x03,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x0E,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFE,0xFF,0x80,0x01,0x5D,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xC0,0x07,0xF1
+                fcb 0xFC,0x07,0xFC,0x00,0x3F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x03,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBF,0xFF,0x00,0x02,0xEF,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0x00,0x0E,0x00
+                fcb 0x7C,0x00,0xF4,0x00,0x0C,0x7F,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x0E,0x7F,0xFF
+                fcb 0xFF,0xF2,0xAB,0xFF,0x00,0x05,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xF8,0x1C,0x00
+                fcb 0xFC,0x01,0xF8,0x01,0xFB,0xBF,0xFF,0xF8,0x00,0x00,0x0F,0xE1,0x80,0x0B,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBF,0xFF,0x00,0x03,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xF8,0x1F,0xC0
+                fcb 0xFE,0x3F,0xFC,0x01,0xF6,0xDF,0xFF,0xF8,0x00,0x3F,0xFF,0xFF,0x80,0x0E,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0x00,0x07,0xFF,0xFF,0xFF,0xFE,0x0F,0xFE,0xFF,0xFC,0x1F,0xF1
+                fcb 0xFF,0x9F,0xF8,0x37,0xF5,0xDF,0xFF,0xF8,0x00,0xFF,0xFF,0xFF,0x80,0x0B,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBF,0xFF,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xF8,0x0F,0xEF
+                fcb 0x7F,0xFF,0xFC,0x03,0xF6,0xDF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0x80,0x06,0x7F,0xFF
+                fcb 0xFF,0xF6,0xFF,0xBF,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0x07,0xFB,0xBB,0xFD,0xDF,0xFF
+                fcb 0xEF,0xFF,0xF9,0x7F,0xFB,0xBF,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xC0,0x0B,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBF,0xFE,0x00,0x03,0xFF,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xFF,0x9F,0xFF
+                fcb 0xFF,0xFF,0xFF,0xBF,0xFC,0x7F,0xFF,0xFC,0x75,0x0F,0xFF,0xCF,0xC0,0x0E,0x7F,0xFF
+                fcb 0xFF,0xF6,0xFF,0xFE,0x00,0x07,0xF5,0x47,0xFF,0xE0,0x07,0xFF,0xEF,0xFF,0xCF,0xFD
+                fcb 0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0xE0,0x07,0xC0,0x0F,0x7F,0xFF
+                fcb 0xFF,0xF7,0xBF,0xFF,0x00,0x0F,0xF8,0x07,0xFF,0xDC,0x07,0xFF,0xFF,0xFF,0xCF,0xFB
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x03,0xE0,0x0D,0x7F,0xFF
+                fcb 0xFF,0xF6,0xFF,0xFE,0x00,0x1F,0xD1,0x1F,0xFF,0xEF,0x07,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x7B,0xF0,0x0B,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBF,0xFE,0x00,0x1F,0xFF,0xEF,0xFE,0x81,0x07,0xFF,0xFF,0xFF,0x7F,0xF8
+                fcb 0x40,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x60,0x01,0xFC,0x1D,0xF0,0x0D,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xFF,0x00,0x1F,0xFF,0x01,0xFE,0x01,0x87,0xFE,0xEE,0xFF,0xFF,0xF0
+                fcb 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xE0,0x03,0xF0,0x67,0xF0,0x17,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBF,0xFE,0x00,0x1F,0xF8,0x01,0xFC,0x03,0x87,0xFF,0xFF,0xFF,0xFF,0xC0
+                fcb 0x00,0x0F,0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,0xC0,0x03,0xF0,0x33,0xF0,0x5F,0x7F,0xFF
+                fcb 0xFF,0xF6,0xAF,0xFE,0x00,0x1F,0xFF,0xF0,0xFE,0x0F,0x87,0xFF,0xBF,0xFF,0xFF,0x80
+                fcb 0xFF,0x07,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0xFA,0xFF,0xF1,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBF,0xBF,0x00,0x1F,0xFF,0xFE,0xFE,0x9B,0x87,0xFF,0xFF,0xFF,0xFF,0xBD
+                fcb 0x80,0xF3,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x17,0xFF,0xFF,0xF4,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xFF,0x00,0x1F,0xFF,0xFF,0xFF,0x03,0x87,0xEF,0xEE,0xEF,0xFF,0x00
+                fcb 0x00,0x07,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x77,0xFF,0xFF,0xFE,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBF,0xBF,0x00,0x0F,0xFF,0xEF,0xF8,0x83,0x87,0xFF,0xFF,0xFF,0xFF,0xBE
+                fcb 0xBF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0xFF,0xFD,0xB3,0xFF,0xFF,0xFD,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEF,0x00,0x0F,0xFF,0xF8,0x7F,0xF7,0x8F,0xFF,0xFB,0xBF,0xFF,0xFF
+                fcb 0xFF,0xF7,0xFC,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xBB,0x00,0x0F,0xFF,0xF3,0x7F,0x0F,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xBF,0xE3,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEF,0x00,0x0F,0xFE,0xF7,0xFF,0xCF,0x8E,0xFF,0xFF,0xEF,0xFF,0xFF
+                fcb 0x17,0xF7,0xFD,0xEF,0xEF,0xFE,0xFF,0xFF,0xFF,0x9F,0xFF,0xFF,0xFF,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xBB,0x00,0x07,0xFF,0xFE,0xFF,0xC1,0x9F,0xFF,0xFF,0xFF,0xFF,0xFE
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0xF7,0xFF,0xFE,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0x00,0x03,0xFF,0xC4,0x1C,0x03,0x9B,0xFB,0xAF,0xBF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFE,0xFB,0xFB,0xBB,0xFF,0xBF,0xFE,0x02,0xAB,0xFF,0xF8,0xFB,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBF,0xBA,0x04,0x03,0xFA,0x00,0x00,0x01,0x9F,0xFF,0xBB,0xFF,0xFB,0xFF
+                fcb 0xFF,0xFF,0xFB,0xBF,0xFF,0xFB,0xFE,0xEF,0xFC,0x00,0x05,0xFF,0xF9,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEC,0x06,0x01,0xFC,0xA2,0x00,0x03,0x9F,0xEE,0xEE,0xEF,0xFE,0xFF
+                fcb 0xFF,0xFF,0xFE,0xFF,0xFE,0xEE,0xEF,0xBF,0xFE,0x00,0x00,0x3F,0xFB,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xB0,0x00,0x01,0xFA,0x10,0x00,0x03,0x9F,0xFB,0xBB,0xFF,0xFB,0xFF
+                fcb 0xFF,0xFF,0xFB,0xBF,0xFF,0xFB,0xBE,0xEF,0xFC,0x0F,0x80,0x1F,0xF6,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0x00,0x00,0x68,0x5F,0xFE,0x03,0x1B,0xAE,0xAE,0xFB,0xEE,0xFD
+                fcb 0xFF,0xFF,0xFE,0xAB,0xBB,0xEA,0xFF,0xBF,0xF8,0x0B,0xFC,0x1F,0xFF,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0xBA,0x00,0x00,0x7B,0x0F,0xFE,0x00,0x1F,0xBB,0xBB,0xFF,0xFB,0xFF
+                fcb 0xFF,0xFF,0xFB,0xBB,0xFF,0xBB,0xBE,0xEF,0xFC,0x07,0xFC,0x5F,0xF6,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0xEE,0x00,0x00,0x14,0x40,0x3C,0x00,0x0E,0xEE,0xEE,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFE,0xEE,0xEE,0xEE,0xEF,0xBF,0xFE,0x00,0x61,0xFF,0xFF,0xBB,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBB,0x80,0x00,0x00,0x00,0x7E,0x00,0x00,0x3F,0xBB,0xFF,0xFF,0xBF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xBB,0xFF,0xBB,0xBE,0xEF,0xFF,0xE0,0x07,0xFF,0xFF,0xEE,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEE,0x00,0x00,0x00,0x00,0x3F,0xEE,0x80,0x2E,0xAB,0xBF,0xBE,0xFC,0xFF
+                fcb 0xFF,0xFF,0xFE,0xEB,0xBB,0xAA,0xBB,0xBF,0xEF,0xFA,0xFF,0xFF,0xF8,0x0B,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBA,0x00,0x00,0xC0,0x00,0x0F,0xFE,0x00,0x3B,0xBF,0xFF,0xFB,0xB1,0xFF
+                fcb 0xFF,0xFF,0xF3,0xBB,0xFF,0xBB,0xAE,0xEF,0xBF,0xD9,0x7F,0xFF,0xF8,0x02,0x7F,0xFF
+                fcb 0xFF,0xF6,0xEC,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0xEE,0xEE,0xEF,0xEE,0xE1,0xFF
+                fcb 0xFF,0xFF,0xF0,0xEE,0xEE,0xEE,0xEB,0xBF,0xEF,0x8E,0x3F,0xFF,0xF8,0x00,0x7F,0xFF
+                fcb 0xFF,0xF3,0xBA,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0xBB,0xBB,0xBF,0xBB,0xB1,0xFF
+                fcb 0xFF,0xFF,0xE0,0x3B,0xFF,0xBB,0xEE,0xFF,0xBB,0x00,0x5F,0xFF,0xF8,0x00,0x7F,0xFF
+                fcb 0xFF,0xF6,0xE0,0x04,0x00,0x78,0x00,0x00,0x00,0x01,0xEE,0xAA,0xAE,0xEA,0xC0,0x7F
+                fcb 0xFF,0xFF,0x80,0x0B,0xFF,0xEF,0xAB,0xFF,0xEF,0xC2,0x3F,0xFF,0xFF,0xE0,0x7F,0xFF
+                fcb 0xFF,0xF3,0x80,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x3B,0xBB,0xBB,0xBB,0x00,0x3F
+                fcb 0xFF,0xFF,0x00,0x03,0xFF,0xFE,0xEE,0xEF,0xBB,0xC0,0x7F,0xFF,0xFE,0xF8,0x7F,0xFF
+                fcb 0xFF,0xF6,0x60,0xC0,0x00,0x7F,0x00,0x00,0x00,0x00,0x2E,0xEE,0xEE,0xEC,0x00,0x01
+                fcb 0x3F,0xFC,0x00,0x00,0x6E,0xEF,0xFF,0xFB,0xEE,0xE2,0x3F,0xFF,0xFE,0x78,0x7F,0xFF
+                fcb 0xFF,0xF0,0x98,0x60,0x00,0x3F,0x80,0x00,0x00,0x00,0x03,0xBB,0xBB,0xB8,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x01,0xBB,0xBB,0xBA,0xBB,0x5F,0x9F,0xFF,0xFC,0xF8,0x7F,0xFF
+                fcb 0xFF,0xF6,0x00,0x30,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x6A,0xEE,0xA0,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFA,0xEE,0x83,0xFF,0xFF,0xFC,0xF8,0x7F,0xFF
+                fcb 0xFF,0xF4,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x05,0x13,0xBB,0x80,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x2E,0xEE,0xEA,0x9B,0xA3,0xFF,0xFF,0xFD,0xF0,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0x0E,0xEE,0x80,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x2F,0xFE,0xAA,0x0E,0xED,0xFF,0xFF,0xF9,0xF0,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x03,0xBB,0x80,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x0A,0xBA,0xA8,0x0B,0xFB,0x7F,0xFF,0xF3,0xF0,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x02,0x8A,0x80,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x02,0xFE,0xA0,0x06,0xFE,0xFF,0xFF,0x07,0xF0,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x00,0x07,0x03,0x80,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x02,0xAA,0x80,0x07,0xF9,0xFF,0xFC,0x07,0xF4,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x0F,0x14,0x0E,0x00,0x00,0x02,0x80,0x80,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0x80,0xBF,0xFF,0xBF,0xF0,0x0F,0xF6,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x03,0xFF,0xFC,0x00,0x00,0x03,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0xEA,0x0F,0xFE,0x7C,0x77,0x80,0x1F,0xF6,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x7F,0xFC,0xFE,0x80,0x00,0x1F,0xF7,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x03,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x37,0x3C,0xFE,0xC0,0x00,0xBF,0xF7,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x07,0x7F,0xE0,0x00,0x00,0xF3,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3E,0xFF,0x80,0x01,0xFF,0xF7,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0xA3,0xFF,0xC0,0x00,0x00,0x63,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFD,0xEE,0x80,0x07,0xFF,0xF7,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x63,0xFF,0xC0,0x00,0x00,0x73,0x00,0x00,0x00,0x00
+                fcb 0xFF,0x00,0x00,0x00,0x00,0x00,0x08,0x1F,0x78,0xF7,0xE8,0x9F,0xFF,0xFC,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x77,0xBF,0x80,0x00,0x00,0x33,0x00,0x00,0x00,0x3F
+                fcb 0xBB,0xE0,0x00,0x00,0x00,0x00,0x00,0x1F,0xF8,0x3B,0x55,0x7F,0x80,0x70,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x01,0xFF,0x00,0x00,0x00,0x3B,0x00,0x00,0x00,0xFF
+                fcb 0x3B,0xFC,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0x1D,0x8E,0xE7,0x82,0xF8,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x30,0x00,0x00,0x01,0xFE
+                fcb 0xF9,0x9F,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xC1,0x17,0xFF,0xFF,0xC0,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0xF8
+                fcb 0xFF,0x3F,0xE0,0x00,0x04,0x00,0x00,0x0F,0xBF,0xC2,0xEF,0xFF,0xFF,0x80,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x1C,0x00,0x00,0x08,0xFB
+                fcb 0xFF,0x37,0xE0,0x00,0x00,0x00,0x00,0x0F,0xBF,0xC1,0x1F,0xFF,0xFF,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x1D,0x07
+                fcb 0xFF,0xE3,0x68,0x00,0x00,0x00,0x00,0x07,0x7F,0xC7,0x3F,0xFF,0xFE,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F
+                fcb 0xFF,0xFB,0xF6,0x00,0x00,0x00,0x00,0x07,0x7F,0xE1,0x7F,0xFF,0xFC,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x01,0xC6,0x7F
+                fcb 0xFF,0xFF,0xE8,0x00,0x00,0x00,0x00,0x07,0x0F,0xF3,0x8F,0x97,0xFC,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xB1,0xEF
+                fcb 0xFF,0xEF,0xB7,0x00,0x00,0x00,0x00,0x07,0x83,0xE1,0xC6,0x00,0x78,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xDF
+                fcb 0xFF,0xD1,0xA2,0x00,0x00,0x40,0x00,0x03,0x00,0xF1,0xFF,0x14,0x20,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF
+                fcb 0xFF,0xFF,0xDF,0x00,0x00,0x00,0x00,0x03,0x06,0x70,0x7C,0x00,0xC0,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF
+                fcb 0xFF,0xFF,0xE7,0xE0,0x00,0x00,0x00,0x03,0x87,0xF1,0xF8,0x03,0x80,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0xAF
+                fcb 0xFF,0xFF,0xF7,0x00,0x00,0x00,0x00,0x03,0x8F,0xFB,0xF8,0x20,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xBF
+                fcb 0xFF,0xFF,0xBF,0xE0,0x00,0x00,0x00,0xF3,0x8D,0xFF,0xF8,0x5F,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0xFF
+                fcb 0xFF,0xFF,0x4F,0xF0,0x00,0x00,0x01,0xE3,0x87,0xFF,0xFC,0x6E,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0xF7
+                fcb 0xBF,0xFF,0xEF,0xE8,0x00,0x00,0x00,0x01,0x1F,0xFF,0xFF,0xFE,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0xFF
+                fcb 0x9F,0xFF,0xFD,0xF8,0x00,0x00,0x00,0x01,0xBF,0xFF,0xFF,0xFF,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
+                fcb 0xFF,0xFF,0x8F,0xE8,0x00,0x00,0x00,0x01,0xBF,0xFF,0xFF,0xFC,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
+                fcb 0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x01,0xBF,0xFF,0xFF,0xF8,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
+                fcb 0xFF,0x9F,0xFF,0xF8,0x00,0x00,0x00,0x01,0x3F,0xFF,0xFF,0xF0,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x07,0xFF
+                fcb 0x1F,0xFF,0xF5,0xFC,0x00,0x00,0x00,0x01,0x3F,0xFF,0xFF,0xE0,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFC
+                fcb 0x3F,0xFF,0xBF,0xF8,0x00,0x00,0x00,0x01,0x3F,0x85,0xFF,0xC0,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF
+                fcb 0xF7,0xFF,0xDF,0xF8,0x00,0x00,0x00,0x00,0x1D,0x2A,0x07,0x80,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
+                fcb 0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x01,0x06,0xFF,0x00,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x1F,0xFF
+                fcb 0xFF,0xFF,0xDF,0xF8,0x00,0x00,0x00,0x01,0x17,0x3D,0x95,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x80,0x00,0x07,0xFF
+                fcb 0xFF,0xFF,0xEF,0xF8,0x00,0x00,0x00,0x00,0x0E,0xEF,0xDA,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF
+                fcb 0xFF,0xFF,0xF7,0xF0,0x00,0x00,0x00,0x00,0x15,0xF7,0x80,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF
+                fcb 0xFF,0xFF,0xED,0xE0,0x00,0x00,0x00,0x00,0x0F,0xBF,0xEC,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
+                fcb 0xFF,0xFF,0xDC,0xE0,0x00,0x00,0x00,0x00,0x17,0x7F,0xD8,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
+                fcb 0xFF,0xFF,0xBC,0xC0,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF
+                fcb 0xFF,0xFF,0xDE,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF
+                fcb 0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF
+                fcb 0xFF,0xFB,0xFF,0x80,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xDF
+                fcb 0xFE,0xC1,0xF2,0x00,0x00,0x00,0x00,0x18,0x7F,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83
+                fcb 0x00,0x1F,0xCC,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00
+                fcb 0x80,0x3F,0x98,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2
+                fcb 0x46,0x3E,0x60,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xE0,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80
+                fcb 0x33,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x60,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0
+                fcb 0x73,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x3A,0x80,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0
+                fcb 0x08,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xF6,0x00,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xB6,0x00,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xED,0x80,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x2C,0x00,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xB0,0x80,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0x00,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x7F,0xFF,0xC0,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0x3C,0xFF,0xF3,0x3F,0xFF,0xCF,0x9F,0xFF,0xFF,0xFF,0x03,0xFF
+                fcb 0xCC,0xFF,0xFF,0xF3,0xFF,0xFF,0xF8,0x1F,0xFE,0x0F,0xFF,0x8F,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0x18,0xFF,0xF3,0x3F,0xFF,0xCF,0xFF,0xFF,0xFF,0xFF,0xCF,0xFF
+                fcb 0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F,0xFE,0x7F,0xFF,0xCF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0x00,0xFF,0xF3,0x31,0x9E,0x49,0x10,0xE1,0xFF,0xFF,0xCF,0xFF
+                fcb 0xCC,0xC6,0x08,0x23,0x0F,0xFF,0xFE,0x7F,0xFE,0x7C,0x60,0xCC,0x70,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0x24,0xFF,0xF0,0x3C,0xC0,0xC3,0x92,0x4F,0xFF,0xFF,0xCF,0xFF
+                fcb 0xC0,0xF2,0x38,0xF2,0x7F,0xFF,0xFE,0x7F,0xFE,0x1F,0x23,0xC9,0x27,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0x3C,0xFF,0xF3,0x30,0xC0,0xC7,0x92,0x63,0xFF,0xFF,0xCF,0xFF
+                fcb 0xCC,0xC2,0x79,0xF3,0x1F,0xFF,0xFE,0x7F,0xFE,0x7C,0x27,0xC8,0x31,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0x3C,0xFF,0xF3,0x24,0xE1,0xC3,0x92,0x79,0xFF,0xFF,0xCF,0xFF
+                fcb 0xCC,0x92,0x79,0xF3,0xCF,0xFF,0xFE,0x7F,0xFE,0x79,0x27,0xC9,0xFC,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0x3C,0x9F,0xF3,0x30,0xE1,0xC9,0x92,0x43,0xFF,0xFF,0xCE,0x7F
+                fcb 0xCC,0xC2,0x79,0xF2,0x1F,0xFF,0xFE,0x73,0xFE,0x0C,0x27,0xCC,0x61,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
+                fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+AUTHPICe        equ *
+; Unused
+                fcb 0xFF,0x00,0x00,0xA0,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
+                fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x40,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; The actual Super Extended Basic (SECB) extensions start here.
+;
+; Note that many routines in this area feature a "lbrn 0" instruction. This appears to be intended as a placeholder to allow
+; patching into the routines similar to the RAM hooks in Color Basic except using direct overwiting of the instruction. It's
+; completely pointless and probably illustrates that the writers of this code didn't really think through what they were doing.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+SUPERVAR        fdb HRMODE                      ; address of direct page variables unique to SECB
+PRGTEXT         fdb SETTEXT                     ; set video registers for text mode (indirect)
+PRGGRAPH        fdb SETGRAPH                    ; set video registers for graphics mode (indirect)
+PRGMMU          fdb SETMMU                      ; set MMU registers to their "default" (indirect)
+GETTEXT         fdb SELTEXT                     ; put hi-res text screen in logical block 1 (indirect)
+GETBLOK0        fdb SELBLOK0                    ; put block in B in logical block 0 (indirect)
+GETTASK0        fdb SELTASK0                    ; re-select MMU task 0 (indirect)
+GETTAKS1        fdb SELTASK1                    ; select MMU task 1(indirect)
+                jmp LA05E                       ; execute non-self starting ROM
+SPARE0          fdb 0                           ; undefined
+SPARE1          fdb 0                           ; undefined
+SPARE2          fdb 0                           ; undefined
+; Set up video registers for the selected text screen. Given that the sets of video mode initializers are contiguous in
+; memory, this would probably be better done with a simple sequence of MUL and ABX.
+SETTEXT         pshs y,x,a                      ; save registers
+                lbrn 0
+                ldx #IM.TEXT                    ; point to 32 column video mode registers
+                lda HRWIDTH                     ; get text mode
+                beq SETVIDEO                    ; brif 32 column
+                ldx #SE03B                      ; point to 40 column mode data
+                cmpa #1                         ; is it 40 column?
+                beq SETVIDEO                    ; brif so
+                ldx #SE044                      ; assume 80 column
+                bra SETVIDEO                    ; program video registers
+; 32 column (VDG) initializer
+IM.TEXT         fcb COCO+MMUEN+MC3+MC2          ; INIT0 (COCO bit enables VDG modes)
+                fcb 0x00                        ; VIDEOMOD (unused for VDG modes)
+                fcb 0x00                        ; VIDEORES (unused for VDG modes)
+                fcb 0x00                        ; V.BORDER (black)
+                fcb 0x00                        ; filler for reserved
+                fcb 0x0f                        ; V.SCROLL - this value is needed to show a proper 12 lines per text row
+                fdb 0xe000                      ; V.OFFSET - SAM offsets operate in 0x7xxx
+                fcb 0x00                        ; H.OFFSET - no horizontal offset
+; 40 column screen
+SE03B           fcb MMUEN+MC3+MC2               ; INIT0 (disable VDG modes)
+                fcb 0x03                        ; VIDEOMOD - 8 lines per row
+                fcb 0x05                        ; VIDEORES - 40 columns, attributes enabled, 192 lines per field
+                fcb 0x12                        ; V.BORDER - nuclear green
+                fcb 0x00                        ; filler for reserved
+                fcb 0x00                        ; V.SCROLL - no offset
+                fdb 0xd800                      ; V.OFFSET - screen at 0x6c000
+                fcb 0x00                        ; H.OFFSET - no offset
+; 80 column screen
+SE044           fcb MMUEN+MC3+MC2               ; INIT0 (disable VDG modes)
+                fcb 0x03                        ; VIDEOMOD - 8 lines per row
+                fcb 0x15                        ; VIDEORES - 80 columns, attributes enabled, 192 lines per field
+                fcb 0x12                        ; V.BORDER - nuclear green
+                fcb 0x00                        ; filler for reserved
+                fcb 0x00                        ; V.SCROLL - no offset
+                fdb 0xd800                      ; V.OFFSET - screen at 0x6c000
+                fcb 0x00                        ; H.OFFSET - no offset
+; Set up video registers for the selected "HSCREEN" mode. Note that the two code paths for the resolution widths
+; are unneeded.
+SETGRAPH        pshs y,x,a                      ; save registers
+                lbrn 0
+                ldx #IM.GRAPH                   ; point to graphics initlializer
+                ldy #RESTABLE                   ; point to resolution bytes table
+                lda HRMODE                      ; get graphics mode
+                cmpa #2                         ; is it a 640 pixel mode?
+                bls SE063                       ; brif not
+                ldx #SE079                      ; point to 640 pixel registers
+SE063           suba #1                         ; normalize mode numbers to start at 0
+                lda a,y                         ; get resolution setting for this mode
+                sta 2,x                         ; put it in the graphics mode initializer
+                jmp SETVIDEO                    ; go set up video registers
+RESTABLE        fcb 0x15                        ; 320x192, 4 colours
+                fcb 0x1e                        ; 320x192, 16 colours
+                fcb 0x14                        ; 640x192, 2 colours
+                fcb 0x1d                        ; 640x192, 4 colours
+; 320x192 graphics modes
+IM.GRAPH        fcb MMUEN+MC3+MC2               ; INIT0 (disable VDG modes)
+                fcb 0x80                        ; VIDEOMOD - enable bit plane, one line per row
+                fcb 0x00                        ; VIDEORES - placeholder
+                fcb 0x00                        ; V.BORDER - black
+                fcb 0x00                        ; filler for reserved
+                fcb 0x00                        ; V.SCROLL - no offset
+                fdb 0xc000                      ; V.OFFSET - screen at 0x60000
+                fcb 0x00                        ; H.SCROLL - no offset
+; 640x192 graphics modes (observe that these are identical to the 320x192 ones above)
+SE079           fcb MMUEN+MC3+MC2               ; INITo (disable VDG modes)
+                fcb 0x80                        ; VIDEOMOD - enable bit plane, one line per row
+                fcb 0x00                        ; VIDEORES - placeholder
+                fcb 0x00                        ; V.BORDER - black
+                fcb 0x00                        ; filler for reserved
+                fcb 0x00                        ; V.SCROLL - no offset
+                fdb 0xc000                      ; V.OFFSET - screen at 0x60000
+                fcb 0x00                        ; H.SCROLL - no offset
+; Program video registers and INIT0 from (X); enter with A,X,Y pre-saved
+SETVIDEO        lda ,x+                         ; set INIT0
+                sta INIT0
+                ldy #VIDEOMOD                   ; point to start of video mode registers
+SE08B           lda ,x+                         ; set a register
+                sta ,y+
+                cmpy #MMUREG                    ; done all of them?
+                blo SE08B                       ; brif not
+                puls a,x,y,pc                   ; restore registers and return
+; Set MMU registers to their default values. All 16 of them.
+SETMMU          pshs y,x,b,a                    ; save registers
+                leax IM.MMU,pcr                 ; point to MMU initializer
+                bsr SE0F1                       ; program MMU registers
+                puls a,b,x,y,pc                 ; restore registers and return
+; Set logical block 0 to the physical block in B. This is embarassingly inefficient since it sets
+; *all 16* MMU registers to change one of them. All the faffing about with pointers and the call
+; to set the MMU registers is pointless. It could be done with a single STB.
+SELBLOK0        pshs y,x,b,a                    ; save registers
+                leax IM.MMU,pcr                 ; point to MMU initializer
+                pshs x                          ; save it for later
+                stb ,x                          ; set desired block in initializer
+                bsr SE0F1                       ; program *all 16* MMU registers (stupid)
+                ldb #BLOCK7.0                   ; get correct block number for logical block 0
+                puls x                          ; get back pointer to the initializer
+                stb ,x                          ; restore initializer value
+                puls a,b,x,y,pc                 ; restore registers and return
+; Put hi-res text screen in logical address space block 1. This is embarassingly ineffecient since
+; it sets *all 16* MMU registers to change only one. All the faffing about with pointers and the
+; call to set the MMU registers is pointless. It could be done with a singel LD/ST sequence.
+SELTEXT         pshs y,x,b,a                    ; save registers
+                leax IM.MMU,pcr                 ; point to MMU initializer
+                pshs x                          ; save pointer for later
+                ldb #BLOCK6.6                   ; get block number for text screen
+                stb 1,x                         ; put in logical block 1 of initializer
+                bsr SE0F1                       ; program *all 16* MMU registers (stupid)
+                puls x                          ; get back pointer
+                ldb #BLOCK7.1                   ; get proper block for logical block 1
+                stb 1,x                         ; put it back in the initializer
+                puls a,b,x,y,pc                 ; restore registers and return
+; Get block 6.4 (HBUFF buffers) to logical block 6 of task 1. This is embarassingly inefficient
+; since it sets *all 16* MMU registers to change only one. All the faffing about with pointers and
+; the call to set the MMU registers ispointless. It could be done with a single LD/ST sequence.
+SE0CB           pshs y,x,b,a                    ; save registers
+                leax IM.MMU,pcr                 ; point to MMU initializer
+                pshs x                          ; save pointer for later
+                ldb #BLOCK6.4                   ; get block for the HBUFF buffers
+                stb 14,x                        ; put in logical block 6, task 1
+                bsr SE0F1                       ; program *all 16* MMU registers (stupid)
+                puls x                          ; get back pointer
+                ldb #BLOCK6.5                   ; get default block for logical block 6 of task 1
+                stb 14,x                        ; put it back in the initializer
+                puls a,b,x,y,pc                 ; restore registers and return
+; MMU initializer
+IM.MMU          fcb BLOCK7.0,BLOCK7.1,BLOCK7.2,BLOCK7.3         ; task 0: map 0x70000-0x7ffff
+                fcb BLOCK7.4,BLOCK7.5,BLOCK7.6,BLOCK7.7
+                fcb BLOCK7.0,BLOCK6.0,BLOCK6.1,BLOCK6.2         ; task 1: put hires gfx at 0x2000 and a stack block at 0xc000
+                fcb BLOCK6.3,BLOCK7.5,BLOCK6.5,BLOCK7.7
+; Set all 16 MMU registers from the initializer pointed to by X.
+SE0F1           ldy #MMUREG                     ; point to MMU registers
+                ldb #16                         ; there are 16 to set
+SE0F7           lda ,x+                         ; set a register
+                sta ,y+
+                decb                            ; done all?
+                bne SE0F7                       ; brif not
+                rts
+; Select task register 0 as the active MMU set. Enter with stack in a temporary location which
+; holds the original stack pointer. Note that the return could be done simply as jmp [V42] instead
+; of pushing the return address onto the stack. Interrupts will be enabled on the way out.
+SELTASK0        std V40                         ; temp save D
+                ldd ,s                          ; get return address
+                std V42                         ; save it
+                ldd 2,s                         ; get original stack pointer
+                std V44                         ; save it
+                clrb                            ; reset INIT1 to task 0 (and slow timer), could just be CLR INIT1
+                stb INIT1
+                lds V44                         ; restore original stack pointer
+                ldd V42                         ; get back return address
+                pshs d                          ; set return address on stack
+                ldd V40                         ; get back original D
+                andcc #0xaf                     ; re-enable interrupts
+                rts
+; Select task register 1 as the active MMU set. Exit with interrupts disabled and the original
+; stack pointer saved at the top of the temporary stack. Note that jmp [V42] could be used to
+; return instead of pushing the return address back on the stack.
+SELTASK1        orcc #0x50                      ; disable interrupts
+                std V40                         ; temp save D
+                puls d                          ; get return address
+                std V42                         ; save it
+                sts V44                         ; save stack pointer
+                ldb #1                          ; set to enable task 1, slow timer input
+                stb INIT1
+                lds #TMPSTACK                   ; point to temporary stack location (top of the C000-Dfff range)
+                ldd V44                         ; get old stack pointer
+                pshs d                          ; stash it
+                ldd V42                         ; put original return address back
+                pshs d
+                ldd V40                         ; restore original D
+                rts
+; Tokenziation patch
+ALINK2          tst V41                         ; is it a function token?
+                bne SE152                       ; brif so
+                lda V42                         ; get token value
+                cmpa #0x62                      ; have we reached the first SECB token?
+                bls SE148                       ; brif not
+                ldu #COMVEC-5                   ; point to function table and go again
+                jmp LB8D7                       ; re-enter mainline code
+SE148           lda #0x62                       ; force tokens to start at the correct number (above Disk Basic)
+                ldu #EBCOMTAB-10                ; point to SECB command table
+SE14D           sta V42                         ; set token counter to SECB values
+                jmp LB89D                       ; re-enter mainstream still in command mode
+SE152           lda V42                         ; get token number
+                cmpa #0x29                      ; have we run through SECB functions yet?
+                bls SE15B                       ; brif not
+                jmp LB8D7                       ; re-enter mainline code (end of processing)
+SE15B           lda #0x29                       ; force token into SECB range (this leaves one unused)
+                ldu #EBCOMTAB-5                 ; point to SECB function table
+                bra SE14D                       ; go transfer control back to mainline with new settings
+EBCOMTAB        fcb 23                          ; number of keywords (commands)
+                fdb COMDIC20                    ; keyword table (commands)
+                fdb ALINK4                      ; interpretation handler (commands)
+                fcb 5                           ; number of keywords (functions)
+                fdb FUNDIC20                    ; keyword table (functions)
+                fdb ALINK5                      ; interpretation handler (functions)
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00 ; marker for no further tables
+; Detokenization patch. This routine has a bug. It freezes if an unknown token is encountered instead
+; of using the placeholder.
+ALINK3          leau 10,u                       ; move to next table
+                tst ,u                          ; valid table?
+                lbne LB7F9                      ; brif so - re-enter mainline code
+                leax -1,x                       ; get token number
+                lda ,x+
+                anda #0x7f                      ; remove token bias
+                cmpa #0x62                      ; SECB command?
+                blo SE18B                       ; brif not
+                suba #0x62                      ; zero-base SECB token number
+                ldu #EBCOMTAB-10                ; point to command table
+                bra ALINK3                      ; go try again
+SE18B           suba #0x29                      ; zero-base function token
+                ldu #EBCOMTAB-5                 ; point to SECB function table
+                bra ALINK3                      ; go try again
+; Command interpretation patch
+ALINK4          cmpa #0xe2                      ; is it within the SECB range?
+                blo SE19A                       ; brif not (below)
+                cmpa #0xf8                      ; is it above range?
+                bls SE19E                       ; brif not - we have a SECB command
+SE19A           jmp [COMVEC+23]                 ; transfer control onward to Disk Basic
+SE19E           suba #0xe2                      ; normalize SECB commands to 0
+                ldx #COMDIS20                   ; point to jump table for SECB commands
+                jmp LADD4                       ; go dispatch command
+; Function processing patch
+ALINK5          cmpb #0x29*2                    ; is it an SECB function?
+                blo SE1AE                       ; brif not (below)
+                cmpb #0x2d*2                    ; is it still an SECB function?
+                bls SE1B2                       ; brif so
+SE1AE           jmp [COMVEC+28]                 ; transfer control to Disk Basic
+SE1B2           subb #0x29*2                    ; normalize SECB functions to 0
+                cmpb #2*2                       ; do we need to parse a parameter?
+                bhs SE1BF                       ; brif not
+                pshs b                          ; save token offset
+                jsr LB262                       ; parse parenthetical expression
+                puls b                          ; get back token offset
+SE1BF           ldx #FUNDIS20                   ; point to jump table for SECB functions
+                jmp LB2CE                       ; go dispatch function call
+; Keyword table (commands) for SECB
+COMDIC20        fcs 'WIDTH'                     ; 0xe2
+                fcs 'PALETTE'                   ; 0xe3
+                fcs 'HSCREEN'                   ; 0xe4
+                fcs 'LPOKE'                     ; 0xe5
+                fcs 'HCLS'                      ; 0xe6
+                fcs 'HCOLOR'                    ; 0xe7
+                fcs 'HPAINT'                    ; 0xe8
+                fcs 'HCIRCLE'                   ; 0xe9
+                fcs 'HLINE'                     ; 0xea
+                fcs 'HGET'                      ; 0xeb
+                fcs 'HPUT'                      ; 0xec
+                fcs 'HBUFF'                     ; 0xed
+                fcs 'HPRINT'                    ; 0xee
+                fcs 'ERR'                       ; 0xef
+                fcs 'BRK'                       ; 0xf0
+                fcs 'LOCATE'                    ; 0xf1
+                fcs 'HSTAT'                     ; 0xf2
+                fcs 'HSET'                      ; 0xf3
+                fcs 'HRESET'                    ; 0xf4
+                fcs 'HDRAW'                     ; 0xf5
+                fcs 'CMP'                       ; 0xf6
+                fcs 'RGB'                       ; 0xf7
+                fcs 'ATTR'                      ; 0xf8
+; Jump table for SECB commands
+COMDIS20        fdb WIDTH                       ; 0xe2 WIDTH
+                fdb PALETTE                     ; 0xe3 PALETTE
+                fdb HSCREEN                     ; 0xe4 HSCREEN
+                fdb LPOKE                       ; 0xe5 LPOKE
+                fdb HCLS                        ; 0xe6 HCLS
+                fdb HCOLOR                      ; 0xe7 HCOLOR
+                fdb HPAINT                      ; 0xe8 HPAINT
+                fdb HCIRCLE                     ; 0xe9 HCIRCLE
+                fdb HLINE                       ; 0xea HLINE
+                fdb HGET                        ; 0xeb HGET
+                fdb HPUT                        ; 0xec HPUT
+                fdb HBUFF                       ; 0xed HBUFF
+                fdb HPRINT                      ; 0xee HPRINT
+                fdb ERR                         ; 0xef ERR (should be LB277)
+                fdb BRK                         ; 0xf0 BRK (should be LB277)
+                fdb LOCATE                      ; 0xf1 LOCATE
+                fdb HSTAT                       ; 0xf2 HSTAT
+                fdb HSET                        ; 0xf3 HSET
+                fdb HRESET                      ; 0xf4 HRESET
+                fdb HDRAW                       ; 0xf5 HDRAW
+                fdb CMP                         ; 0xf6 CMP
+                fdb RGB                         ; 0xf7 RGB
+                fdb ATTR                        ; 0xf8 ATTR
+; Keyword table for SECB functions
+FUNDIC20        fcs 'LPEEK'                     ; 0xa9
+                fcs 'BUTTON'                    ; 0xaa
+                fcs 'HPOINT'                    ; 0xab
+                fcs 'ERNO'                      ; 0xac
+                fcs 'ERLIN'                     ; 0xad
+; Jump table for SECB functions
+FUNDIS20        fdb LPEEK                       ; 0xa9 LPEEK
+                fdb BUTTON                      ; 0xaa BUTTON
+                fdb HPOINT                      ; 0xab HPOINT
+                fdb ERNO                        ; 0xac ERNO
+                fdb ERLIN                       ; 0xad ERLIN
+; Signon message patch
+ALINK12         ldx #L80E8-1                    ; point to ECB's message
+                jsr STRINOUT                    ; display it
+                ldx #MWAREMS-1                  ; point to Microware string
+                jsr STRINOUT                    ; display it
+                jmp L80B8                       ; return to mainline code
+; Signon message patch for Disk Basic 1.0
+ALINK28         ldx #DISK20MS-1                 ; point to modified message
+                jmp DC0DC-19                    ; return to mainline code
+; Signon message patch for Disk Basic 1.1
+ALINK29         ldx #DISK21MS-1                 ; point to modified message
+                jmp DC0DC                       ; return to mainline code
+DISK20MS        fcc 'DISK EXTENDED COLOR BASIC 2.0'
+                fcb 0x0d
+                fcc 'COPR. 1981, 1986 BY TANDY'
+                fcb 0x0d
+                fcc 'UNDER LICENSE FROM MICROSOFT'
+                fcb 0x0d
+MWAREMS         fcc 'AND MICROWARE SYSTEMS CORP.'
+                fcb 0x0d,0x0d,0x00
+DISK21MS        fcc 'DISK EXTENDED COLOR BASIC 2.1'
+                fcb 0x0d
+                fcc 'COPR. 1982, 1986 BY TANDY'
+                fcb 0x0d
+                fcc 'UNDER LICENSE FROM MICROSOFT'
+                fcb 0x0d
+                fcc 'AND MICROWARE SYSTEMS CORP.'
+                fcb 0x0d,0x0d,0x00
+; Extended Basic extra initialization patch
+ALINK14         clra                            ; set up to clear things
+                clrb
+                lbrn 0
+                stb H.CRSATT                    ; reset cursor attributes
+                std HRMODE                      ; reset to VDG screen and no HSCREEN graphics
+                std H.ONBRK                     ; reset ON BRK destination
+                std H.ONERR                     ; reset ON ERR destinatin
+                sta H.BCOLOR                    ; default HSCREEN background to 0
+                lda #1                          ; default HSCREEN foreground to 1
+                sta H.FCOLOR
+                lda #BLOCK6.4                   ; map the HGET/HPUT buffers
+                sta MMUREG
+                ldd #0xffff                     ; mark as empty
+                std 0
+                lda #BLOCK7.0                   ; restore memory map
+                sta MMUREG
+                jmp LAD19                       ; go finish initializing (NEW)
+; ON command patch
+ALINK18         cmpa #0xef                      ; ERR?
+                beq ERR                         ; brif so
+                cmpa #0xf0                      ; BRK?
+                beq BRK                         ; brif so
+                jsr EVALEXPB                    ; evaluate the ON index argument
+                jmp LAF45                       ; return to mainline code
+SE3C2           jsr GETNCH                      ; eat the ERR/BRK token
+                cmpa #0x81                      ; GO?
+                bne SE3CF                       ; brif not
+                jsr GETNCH                      ; eat the GO
+                cmpa #0xa5                      ; TO?
+                bne SE3CF                       ; brif not
+                rts
+SE3CF           leas 2,s                        ; clean up stack (not needed)
+                jmp LB277                       ; raise syntax error
+; ERR jumps here if used as a command
+; NOTE: you can do ERR <char> GOTO (where <char> is a single character that doesn't prevent GOTO from being tokenized
+ERR             bsr SE3C2                       ; check for GOTO
+                jsr GETNCH                      ; eat the "TO"
+                jsr LAF67                       ; evaluate destination line number
+                ldd BINVAL                      ; get line number
+                std H.ONERR                     ; set error destination
+                ldd CURLIN                      ; get current line number
+                std H.ONERRS                    ; save line number where ON ERR was executed
+                rts
+; BRK jump shere if used as a command.
+; Same note as for ERR applies.
+BRK             bsr SE3C2                       ; check for GOTO
+                jsr GETNCH                      ; eat the "TO"
+                jsr LAF67                       ; evaluate destination line number
+                ldd BINVAL                      ; get line number
+                std H.ONBRK                     ; set break destination
+                ldd CURLIN                      ; get current line number
+                std H.ONBRKS                    ; save line number where ON BRK was executed
+                rts
+; Patches for &H parsing
+ALINK6A         lsl 2,x                         ; multiply accumulator by 2
+                rol 1,x
+                rol ,x
+                lbcs LBA92                      ; brif we overflowed
+                decb                            ; done enough shifts?
+                bne ALINK6A                     ; brif not
+                suba #'0                        ; remove ASCII bias
+                adda 2,x                        ; add digit to accumulator (this cannot cause carry)
+                sta 2,x
+                rts
+ALINK6B         lbcs L8800                      ; brif numeric
+                jmp L883F                       ; return to mainline
+; Line input patch
+ALINK16         cmpa #3                         ; is it BREAK?
+                orcc #1                         ; set C for BREAK
+                bne SE426                       ; brif not BREAK
+                pshs a,cc                       ; save character and break status
+                lda HRMODE                      ; is it graphics mode?
+                beq SE424                       ; brif not
+                clr HRMODE                      ; disable graphics mode
+                jsr SETTEXT
+SE424           puls cc,a                       ; get back BREAK status and character
+SE426           jmp LA3C6                       ; return to mainline
+; Break check patch
+ALINK15         cmpa #3                         ; BREAK?
+                beq SE430                       ; brif so
+                jmp LADF4                       ; re-enter mainline
+SE430           lda #1                          ; BREAK flag
+                sta H.ERRBRK
+                lda CURLIN                      ; immediate mode?
+                inca
+                beq SE43F                       ; brif so
+                ldd H.ONBRK                     ; is ON BRK active?
+                bne SE449                       ; brif so
+SE43F           lda HRMODE                      ; graphics m ode?
+                beq SE446                       ; brif not
+                jsr SETTEXT                     ; set text mode
+SE446           jmp STOP                        ; go handle BREAK
+SE449           std BINVAL                      ; set destination line number
+                tst H.ERRBRK                    ; error or break?
+                bne SE458                       ; brif break
+                lds FRETOP                      ; reset stack pointer
+                ldd #LADC4                      ; return to main loop
+                pshs d
+SE458           jsr LAEEB                       ; move to end of line
+                leax 1,x                        ; move past line terminator
+                ldd BINVAL                      ; get desired line number
+                cmpd CURLIN                     ; is it here or later?
+                bhi SE466                       ; brif so
+                ldx TXTTAB                      ; start search at beginning
+SE466           jsr LAD05                       ; find program line
+                lbcs SE51E                      ; brif not found
+                jmp LAEBB                       ; reset input pointer and return to main loop
+; Error handling patch
+ALINK20         clr H.ERRBRK                    ; flag error handling
+                lda CURLIN                      ; immediate mode?
+                inca
+                beq SE47D                       ; brif so
+                ldx H.ONERR                     ; is ON ERR in effect
+                bne SE4B3                       ; brif so
+SE47D           pshs a                          ; save register
+                lda HRMODE                      ; set flags on graphics mode
+                puls a                          ; get back A
+                beq SE488                       ; brif not graphics mode
+                jsr SETTEXT                     ; force text mode
+SE488           cmpb #38*2                      ; HG error?
+                bne SE49F                       ; brif not
+                jsr LB95C                       ; do newline
+                jsr LB9AF                       ; do ?
+                leax BAS20ERR,pcr               ; point to error string
+SE496           jsr LACA0                       ; display two character error message
+                jsr LACA0
+                jmp LAC65                       ; return to mainline code
+SE49F           cmpb #39*2                      ; HP error?
+                bne SE4B0                       ; brif not
+                jsr LB95C                       ; do newline
+                jsr LB9AF                       ; do ?
+                leax BAS20ERR+2,pcr             ; point to error string
+                jmp SE496                       ; go finish up
+SE4B0           jmp LAC49                       ; return to mainline error handler
+SE4B3           stb H.ERROR                     ; save error number
+                pshs b                          ; save error number
+                ldd CURLIN                      ; get current line number
+                std H.ERLINE                    ; save line number where error occurred
+                puls b                          ; get back error number
+                cmpb #3*2                       ; OD error?
+                bne SE4C7                       ; brif not
+                ldd BINVAL                      ; restore input pointer
+                std CHARAD
+SE4C7           tfr x,d                         ; save error destination line
+                lbra SE449                      ; go transfer control to error handler
+BAS20ERR        fcc 'HR'                        ; 38 Hi resolution graphics error
+                fcc 'HP'                        ; 39 Hi resolutuion print error
+; NEW handling patch
+ALINK19         pshs d                          ; save D
+                clra                            ; set up to clear things
+                clrb
+                std OLDPTR                      ; reset CONT address
+                std H.ONBRK                     ; reset ON BRK line
+                std H.ONERR                     ; reset ON ERR line
+                std H.ERLINE                    ; reset error source line
+                lda #0xff                       ; set error number to -1
+                sta H.ERROR
+                puls d                          ; restore d
+                jmp LAD43                       ; return to mainline
+; ERNO function
+ERNO            clra                            ; zero extend error number
+                ldb H.ERROR                     ; get error number
+                cmpb #0xff                      ; real?
+                bne SE4F4                       ; brif so
+                sex                             ; return "-1"
+                bra SE4FA
+SE4F4           cmpb #0xf1                      ; error number 0xf1?
+                bne SE4F9                       ; brif not
+                comb                            ; turn it back into UL error
+SE4F9           asrb                            ; error numbers are pre-multiplied by 2 - undo that
+SE4FA           jmp GIVABF                      ; return error number
+; ERLIN function
+ERLIN           ldd H.ERLINE                    ; get the line number where the error occurred
+                bra SE4FA                       ; return it - BUG: will treat lines above 32767 as negative
+; Immediate mode patch
+ALINK21         jsr SETTEXT                     ; force text mode
+                jsr LB95C                       ; do line feed if needed
+                orcc #0x50                      ; disable interrupts
+                lda #BLOCK6.4                   ; map HGET/HPUT buffers
+                sta MMUREG
+                ldd #0xffff                     ; mark buffers empty
+                std 0
+                lda #BLOCK7.0                   ; restore memory map
+                sta MMUREG
+                andcc #0xaf                     ; re-enable interrupts
+                jmp LAC76                       ; return to mainline
+; Handle undefined line in ON ERR or ON BRK
+SE51E           tst H.ERRBRK                    ; break?
+                beq SE528                       ; brif not
+                ldd H.ONBRKS                    ; get line number where ON BRK is
+                bra SE52B
+SE528           ldd H.ONERRS                    ; get line number where ON ERR is
+SE52B           std CURLIN                      ; reset the current line number there
+                ldb #7*2                        ; undefined line number
+                jmp LAC49                       ; raise error (bypass ON ERR check)
+; INPUT patch
+ALINK17         ldd H.ONBRK                     ; is ON BRK operating?
+                lbeq LAE11                      ; brif not
+                pshs d                          ; save destination line
+                lda #1                          ; set BREAK flag
+                sta H.ERRBRK
+                puls d                          ; get destination line
+                lbra SE449                      ; go handle ON BRK in INPUT
+; LPOKE command
+LPOKE           jsr LB141                       ; evaluate numeric expression (address)
+                lbrn 0
+                bsr SE58E                       ; convert to extended address
+                cmpb #BLOCK7.7                  ; valid block number?
+                lbhi LB44A                      ; brif not
+                pshs x,b                        ; save block and offset
+                jsr SYNCOMMA                    ; require a comma
+                jsr EVALEXPB                    ; evaluate value to put in memory
+                tfr b,a                         ; save value in A
+                puls b,x                        ; get back block and offset
+                cmpb #BLOCK7.7                  ; valid block (we already tested this!!)
+                lbhi LB44A                      ; brif not
+                orcc #0x50                      ; clobber interrupts
+                lbsr SELBLOK0                   ; map the block (by writing *all 16* MMU registers)
+                sta ,x                          ; save byte in memory
+                lbsr SETMMU                     ; unmap block (by writing *all 16* MMU registers)
+                andcc #0xaf                     ; re-enable interrupts
+                rts
+; LPEEK function
+LPEEK           bsr SE58E                       ; convert to block and offset
+                lbrn 0
+                cmpb #BLOCK7.7                  ; valid block?
+                lbhi LB44A                      ; brif not
+                orcc #0x50                      ; clobber interrupts
+                lbsr SELBLOK0                   ; map the block (by writing *all 16* MMU registers)
+                ldb ,x                          ; get memory contents
+                lbsr SETMMU                     ; restore map (by writing *all 16* MMU registers)
+                andcc #0xaf                     ; re-enable interrupts
+                jmp LB4F3                       ; return B as unsigned
+SE58E           pshs a                          ; save register
+                lda FP0EXP                      ; is it in range for 0x80000?
+                cmpa #0x93
+                bls SE59A                       ; brif so
+                ldb #BLOCK7.7+1                 ; return illegal block number
+                bra SE5AF
+SE59A           jsr LBCC8                       ; shift binary point to right of mantissa
+                ldd FPA0+2                      ; get low bits
+                anda #0x1f                      ; mask off block number bits
+                tfr d,x                         ; now X has the block offset
+                ldd FPA0+1                      ; get high bits
+                asra                            ;* shift block number to the right of B; note that
+                rorb                            ;* asr *should* be lsr but it works here because of
+                asra                            ;* the maximum range of the value
+                rorb
+                asra
+                rorb
+                asra
+                rorb
+                asra
+                rorb
+SE5AF           puls a,pc                       ; restore registers and return
+; BUTTON command
+BUTTON          jsr INTCNV                      ; get button number
+                lbrn 0
+                cmpb #3                         ; button number in range?
+                lbhi LB44A                      ; raise error if not
+                tfr b,a                         ; save button number
+                clrb                            ; set B to 0xff (strobe no keyboard columns)
+                comb
+                ldx #PIA0                       ; point to PIA0
+                stb 2,x                         ; strobe nothing
+                ldb ,x                          ; get button data
+                cmpb #0x0f                      ; buttons are on bottom four rows
+                beq SE5EA                       ; brif no buttons down
+                leax SE5D5,pcr                  ; point to button mask routines
+                asla                            ; four bytes per button routine
+                asla
+                jmp a,x                         ; jump to appropriate routine
+SE5D5           andb #1                         ; keep button 1, right joystick
+                bra SE5E3
+                andb #4                         ; keep button #1, left joystick
+                bra SE5E3
+                andb #2                         ; keep button #2, right joystick
+                bra SE5E3
+                andb #8                         ; keep button #2, left joystick
+SE5E3           bne SE5EA                       ; brif button was not down
+                ldd #1                          ; return nonzero if button down
+                bra SE5EC                       ; return result
+SE5EA           clra                            ; return zero if not down
+                clrb
+SE5EC           jsr GIVABF                      ; return result
+                rts
+; PALETTE command
+PALETTE         cmpa #0xf7                      ; RGB?
+                lbrn 0
+                bne SE600                       ; brif not
+                jsr GETNCH                      ; munch the RGB
+SE5FA           leax IM.RGB,pcr                 ; point to RGB palette initializer
+                bra SE634                       ; go set palette registers
+SE600           cmpa #0xf6                      ; CMP?
+                bne SE60C                       ; brif not
+                jsr GETNCH                      ; eat the CMP
+SE606           leax IM.CMP,pcr                 ; point to CMP palette initializer
+                bra SE634                       ; go set palette registers
+SE60C           jsr SE7B2                       ; evaluate two expressions
+                ldx #PALETREG                   ; point to palette registers
+                ldy #IM.PALET                   ; point to palette register images
+                lda BINVAL+1                    ; get palette number
+                cmpa #16                        ; valid entry?
+                lbhs LB44A                      ; brif not 0-15
+                leax a,x                        ; offset the pointers to the right entries
+                leay a,y
+                ldb VERBEG+1                    ; get colour number
+                cmpb #63                        ; valid?
+                bls SE62A                       ; brif so
+                ldb #63                         ; maximize to 63 (white)
+SE62A           orcc #0x50                      ; disable interrupts
+                sync                            ; synchronize to VSYNC
+                stb ,x                          ; set palette register
+                stb ,y                          ; record it in image
+                andcc #0xaf                     ; restore interrupts
+                rts
+SE634           pshs x                          ; save source pointer
+                ldy #IM.PALET                   ; point to palette register live image
+                bsr SE648                       ; copy source to the live image
+                puls x                          ; get source back
+                ldy #PALETREG                   ; point to palette registers
+                orcc #0x50                      ; disable interrupts
+                sync                            ; synchronize to VSYNC
+                bsr SE648                       ; copy the colour values into the palette registers
+                rts
+SE648           ldb #16-1                       ; BUG: should be 16 - this doesn't set register #15
+SE64A           lda ,x+                         ; set a register
+                sta ,y+
+                decb                            ; done all?
+                bne SE64A                       ; brif not
+                andcc #0xaf                     ; re-enable interrupts
+                rts
+IM.CMP          fcb 18,36,11,7,63,31,9,38       ; palette values for CMP
+                fcb 0,18,0,63,0,18,0,38
+IM.RGB          fcb 18,54,9,36,63,27,45,38      ; palette values for RGB
+                fcb 0,18,0,63,0,18,0,38
+; CMP and RGB commands just jump to the relevant implementations above
+RGB             bra SE5FA
+CMP             bra SE606
+IM.PALET        fcb 18,36,11,7,63,31,9,38       ; live palette images
+                fcb 0,18,0,63,0,18,0,38
+; HSCREEN command
+HSCREEN         cmpa #0                         ; end of line? BUG: won't work if colon terminates the command
+                lbrn 0
+                bne SE693                       ; brif not end of line
+                clrb                            ; default to HSCREEN 0 - turn off graphics
+                bra SE69C
+SE693           jsr EVALEXPB                    ; evaluate HSCREEN argument
+                cmpb #4                         ; only 4 HSCREEN modes
+                lbhi LB44A                      ; brif out of range
+SE69C           stb HRMODE                      ; set graphics mode
+                cmpb #0                         ; HSCREEN 0?
+                bne SE6A5                       ; brif not
+                jmp SETTEXT                     ; set text mode (disable graphics)
+SE6A5           stb HRMODE                      ; set graphics mode (we already did!)
+                ldx #SE6CB                      ; point to bytes/row table
+                subb #1                         ; normalize mode to 0
+                lda b,x                         ; get bytes per row value
+                sta HORBYT                      ; set it
+                cmpb #1                         ; is it 1 or 2?
+                bgt SE6B9                       ; brif not
+                ldd #160                        ; default coordinate for middle of 320 screen
+                bra SE6BC
+SE6B9           ldd #320                        ; default coordainte for middle of 640 screen
+SE6BC           std HORDEF                      ; set default horizontal coordinate
+                ldd #96                         ; set default vertical coordinate to middle
+                std VERDEF
+                ldb H.BCOLOR                    ; get background colour
+                bsr CLRHIRES                    ; clear hi-res graphics screen
+                jmp SETGRAPH                    ; set up to display the screen
+SE6CB           fcb 80,160,80,160               ; bytes per row values for HSCREEN 1 through 4
+; HCLS command
+HCLS            bne SE6D6                       ; brif not end of statement
+                ldb H.BCOLOR                    ; get background colour as default
+                bra CLRHIRES                    ; go clear screen
+SE6D6           bsr SE70E                       ; evaluate colour number
+CLRHIRES        tst HRMODE                      ; graphics mode?
+                beq SE6EF                       ; brif not
+                bsr PIXELFIL                    ; get all pixels set byte
+                jsr SELTASK1                    ; swap screen in
+                ldx #HRESSCRN                   ; point to start of screen
+SE6E4           stb ,x+                         ; set a byte worth of pixels
+                cmpx #HRESSCRN+0x8000           ; end of graphics memory?
+                bne SE6E4                       ; brif not
+                jsr SELTASK0                    ; restore memory map
+                rts
+SE6EF           ldb #38*2                       ; code for HR error
+                jmp LAC46                       ; raise error
+; HCOLOR command
+HCOLOR          cmpa #',                        ; was a foreground colour given?
+                lbrn 0
+                beq SE705                       ; brif not
+                bsr SE70E                       ; evaluate colour number
+                stb H.FCOLOR                    ; save foreground colour
+                jsr GETCCH                      ; is there something after the foreground?
+                beq SE70D                       ; brif not
+SE705           jsr SYNCOMMA                    ; insist on a comma
+                bsr SE70E                       ; evaluate colour number
+                stb H.BCOLOR                    ; set background colour
+SE70D           rts
+; Evaluate a colour number and make sure it's between 0 and 15 inclusive
+SE70E           jsr EVALEXPB                    ; evaluate colour
+SE711           cmpb #16                        ; is it in range?
+                lbhs LB44A                      ; brif not
+                rts
+SE718           jsr SE731                       ; set working colour and pixel bytes to default
+                jsr GETCCH                      ; is there a colour number?
+                beq SE72F                       ; brif not
+                cmpa #')                        ; )?
+                beq SE72F                       ; brif so - no colour
+                jsr SYNCOMMA                    ; insist on a comma
+                cmpa #',                        ; another comma?
+                beq SE72F                       ; brif so - colour not specified
+                jsr SE70E                       ; evaluate colour
+                bsr SE73B                       ; set working colour and pixel bytes
+SE72F           jmp GETCCH                      ; get current character and return
+SE731           ldb H.FCOLOR                    ; get foreground colour
+                tst SETFLG                      ; doing set?
+                bne SE73B                       ; brif so
+                ldb H.BCOLOR                    ; use background colour if doing reset
+SE73B           stb WCOLOR                      ; save working colour
+                bsr PIXELFIL                    ; get all pixel byte
+                stb ALLCOL                      ; save all pixel byte
+                rts
+; Return B with all pixels set to colour number in B
+PIXELFIL        pshs x                          ; save registers
+                lda HRMODE                      ; get graphics mode
+                suba #1                         ; normalize mode numbers to start at 0
+                ldx #SE759                      ; point to colour masks
+                andb a,x                        ; now B has only the relevant low bits of colour number
+                lda HRMODE                      ; get graphics mode
+                suba #1                         ; normalize mode numbers to start at 0
+                ldx #SE75D                      ; point to multiplier table
+                lda a,x                         ; get multplier
+                mul                             ; now B has all pixels set
+                puls x,pc                       ; restore registers and return
+SE759           fcb 0x03,0x0f,0x01,0x03         ; colour masks to keep only necessary low bits
+SE75D           fcb 0x55,0x11,0xff,0x55         ; multipliers to duplicate colour value across all pixels
+; HSET command
+HSET            lda #1                          ; HSET flag
+                bra SE76A
+; HRESET command
+HRESET          clra                            ; HRESET flag
+                lbrn 0
+SE76A           tst HRMODE                      ; are we in a graphics mode?
+                beq SE6EF                       ; brif not - raise error
+                sta SETFLG                      ; save our set/reset state
+                jsr LB26A                       ; insist on (
+                jsr SE7AA                       ; evaluate coordindates
+                tst SETFLG                      ; resetting?
+                bne SE77F                       ; brif so
+                jsr SE731                       ; set working colour and pixel byte
+                bra SE782
+SE77F           jsr SE718                       ; evaluate colour number if present
+SE782           jsr LB267                       ; insist on a )
+                jsr HCALPOS                     ; fetch screen pointer address and pixel mask
+SE788           jsr SELTASK1                    ; map the screen
+                jsr SE792                       ; set or reset the pixel
+                jsr SELTASK0                    ; unmap the screen
+                rts
+SE792           ldb ,x                          ; get byte on screen
+                pshs b                          ; save it
+                tfr a,b                         ; duplicate mask
+                coma                            ; invert the mask for clearing the screen data
+                anda ,x                         ; reset the pixel
+                andb ALLCOL                     ; set pixel mask to correct colour
+                pshs b                          ; merge pixel colour into screen data
+                ora ,s+
+                sta ,x                          ; put modified data on screen
+                suba ,s+                        ; nonzero if the screen changed
+                ora CHGFLG                      ; merge with existing change flag
+                sta CHGFLG
+                rts
+SE7AA           jsr SE7B2                       ; evaluate coordinates
+SE7AD           ldu #HORBEG                     ; point to horizontal coordinates
+SE7B0           rts                             ; dummy "normalization" routine
+                rts                             ; pointles RTS
+; Evaluate two expressions (usually coordinates)
+SE7B2           jsr LB734                       ; evaluate two expressions, first in BINVAL, second in B
+                ldy #HORBEG                     ; point to horizontal coordinates
+SE7B9           cmpb #192                       ; in range vertically?
+                blo SE7BF                       ; brif so
+                ldb #191                        ; set to maximum coordinate
+SE7BF           clra                            ; zero extend vertical
+                std 2,y                         ; set vertical coordinate
+                lda HRMODE                      ; get graphics mode
+                cmpa #2                         ; is it 1 or 2?
+                bgt SE7CD                       ; brif not
+                ldd #319                        ; maximum coordinate for modes 1 and 2
+                bra SE7D0
+SE7CD           ldd #639                        ; maximum coordindate for modes 3 and 4
+SE7D0           cmpd BINVAL                     ; is our max less than the specified one?
+                blo SE7D7                       ; brif so - keep max
+                ldd BINVAL                      ; use specified coordinate
+SE7D7           std ,y                          ; save horizontal coordinate
+                rts
+; Calculate pixel mask and memory address for pixel
+HCALPOS         bsr SE7E6                       ; point to correct routine for current mode
+                jmp ,u                          ; execute it
+CALTABLE        fdb G2BITPIX                    ; HSCREEN 1
+                fdb G4BITPIX                    ; HSCREEN 2
+                fdb G1BITPIX                    ; HSCREEN 3
+                fdb G2BITPIX                    ; HSCREEN 4
+SE7E6           ldu #CALTABLE                   ; point to routine table
+                lda HRMODE                      ; get graphicsmode
+                suba #1                         ; zero-base it
+                asla                            ; two bytes per address
+                ldu a,u                         ; get routine address
+                rts
+PIX1MASK        fcb 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 ; pixel masks for 1 bpp
+PIX2MASK        fcb 0xc0,0x30,0x0c,0x03         ; pxiel masks for 2 bpp
+PIX4MASK        fcb 0xf0,0x0f                   ; pixel masks for 4 bpp
+G1BITPIX        pshs u,b                        ; save registers
+                ldb HORBYT                      ; get bytes per row
+                lda VERBEG+1                    ; get vergical coord
+                mul                             ; now D is the offset to the start of the row
+                addd #HRESSCRN                  ; add in start of screen in memory
+                tfr d,x                         ; put it in a pointer
+                ldd HORBEG                      ; get horiztonal coordindate
+                lsra                            ; 8 pixels per byte do divide by 8
+                rorb
+                lsra
+                rorb
+                lsra
+                rorb
+                leax d,x                        ; offset to correct byte row
+                lda HORBEG+1                    ; get pixel number
+                anda #7                         ; keep only byte offset
+                ldu #PIX1MASK                   ; point to 1 bpp masks
+                lda a,u                         ; get pixel mask
+                puls b,u,pc                     ; restore registers and return
+G2BITPIX        pshs u,b                        ; save registers
+                ldb HORBYT                      ; get number of bytes per row
+                lda VERBEG+1                    ; get horizontal coordinate
+                mul                             ; now D is the offset to the start of the row
+                addd #HRESSCRN                  ; add in memory offset to the screen
+                tfr d,x                         ; put that in a pointer
+                ldd HORBEG                      ; get horizontal coordinate
+                lsra                            ; 4 pixels per byte so divide by 4
+                rorb
+                lsra
+                rorb
+                leax d,x                        ; now X points to the correct memory byte
+                lda HORBEG+1                    ; get horizontal coordinate
+                anda #3                         ; keep only the pixel number in the byte
+                ldu #PIX2MASK                   ; point to 2 bpp pixel masks
+                lda a,u                         ; get mask for this pixel
+                puls b,u,pc                     ; restore registers and return
+G4BITPIX        pshs u,b                        ; save registers
+                ldb HORBYT                      ; get bytes per row
+                lda VERBEG+1                    ; get vertical coordinate
+                mul                             ; now D is the offset to the start of the row
+                addd #HRESSCRN                  ; add in memory address of start of screen
+                tfr d,x                         ; put it in a pointer
+                ldd HORBEG                      ; get horizontal coordinate
+                lsra                            ; divide by 2 - only 2 pixels per byte
+                rorb
+                leax d,x                        ; now X points to the memory address of the pixel
+                lda HORBEG+1                    ; get horiztonal coordinate
+                anda #1                         ; keep offset into byte
+                ldu #PIX4MASK                   ; point to 4 bpp pixel masks
+                lda a,u                         ; get pixel mask
+                puls b,u,pc                     ; restore registers and return
+; HPOINT function
+HPOINT          tst HRMODE                      ; is there a graphics mode?
+                lbeq SE6EF                      ; brif not - raise error
+                jsr LB26A                       ; insist on (
+                jsr SE7AA                       ; evaluate coordinates
+                jsr LB267                       ; insist on )
+                jsr SELTASK1                    ; map the screen
+                jsr HCALPOS                     ; get screen pointer
+                tfr a,b                         ; save mask
+                andb ,x                         ; get pixel data
+SE875           lsra                            ; is the pixel aligned right?
+                bcs SE87B                       ; brif so
+                lsrb                            ; shift right
+                bra SE875                       ; see if it's aligned yet
+SE87B           jsr LB4F3                       ; return colour number
+                jsr SELTASK0                    ; restore memory map
+                rts
+; HLINE command
+HLINE           tst HRMODE                      ; is there a graphics mode active?
+                lbeq SE6EF                      ; brif not - raise error
+                lbrn 0
+                cmpa #'(                        ; is there (?
+                beq SE899                       ; brif so - we have start coords
+                cmpa #0xac                      ; -?
+                beq SE899                       ; brif no start given
+                ldb #'@                         ; make sure it's @ if not
+                jsr LB26F
+SE899           jsr SE9E1                       ; get start/end coords
+                ldx HOREND                      ; put end in the defaults
+                stx HORDEF
+                ldx VEREND
+                stx VERDEF
+                jsr SYNCOMMA                    ; make sure comma
+                cmpa #0xbe                      ; PRESET?
+                beq SE8B4                       ; brif so
+                cmpa #0xbd                      ; PSET?
+                lbne LB277                      ; brif not
+                ldb #1                          ; set flag
+                skip1lda
+SE8B4           clrb                            ; reset flag
+                pshs b                          ; save set/reset flag
+                jsr GETNCH                      ; eat the PSET/PRESET token
+                jsr SEA0D                       ; normalize start/end
+                puls b                          ; get back set/reset flag
+                stb SETFLG                      ; save set/reset flag
+                jsr SE731                       ; set active colour byte
+                jsr GETCCH                      ; is there more?
+                lbeq SE94E                      ; brif not - no box
+                jsr SYNCOMMA                    ; insist on a comma
+                ldb #'B                         ; insist on a B
+                jsr LB26F
+                bne SE8EB                       ; brif something after B
+                bsr SE906                       ; draw horizontal line (top)
+                bsr SE931                       ; draw vertical line (left)
+                ldx HORBEG                      ; save horizontal start
+                pshs x
+                ldx HOREND                      ; set up to draw vertical line (right)
+                stx HORBEG
+                bsr SE931                       ; draw vertical line (right)
+                puls x                          ; restore start coord
+                stx HORBEG
+                ldx VEREND                      ; set up to draw horizontal line (bottom)
+                stx VERBEG
+                bra SE906                       ; draw horizontal line (bottom) and return
+SE8EB           ldb #'F                         ; insist on F
+                jsr LB26F
+                bra SE8F6                       ; draw a filled box
+SE8F2           leax -1,x                       ; move vertical coordinate up one
+SE8F4           stx VERBEG                      ; save new vertical coordinate
+SE8F6           jsr SE906                       ; draw horizontal line
+                ldx VERBEG                      ; get current coordinate
+                cmpx VEREND                     ; above or below end?
+                beq SE905                       ; brif done
+                bhs SE8F2                       ; brif below - move up
+                leax 1,x                        ; move down (we're above)
+                bra SE8F4                       ; draw another line
+SE905           rts
+SE906           ldx HORBEG                      ; get starting coordinate
+                pshs x                          ; save it
+                jsr SE9DB                       ; get absolute horizontal difference
+                bcc SE913                       ; brif end > start
+                ldx HOREND                      ; get ending coordinate
+                stx HORBEG                      ; save as starting position
+SE913           tfr d,y                         ; save difference (pixel count)
+                leay 1,y                        ; bump it (coords are inclusive)
+                jsr HCALPOS                     ; calculate pixel address
+                puls u                          ; get start coordinate
+                stu HORBEG                      ; restore it
+                lbsr SEA16                      ; point to routine to move pixel pointer right
+SE921           sta VD7                         ; save pixel mask
+                jsr SE788                       ; turn on pixel
+                lda VD7                         ; get back pixel mask
+                jsr ,u                          ; move one pixel right
+                leay -1,y                       ; done all pixels?
+                bne SE921                       ; brif not
+                rts
+SE92F           puls d                          ; clean up stack
+SE931           ldd VERBEG                      ; get vertical start
+                pshs d                          ; save it
+                jsr SE9CD                       ; calculate absolute vertical difference
+                bcc SE93E                       ; brif end > start
+                ldx VEREND                      ; swap coordinate
+                stx VERBEG
+SE93E           tfr d,y                         ; save difference (pixel count)
+                leay 1,y                        ; coordinates are inclusive
+                jsr HCALPOS                     ; get screen pointer
+                puls u                          ; get original start coord
+                stu VERBEG                      ; restore it
+                lbsr SEA21                      ; get routine to move down one row
+                bra SE921                       ; draw vertical line
+SE94E           ldy #SE9B8                      ; point to vertical increment routine
+                jsr SE9CD                       ; calculate absolute vertical difference
+                beq SE906                       ; draw horizontal if difference is 0
+                bcc SE95D                       ; brif vertical end > vertical start
+                ldy #SE9C6                      ; point to decrement vertical routine
+SE95D           pshs b,a                        ; save vertical difference
+                ldu #SE9B1                      ; point to horitzontal increment routine
+                jsr SE9DB                       ; calculate absolute horizontal difference
+                beq SE92F                       ; draw vertical line if difference is 0
+                bcc SE96C                       ; brif horizontal end > horizontal start
+                ldu #SE9BF                      ; point to decrement horizontal routine
+SE96C           cmpd ,s                         ; compare horiztonal difference with vertical difference
+                puls x                          ; get vertical difference back
+                bhs SE977                       ; brif horizontal difference is greater
+                exg u,y                         ; swap major/minor directions
+                exg d,x
+SE977           pshs u,d                        ; save larger difference and incr/decr routine
+                pshs d                          ; save larger difference
+                lsra                            ; divide larger difference by 2
+                rorb
+                bcs SE988                       ; brif odd
+                cmpu #SE9B8+1                   ; inc or dec?
+                blo SE988                       ; brif inc
+                subd #1                         ; move back of dec (round down)
+SE988           pshs x,d                        ; save smaller difference and inc/dec
+                jsr SE7E6                       ; point to screen address routine
+SE98D           jsr ,u                          ; convert coordinates to screen address
+                jsr SE788                       ; turn on pxiel
+                ldx 6,s                         ; done all?
+                beq SE9AD                       ; brif so
+                leax -1,x                       ; account for pixel just drawn
+                stx 6,s
+                jsr [8,s]                       ; bump coordinate
+                ldd ,s                          ; get minor coordinate increment counter
+                addd 2,s                        ; add to minor coordinate
+                std ,s                          ; save new minor increment
+                subd 4,s                        ; subtract largest difference
+                bcs SE98D                       ; brif result not bigger than largest difference
+                std ,s                          ; save new minor increment
+                jsr ,y                          ; inc/dec minor
+                bra SE98D                       ; draw another pixel
+SE9AD           puls x                          ; clean up stack
+                puls d,x,y,u,pc                 ; clean up stack and return
+SE9B1           ldx HORBEG                      ; bump horizontal coord
+                leax 1,x
+                stx HORBEG
+                rts
+SE9B8           ldx VERBEG                      ; bump vertical coord
+                leax 1,x
+                stx VERBEG
+                rts
+SE9BF           ldx HORBEG                      ; reduce horizontal coord
+                leax -1,x
+                stx HORBEG
+                rts
+SE9C6           ldx VERBEG                      ; reduce vertical coord
+                leax -1,x
+                stx VERBEG
+SE9CC           rts
+SE9CD           ldd VEREND                      ; get vertical end
+                subd VERBEG                     ; get subtract start
+SE9D1           bcc SE9CC                       ; brif end > start
+                pshs cc                         ; save flag for which is >
+                nega                            ; negate difference
+                negb
+                sbca #0
+                puls cc,pc                      ; restore status andreturn
+SE9DB           ldd HOREND                      ; get horizontal end coord
+                subd HORBEG                     ; subtract start coord
+                bra SE9D1                       ; handle going negative
+; Evaluate two sets of coordinates
+SE9E1           ldx HORDEF                      ; set start to default
+                stx HORBEG
+                ldx VERDEF
+                stx VERBEG
+                cmpa #0xac                      ; -?
+                beq SE9F0                       ; brif so - use default start
+                jsr SEA04                       ; evaluate coordinate pair
+SE9F0           ldb #0xac                       ; insist on -
+                jsr LB26F
+                jsr LB26A                       ; insist on (
+                jsr LB734                       ; evaluate two expressions (X, B)
+                ldy #HOREND                     ; point to end coords
+                jsr SE7B9                       ; validate end coords
+                bra SEA0A                       ; handle rest of evaluation
+SEA04           jsr LB26A                       ; insist on (
+                jsr SE7B2                       ; evaluate coordinates with range check
+SEA0A           jmp LB267                       ; insist on )
+SEA0D           jsr SE7AD                       ; "normalize" start
+                ldu #HOREND                     ; point to end coords
+                jmp SE7B0                       ; "normalize" end
+; Point U to routine to move pixel to right
+SEA16           ldu #SEA25                      ; point to jump table
+                ldb HRMODE                      ; get graphics mode
+                subb #1                         ; zero-base it
+                aslb                            ; two bytes per entry
+                ldu b,u                         ; get routine address
+                rts
+SEA21           ldu #SEA45                      ; point to routine to move down one row
+                rts
+SEA25           fdb SEA34                       ; HSCREEN 1 right
+                fdb SEA3D                       ; HSCREEN 2 right
+                fdb SEA2D                       ; HSCREEN 3 right
+                fdb SEA34                       ; HSCREEN 4 right
+SEA2D           lsra                            ; move pixel mask right
+                bcc SEA33                       ; brif not changing bytes
+                rora                            ; shift mask back around to left
+                leax 1,x                        ; move byte forward
+SEA33           rts
+SEA34           lsra                            ; move one pixel right
+                lsra
+                bcc SEA33                       ; brif same byte
+                lda #0xc0                       ; reset pixel mask
+                leax 1,x                        ; move to next byte
+                rts
+SEA3D           coma                            ; flip pixels
+                cmpa #0xf0                      ; did we move to a new byte?
+                bne SEA44                       ; brif not
+                leax 1,x                        ; move to next byte
+SEA44           rts
+SEA45           ldb HORBYT                      ; get number of bytes per row
+                abx                             ; move ahead that many
+                rts
+; HCIRCLE command
+HCIRCLE         tst HRMODE                      ; graphics mode?
+                lbeq SE6EF                      ; brif not - raise error
+                lbrn 0
+                cmpa #'@                        ; is there @ before coords?
+                bne SEA59                       ; brif not
+                jsr GETNCH                      ; eat the @
+SEA59           jsr SEB60                       ; get max coords for video mode
+                jsr SEA04                       ; parse centre coords
+                jsr SE7AD                       ; normalize coordinates (ha ha)
+                ldx ,u                          ; get horizontal coordinate
+                stx VCB                         ; save it
+                ldx 2,u                         ; get vertical coordinate
+                stx VCD                         ; save it
+                jsr SYNCOMMA                    ; insist on a comma
+                jsr LB73D                       ; evaluate expression into X (radius)
+                ldu #VCF                        ; point to temp storage area
+                stx ,u                          ; save radius
+                jsr SE7B0                       ; normalize - pointless
+                lda #1                          ; put into "set" mode
+                sta SETFLG
+                jsr SE718                       ; evaluate colour
+                ldx #0x100                      ; default H/W ratio (1:1)
+                jsr GETCCH                      ; is the an HW ratio?
+                beq SEA95                       ; brif not
+                jsr SYNCOMMA                    ; insist on comma
+                jsr LB141                       ; evaluate HW ratio
+                lda FP0EXP                      ; multiply by 256
+                adda #8
+                sta FP0EXP
+                jsr LB740                       ; fetch HW ratio to X (with a fixed 8 bit fraction part)
+SEA95           lda HRMODE                      ; get graphics mode
+                cmpa #2                         ; is it a 320 mode?
+                bhi SEA9F                       ; brif not
+                tfr x,d                         ; double HW ratio for 320 modes
+                leax d,x
+SEA9F           stx VD1                         ; save H/W ratio
+                ldb #1                          ; go into SET mode
+                stb SETFLG
+                stb VD8                         ; flag for "first arc"
+                jsr SEB7B                       ; evaluate start point (octant, subarc)
+                pshs d                          ; save start point
+                jsr SEB7B                       ; evaluate end point
+                std VD9                         ; save end point
+                puls d                          ; get back start point
+SEAB3           pshs d                          ; save current circle position
+                ldx HOREND                      ; switch previous end coords in as the start
+                stx HORBEG
+                ldx VEREND
+                stx VERBEG
+                ldu #CIRCDATA+2                 ; point to sines/cosines table
+                anda #1                         ; is it an even octant?
+                beq SEAC7                       ; brif so
+                negb                            ; swap arc order for odd octants
+                addb #8
+SEAC7           aslb                            ; four bytes per table entry
+                aslb
+                leau b,u                        ; now U points to the correct entry
+                pshs u                          ; save table entry
+                jsr SEBBD                       ; calculate horizontal offset
+                puls u                          ; get back table pointer
+                leau -2,u                       ; move to other entry
+                pshs x                          ; save horizontal offset
+                jsr SEBBD                       ; calculaute vertical offset
+                puls y                          ; get back horizontal offset
+                lda ,s                          ; get octant number
+                anda #3                         ; is it 0 or 4?
+                beq SEAE7                       ; brif so
+                cmpa #3                         ; is it 3 or 7?
+                beq SEAE7                       ; brif so
+                exg x,y                         ; swap horizontal and vertical otherwise
+SEAE7           stx HOREND                      ; save horizontal offset
+                tfr y,d                         ; divide offset by 2
+                lsra
+                rorb
+                ldx VD1                         ; get H/W ratio
+                jsr SEBCB                       ; multiply offset by ratio
+                tfr y,d                         ; did MSB (bits 23-16) end up nonzero?
+                tsta                            ; brif so - outside 16 bit range
+                lbne LB44A                      ; brif so - raise error
+                stb VEREND                      ; save vertical offset MSB
+                tfr u,d                         ; get low bytes of result
+                sta VEREND+1                    ; save LSB (lose fractional part)
+                lda ,s                          ; get octant number
+                cmpa #2                         ; 0 or 1?
+                blo SEB13                       ; brif so
+                cmpa #6                         ; 6 or h?
+                bhs SEB13                       ; brif so
+                ldd VCB                         ; get horizontal center
+                subd HOREND                     ; subtract offset (going left)
+                bcc SEB20                       ; brif we didn't go negative
+                clra                            ; minimize to 0
+                clrb
+                bra SEB20
+SEB13           ldd VCB                         ; get horizontal centre
+                addd HOREND                     ; add offset
+                bcs SEB1E                       ; brif we overflowed
+                cmpd VD3                        ; did we overflow screen size?
+                blo SEB20                       ; brif not
+SEB1E           ldd VD3                         ; maximize horizontal coordinate
+SEB20           std HOREND                      ; save new horizontal coordinate
+                lda ,s                          ; get octantnumber
+                cmpa #4                         ; is it 0-3 (bottom half)?
+                blo SEB32                       ; brif so
+                ldd VCD                         ; get vertical centre
+                subd VEREND                     ; subtract offset
+                bcc SEB3F                       ; brif we didn't run past 0
+                clra                            ; minimize to 0
+                clrb
+                bra SEB3F
+SEB32           ldd VCD                         ; get vertical centre
+                addd VEREND                     ; add offset
+                bcs SEB3D                       ; brif we overflowed
+                cmpd VD5                        ; did we go past end of screen?
+                blo SEB3F                       ; brif not
+SEB3D           ldd VD5                         ; maximize to screen size
+SEB3F           std VEREND                      ; save new vertical coord
+                tst VD8                         ; was this the first coordinate?
+                bne SEB48                       ; brif so - don't draw a line
+                lbsr SE94E                      ; draw the subarc line
+SEB48           puls d                          ; get octant and arc
+                lsr VD8                         ; test if first point, and clear flag
+                bcs SEB53                       ; brif first coord
+                cmpd VD9                        ; at end of circle?
+                beq SEB5F                       ; brif so
+SEB53           incb                            ; bump arc counter
+                cmpb #8                         ; done 8 subarcs?
+                bne SEB5C                       ; brif not
+                inca                            ; bump octant
+                clrb                            ; reset arc counter
+                anda #7                         ; wrap octant number if needed
+SEB5C           jmp SEAB3                       ; move on with the next arc
+SEB5F           rts
+SEB60           ldu #VD3                        ; point to storage area
+                ldx #639                        ; set max horizontal coord for 640 mode
+                stx ,u
+                lda HRMODE                      ; get graphics mode
+                cmpa #2                         ; is it a 640 mode?
+                bgt SEB73                       ; brif so
+                ldx #319                        ; set max horzontalcoord for 320 mode
+                stx ,u
+SEB73           ldx #191                        ; all modes have a 191 vertical max
+                stx 2,u
+                jmp SE7B0                       ; "normalize" coords
+SEB7B           clrb                            ; default circle start/end to 0
+                jsr GETCCH                      ; is there a fraction?
+                beq SEB91                       ; brif not
+                jsr SYNCOMMA                    ; insist on a comma
+                jsr LB141                       ; evaluate circle fraction
+                lda FP0EXP                      ; multiply by 64 (calculate # of 64ths)
+                adda #6
+                sta FP0EXP
+                jsr LB70E                       ; fetch result as 8 bits unsigned
+                andb #0x3f                      ; keep only the fraction part
+SEB91           tfr b,a                         ; copy fraction to A (for octant)
+                andb #7                         ; keep only arc number in B
+                lsra                            ; shift octant number to right of A
+                lsra
+                lsra
+                rts
+CIRCDATA        fdb 0x0000,0x0001               ; subarc 0
+                fdb 0xfec5,0x1919               ; subarc 1
+                fdb 0xfb16,0x31f2               ; subarc 2
+                fdb 0xf4fb,0x4a51               ; subarc 3
+                fdb 0xec84,0x61f9               ; subarc 4
+                fdb 0xe1c7,0x78ae               ; subarc 5
+                fdb 0xd4dc,0x8e3b               ; subarc 6
+                fdb 0xc5e5,0xa269               ; subarc 7
+                fdb 0xb506,0xb506               ; subarc 8
+SEBBD           ldx VCF                         ; get radius
+                ldd ,u                          ; get sin/cos value
+                beq SEBCA                       ; brif 0 - just use radius
+                subd #1                         ; subtract 1
+                bsr SEBCB                       ; do the multiplication dance
+                tfr y,x                         ; save result to X
+SEBCA           rts
+SEBCB           pshs u,y,x,b,a                  ; save registers and reserve storage
+                clr 4,s                         ; clear high bits
+                lda 3,s                         ; B*XL
+                mul
+                std 6,s                         ; save in partical result
+                ldd 1,s                         ; A*XH
+                mul
+                addb 6,s                        ; add to partial product
+                adca #0
+                std 5,s
+                ldb ,s                          ; A*XL
+                lda 3,s
+                mul
+                addd 5,s                        ; add to partial product
+                std 5,s
+                bcc SEBEA
+                inc 4,s
+SEBEA           lda ,s                          ; A*XH
+                ldb 2,s
+                mul
+                addd 4,s                        ; add to partial product
+                std 4,s                         ; save final product bits
+                puls a,b,x,y,u,pc               ; save factors, retrieve result, and return
+; HPAINT command
+HPAINT          tst HRMODE                      ; do we have a grahpics mode?
+                lbeq SE6EF                      ; brif not - raise error
+                lbrn 0
+                cmpa #'@                        ; is there @ before the coords?
+                bne SEC05                       ; brif not
+                jsr GETNCH                      ; eat the @
+SEC05           jsr SEA04                       ; insist on (
+                jsr SE7AD                       ; evaluate the coordinates
+                lda #1                          ; set up for "setting"
+                sta SETFLG
+                jsr SE718                       ; evaluate colour code
+                ldd WCOLOR                      ; get working colour and all pixels byte
+                pshs d                          ; save them for later
+                jsr GETCCH                      ; do we have a border colour?
+                beq SEC1D                       ; brif not - use default
+                jsr SE718                       ; evaluate border colour
+SEC1D           lda ALLCOL                      ; get border colour pixel byte
+                sta VD8                         ; save it
+                puls d                          ; get paint colour details
+                std WCOLOR                      ; restore them
+                jsr SELTASK1                    ; map the graphics screen
+                clra                            ;* add a terminator block to the top of the stack
+                pshs u,x,b,a                    ;* which is how HPAINT knows it's done 
+                jsr SEB60                       ; get maximum coordinate values
+                jsr SE7E6                       ; point U to routine that selects a pixel
+                stu VD9                         ; save pixel selection routine address
+                jsr SECBE                       ; paint from current coord to the left
+                beq SEC47                       ; brif no painting done - we started on the border
+                jsr SED01                       ; paint to the right
+                lda #1                          ; set up a record to paint down the screen
+                sta VD7
+                jsr SED2E
+                neg VD7                         ; set up a record to paint up the screen
+                jsr SED2E
+SEC47           sts TMPSTK                      ; save stack pointer
+SEC4A           tst CHGFLG                      ; see if a pixel changed
+                bne SEC51                       ; brif so
+                lds TMPSTK                      ; get stack pointer back
+SEC51           puls a,b,x,u                    ; get data for the next line to handle
+                clr CHGFLG                      ; flag nothing changed yet
+                sts TMPSTK                      ; save new stack address
+                leax 1,x                        ; add one to the start position
+                STX HORBEG                      ; set it as the starting position
+                stu VD1                         ; save length of parent line
+                sta VD7                         ; save up/down flag
+                beq SECBA                       ; brif up/down is 0 - end marker
+                bmi SEC6A                       ; brif we're going up the screen
+                incb                            ; bump vertical coord
+                cmpb VD6                        ; at end of screen?
+                bls SEC6E                       ; brif not
+                clrb                            ; wrap around - this will cause us to bail below
+SEC6A           tstb                            ; is coord 0?
+                beq SEC4A                       ; brif so - don't go upward
+                decb                            ; move upward on the screen
+SEC6E           stb VERBEG+1                    ; save new vertical coordinate
+                jsr SECBE                       ; paint to the left
+                beq SEC86                       ; brif no pixels changed
+                cmpd #3                         ; less than 3 painted?
+                blo SEC80                       ; brif so - no need to check for paintable data
+                leax -2,x                       ; move coord left two
+                jsr SED15                       ; save block of paint data in the other direction (vertically)
+SEC80           jsr SED01                       ; paint to the right
+SEC83           jsr SED2E                       ; save a block of paint data in the same direction
+SEC86           coma                            ; invert number of pixels painted (but "less 1")
+                comb
+SEC88           addd VD1                        ; add to length of parent line
+                std VD1                         ; now we have the new parent line length
+                ble SECA5                       ; brif parent line was shorter
+                jsr SE9B1                       ; bump horizontal
+                jsr SECF1                       ; check for border
+                bne SEC9B                       ; brif not
+                ldd #-1                         ; count down
+                bra SEC88                       ; keep looking
+SEC9B           jsr SE9BF                       ; move left
+                jsr SED3A                       ; save horizontal coord
+                bsr SECC7                       ; paint to the right
+                bra SEC83                       ; save paint block and keep going
+SECA5           jsr SE9B1                       ; bump horizontal coord
+                leax d,x                        ; point to right of end of parent line
+                stx HORBEG                      ; set as start coord
+                coma                            ; negate pixel count (and subtract 2?)
+                comb
+                subd #1
+                ble SECB7                       ; brif line doesn't extend past right of parent
+                tfr d,x                         ; save portion of line to the right as length
+                bsr SED15                       ; save block of paint data
+SECB7           jmp SEC4A                       ; go process more paint blocks
+SECBA           jsr SELTASK0                    ; unmap screen
+                rts
+SECBE           jsr SED3A                       ; point starting coord in end
+                ldy #SE9BF                      ; point to dec horizontal
+                bra SECCD                       ; paint line
+SECC7           ldy #SE9B1                      ; point to incr horizontal coord
+                jsr ,y                          ; skip first - already done
+SECCD           ldu ZERO                        ; initial pixel counter to 0
+                ldx HORBEG                      ; get starting coord
+SECD1           bmi SECEA                       ; brif off the left side
+                cmpx VD3                        ; at max value?
+                bhi SECEA                       ; brif off right side
+                pshs u,y                        ; save counter and inc/dec p ointer
+                bsr SECF1                       ; check for border
+                beq SECE8                       ; brif so - we're done
+                jsr SE792                       ; set pixel
+                puls y,u                        ; restore count and inc/dec routine
+                leau 1,u                        ; bump count
+                jsr ,y                          ; adjust coord
+                bra SECD1                       ; go do another pixel
+SECE8           puls y,u                        ; get back counter and inc/dec pointer
+SECEA           tfr u,d                         ; save paint counter in D and X
+                tfr d,x
+                subd ZERO                       ; set flags on counter
+                rts
+SECF1           jsr [VD9]                       ; get address of pixel
+                tfr a,b                         ; duplicate mask
+                andb VD8                        ; get pixel colour mask for the pixel
+                pshs b,a                        ; save masks
+                anda ,x                         ; merge in with pixel data on screen
+                cmpa 1,s                        ; does it match? (Z set if so)
+                puls a,b,pc                     ; restore masks and return
+SED01           std VCD                         ; save pixel count
+                ldy HOREND                      ; get last horizontal coord
+                bsr SED3A                       ; save current coord
+                sty HORBEG                      ; start painting to right from the previous end
+                bsr SECC7                       ; go paint rightward
+                ldx VCD                         ; get previous pixel count
+                leax d,x                        ; now we have a total count for this line
+                addd #1                         ; bump it by one?
+                rts
+SED15           std VCB                         ; save painted pixel count
+                puls y                          ; get return address
+                ldd HORBEG                      ; get start coord
+                pshs x,d                        ; save start coord and line length
+                lda VD7                         ; get direction
+                nega                            ; invert it
+SED20           ldb VERBEG+1                    ; get vertical coordinate
+                pshs b,a                        ; save direction and vertical coord
+                pshs y                          ; put return address back
+                ldb #6                          ; make sure we didn't overflow the stack
+                jsr SED3F
+                ldd VCB                         ; get line length back
+                rts
+SED2E           std VCB                         ; save line length
+                puls y                          ; get return address
+                ldd HOREND                      ; get horizontal start
+                pshs x,d                        ; save line length and horizontal coord
+                lda VD7                         ; get direction flag
+                bra SED20                       ; finish saving frame
+SED3A           ldx HORBEG                      ; get start coord
+                stx HOREND                      ; save it as end coord
+                rts
+SED3F           negb                            ; subtract B bytes from S
+                leas b,s
+                cmps #TMPSTACK-(0x2000+14)      ; does it overflow? (14 extra is from the unused vectors at the top of the CB ROM area)
+                lblo SED4E                      ; raise OM error if we did
+                negb                            ; restore stack pointer
+                leas b,s
+                rts
+SED4E           lds #TMPSTACK-2                 ; reset stack (since we overflowed it)
+                jsr SELTASK0                    ; restore default memory map
+                jmp LAC44                       ; raise OM error
+; HBUFF command
+HBUFF           jsr LB73D                       ; evaluate buffer number to X
+                lbrn 0
+                cmpx #255                       ; valid?
+                lbhi LB44A                      ; brif not
+                stx VD1                         ; save buffer number
+                beq SED72                       ; don't get size if buffer 0 select
+                jsr SYNCOMMA                    ; insist on a comma
+                jsr LB73D                       ; evaluate size to X
+                stx VD3                         ; save buffer size
+SED72           jsr SE0CB                       ; map the buffers
+                jsr SELTASK1
+                ldd VD1                         ; get buffer number
+                tstb                            ; is it zero (not needed!)
+                bne SED85                       ; brif not
+                ldd #0xffff                     ; clear all buffers
+                std HRESBUFF
+                bra SEDBD                       ; reset memory map and return
+SED85           ldy #HRESBUFF                   ; point to buffers
+                ldd ,y                          ; get address of next block
+                cmpd #0xffff                    ; empty buffer space?
+                bne SED95                       ; brif not
+                bsr SEDC4                       ; check for room in buffer space
+                bra SEDB0                       ; set up buffer
+SED95           ldb VD1+1                       ; get buffer number
+SED97           cmpb 2,y                        ; is this buffer the same number?
+                beq SEDD2                       ; brif so - throw error
+                ldu ,y                          ; get address of next buffer
+                beq SEDA3                       ; brif last buffer
+                tfr u,y                         ; move on to next buffer
+                bra SED97                       ; see if we have a matching number here
+SEDA3           tfr y,u                         ; save start address to U
+                ldd 3,y                         ; get size of last buffer
+                leay 5,y                        ; move past header
+                leay d,y                        ; move past buffer data
+                bsr SEDC4                       ; check for enough room
+                sty ,u                          ; save pointer to the new buffer in previous header
+SEDB0           ldd #0                          ; mark this as the last buffer
+                std ,y
+                ldb VD1+1                       ; set buffer number
+                stb 2,y
+                ldd VD3                         ; set buffer size
+                std 3,y
+SEDBD           jsr SELTASK0                    ; restore memory map
+                jsr SETMMU
+                rts
+SEDC4           tfr y,x                         ; point X to the start of the buffer data
+                leax 5,x
+                ldd VD3                         ; get length requested
+                leax d,x                        ; point to end of new buffer
+                cmpx #HRESBUFF+0x1f00           ; does it fit?
+                bhi SEDD6                       ; brif not
+                rts
+SEDD2           ldb #9*2                        ; code for redim array
+                bra SEDD8
+SEDD6           ldb #6*2                        ; code for out of memory
+SEDD8           lds #TMPSTACK-2                 ; reset stack
+                jsr SELTASK0                    ; restore memory map
+                jsr SETMMU
+                jmp LAC46                       ; raise error
+; HGET command
+HGET            ldx #SEEC0                      ; point to HGET movement routine
+                stx VD5                         ; save it
+                clrb                            ; flag for "GET"
+                bra SEDF4                       ; get on with things
+; HPUT command
+HPUT            ldx #SEEEF                      ; point to HPUT movement routine
+                stx VD5                         ; save it
+                ldb #1                          ; flag for "PUT"
+SEDF4           tst HRMODE                      ; check for graphics
+                lbeq SE6EF                      ; brif not - raise error
+                lbrn 0
+                stb VD8                         ; save GET/PUT flag
+                cmpa #'@                        ; is there @ before coords?
+                bne SEE06                       ; brif not
+                jsr GETNCH                      ; eat the @
+SEE06           jsr SE9E1                       ; evaluate box bounds
+                jsr SYNCOMMA                    ; insist on a comma
+                jsr EVALEXPB                    ; evaluate buffer number
+                stb VD3                         ; save buffer number
+                clr VD4                         ; default action to none
+                jsr GETCCH                      ; is there an action flag?
+                beq SEE38                       ; brif not
+                com VD4                         ; flag for action flag specified
+                jsr SYNCOMMA                    ; insist on a comma
+                tst VD8                         ; is it GET?
+                bne SEE23                       ; brif not
+                lbra LB277                      ; raise error
+SEE23           ldb #5                          ; 5 possible actions
+                ldx #SEEE0                      ; point to action routine table address
+SEE28           ldu ,x++                        ; get routine address
+                cmpa ,x+                        ; does the action match?
+                beq SEE34                       ; brif so
+                decb                            ; checked all of them?
+                bne SEE28                       ; brif not
+                jmp LB277                       ; raise error
+SEE34           stu VD5                         ; save action address
+                jsr GETNCH                      ; eat the action token
+SEE38           jsr SE0CB                       ; map the buffers and screen
+                jsr SELTASK1
+                ldb VD3                         ; get buffer number
+                jsr SEF18                       ; find the correct buffer's data
+                ldd HORBEG                      ; get horizontal start
+                cmpd HOREND                     ; is it less than end?
+                ble SEE50                       ; brif so
+                ldx HOREND                      ; swap start/end horizontal coords
+                stx HORBEG
+                std HOREND
+SEE50           ldd VERBEG                      ; get vertical start
+                cmpd VEREND                     ; less that end?
+                ble SEE5D                       ; brif so
+                ldx VEREND                      ; swap vertical coords
+                stx VERBEG
+                std VEREND
+SEE5D           lda HRMODE                      ; get graphics mode
+                ldb #0xf8                       ; round off mask for mode 3 (1 bpp)
+                cmpa #3                         ; is it mode 3 (1 bpp)
+                beq SEE6D                       ; brif so
+                ldb #0xfc                       ; mask for mode 1 or 4 (2 bpp)
+                cmpa #2                         ; is it mode 2?
+                bne SEE6D                       ; brif not - it's mode 1 or 4
+                ldb #0xfe                       ; round off mask for mode 2 (4 bpp)
+SEE6D           tfr b,a                         ; save round off in A and B - we need it twice
+                anda HORBEG+1                   ; round off horizontal start
+                sta HORBEG+1
+                andb HOREND+1                   ; round of horizontal end coord
+                stb HOREND+1
+                jsr SE9DB                       ; calculate horizontal difference
+                std HOREND                      ; save it
+                jsr SE9CD                       ; calculate vertial difference
+                addd #1                         ; make it inclusive
+                std VEREND                      ; save it
+                lda HRMODE                      ; get graphics mode
+                cmpa #2                         ; HSCREEN 2?
+                beq SEE96                       ; divide pixel count by 2 for byte count
+                cmpa #3                         ; HSCREEN 3?
+                bne SEE92                       ; brif not - divide by 4 (HSCREEN 1, 4)
+                lsr HOREND                      ; divide by 8 (falls through to by 4)
+                ror HOREND+1
+SEE92           lsr HOREND                      ; divide by 4 (falls through to divide by 2)
+                ror HOREND+1
+SEE96           lsr HOREND                      ; divide by 2
+                ror HOREND+1
+                ldd HOREND                      ; get byte count
+                addd #1                         ; make it inclusive of the end
+                std HOREND
+                jsr HCALPOS                     ; get pointer to screen location
+                ldy VD5                         ; point to action routine address
+SEEA7           ldb HOREND+1                    ; get LS byte of byte count
+                pshs x                          ; save line start pointer
+SEEAB           jsr ,y                          ; perform movement action
+                decb                            ; done all bytes?
+                bne SEEAB                       ; brif not
+                puls x                          ; get back line start
+                jsr SEA45                       ; move down one line
+                dec VEREND+1                    ; done all rows?
+                bne SEEA7                       ; brif not
+                jsr SELTASK0                    ; restore memory map
+                jsr SETMMU
+                rts
+SEEC0           lda ,x+                         ; get a byte from screen
+                bsr SEEC7                       ; point to proper buffer location
+                sta ,u                          ; save it
+                rts
+SEEC7           ldu VCF                         ; get buffer pointer
+                leau 1,u                        ; move to next byte
+                stu VCF                         ; save new pointer
+                cmpu VD1                        ; did we run past the end of the buffer?
+                bhi SEED3                       ; brif so - raise error
+                rts
+SEED3           lds #TMPSTACK-2                 ; reset stack
+                jsr SELTASK0                    ; restore memory map
+                jsr SETMMU
+                jmp LB44A                       ; raise FC error
+SEEE0           fdb SEEEF                       ; PSET action routine
+                fcb 0xbd                        ; PSET token
+                fdb SEEF6                       ; PRESET action routine
+                fcb 0xbe                        ; PRESET token
+                fdb SEF07                       ; OR action routine
+                fcb 0xb1                        ; OR token
+                fdb SEEFE                       ; AND action routine
+                fcb 0xb0                        ; AND token
+                fdb SEF10                       ; NOT action routine
+                fcb 0xa8                        ; NOT token
+SEEEF           bsr SEEC7                       ; point to buffer location
+                lda ,u                          ; get byte from buffer
+                sta ,x+                         ; put it on screen
+                rts
+SEEF6           bsr SEEC7                       ; point to buffer location
+                lda ,u                          ; get byte
+                coma                            ; invert it
+                sta ,x+                         ; put it on screen
+                rts
+SEEFE           bsr SEEC7                       ; point to buffer location
+                lda ,u                          ; get byte from buffer
+                anda ,x                         ; "AND" with screen data
+                sta ,x+                         ; put it on screen
+                rts
+SEF07           bsr SEEC7                       ; point to buffer location
+                lda ,u                          ; get byte from buffer
+                ora ,x                          ; "OR" with screen data
+                sta ,x+                         ; put on screen
+                rts
+SEF10           bsr SEEC7                       ; point to buffer address
+                lda ,x                          ; get byte from screen (BUG: should be ,u to get from buffer)
+                coma                            ; invert data
+                sta ,x+                         ; save on screen
+                rts
+SEF18           ldy #HRESBUFF                   ; point to start of buffers
+                lda ,y                          ; are there any buffers?
+                cmpa #0xff
+                bne SEF2C                       ; brif so
+                jmp SEED3                       ; raise error if no buffers
+SEF25           ldy ,y                          ; point to next buffer
+                lbeq SEED3                      ; brif end of buffers - raise error
+SEF2C           cmpb 2,y                        ; is this the desired buffer?
+                bne SEF25                       ; brif not
+                ldd 3,y                         ; get size of buffer
+                leay 4,y                        ; point to start of data (less one for "pre-inc" on use
+                sty VCF                         ; save buffer pointer
+                leay 1,y                        ; point to actual data start
+                leay d,y                        ; calculate address of end of buffer
+                sty VD1                         ; save end address
+                rts
+; HPRINT command
+HPRINT          tst HRMODE                      ; graphics mode?
+                lbeq SE6EF                      ; brif not - raise error
+                lbrn 0
+                jsr LB26A                       ; insist on (
+                jsr SE7B2                       ; evaluate coordinates
+                jsr LB267                       ; insist on )
+                jsr SYNCOMMA                    ; insist on comma
+                jsr LB156                       ; evaluate print string
+                tst VALTYP                      ; is it string?
+                bne SEF62                       ; brif not numeric (should be BMI)
+                jsr LBDD9                       ; convert number to string
+                jsr LB516                       ; save string in string space and all that jazz
+SEF62           jsr LB657                       ; fetch string details
+                stb H.PCOUNT                    ; save length in print count
+                ldy #H.PBUF                     ; point to temporary string buffer
+SEF6C           decb                            ; have we processed the whole string?
+                bmi SEF75                       ; brif so (or if the string length was > 128)
+                lda ,x+                         ; copy a character from the string into the buffer
+                sta ,y+
+                bra SEF6C                       ; see if we're done yet
+SEF75           lda HRMODE                      ; get graphics mode
+                ldb #40                         ; 40 characters on a 320 line
+                cmpa #3                         ; is it mode 1 or 2?
+                blo SEF7F                       ; brif so
+                ldb #80                         ; 80 characters on a 640 line
+SEF7F           clra                            ; zero extend line size
+                subd HORBEG                     ; subtract first position from line length
+                bmi SF001                       ; brif we're printing off the side of the screen
+                cmpb H.PCOUNT                   ; is the print count larger than characters left?
+                bhi SEF8E                       ; brif not
+                stb H.PCOUNT                    ; save remaining screen positions as print count
+                beq SF001                       ; brif nothing to print
+SEF8E           lda #ROWMAX-1                   ; get highest row number
+                cmpa VERBEG+1                   ; are we in range?
+                bge SEF96                       ; brif so
+                sta VERBEG+1                    ; force bottom row if not in range
+SEF96           jsr SF08C                       ; calculate actual pixel coordinates
+                jsr HCALPOS                     ; get screen pointer
+                ldy #H.PBUF                     ; point to string data
+                ldb H.PCOUNT                    ; get number of characters to print
+SEFA3           lda ,y                          ; get character to print
+                anda #0x7f                      ; lose bit 7 (character set repeats)
+                suba #0x20                      ; lose the "control" characters - no glyphs for those codes
+                bpl SEFAD                       ; brif it was not a control character
+                lda #0                          ; use a space if it was
+SEFAD           sta ,y+                         ; put glyph number into the buffer
+                decb                            ; processed all of them?
+                bgt SEFA3                       ; brif not
+                lda HRMODE                      ; get graphics mode
+                deca                            ; zero-base it
+                asla                            ; two bytes per display routine
+                ldy #SF002                      ; point to display routine table
+                ldy a,y                         ; point to display routine
+                sty VD1                         ; save it
+                lda #8                          ; 8 rows per character
+                sta VD3                         ; temp save row counter
+                ldy #H.PBUF                     ; point to print buffer
+                ldu #SF09D                      ; point to FONT data
+                ldb H.FCOLOR                    ; get foreground colour
+                jsr PIXELFIL                    ; get an all pixel byte
+                stb ALLCOL                      ; save it
+                jsr SELTASK1                    ; map the screen
+                lda H.PCOUNT                    ; get character count to display
+SEFD9           pshs y,x,a                      ; save buffer pointer, character count, and screen address
+SEFDB           ldb ,y+                         ; get character from buffer
+                clra                            ; zero extend it
+                aslb                            ;* 8 bytes per character entry (don't need rola after first
+                aslb                            ;* because characters are only 7 bits
+                rola
+                aslb
+                rola
+                lda d,u                         ; get font data for this row
+                jsr [VD1]                       ; display it
+                dec H.PCOUNT                    ; done all characters on this row?
+                bgt SEFDB                       ; brif not
+                puls a,x,y                      ; get back character count, buffer pointer, and screen address
+                dec VD3                         ; have we done all the rows?
+                beq SEFFE                       ; brif so
+                sta H.PCOUNT                    ; restore print count
+                leau 1,u                        ; move one row down the font data
+                jsr SEA45                       ; move one row down the screen
+                bra SEFD9                       ; go do another row of pixels
+SEFFE           jsr SELTASK0                    ; restore memory map
+SF001           rts
+SF002           fdb SF01A                       ; HSCREEN 1 (2 bpp)
+                fdb SF045                       ; HSCREEN 2 (4 bpp)
+                fdb SF00A                       ; HSCREEN 3 (1 bpp)
+                fdb SF01A                       ; HSCREEN 4 (2 bpp)
+SF00A           pshs a                          ; save font data
+                coma                            ; invert it
+                anda ,x                         ; merge with screen - turns off pixels in the character
+                sta ,x                          ; save it back on the screen
+                puls a                          ; get back font data
+                anda ALLCOL                     ; merge with colour data
+                ora ,x                          ; merge with screen to fill hole created above
+                sta ,x+                         ; save it on screen
+                rts
+SF01A           pshs y                          ; save buffer pointer
+                ldy #SF035                      ; point to 2 bpp pixel masks
+                tfr a,b                         ; copy character data (need two bytes per character)
+                lsra                            ; use the upper 4 bits in first byte
+                lsra
+                lsra
+                lsra
+                lda a,y                         ; get pixel mask for all 16 possibilities for upper 4 bits
+                jsr SF00A                       ; shove it on screen
+                andb #0x0f                      ; lose upper bits for low half
+                lda b,y                         ; get pixel mask for this pixel combination
+                jsr SF00A                       ; shove that on screen too
+                puls y                          ; restore buffer pointer
+                rts
+SF035           fcb 0x00,0x03,0x0c,0x0f         ; combined pixel masks for 16 possibilities for a 2 bpp byte
+                fcb 0x30,0x33,0x3c,0x3f
+                fcb 0xc0,0xc3,0xcc,0xcf
+                fcb 0xf0,0xf3,0xfc,0xff
+SF045           pshs y,a                        ; save buffer pointer and font data
+                ldy #SF06C                      ; point to 16 colour masks
+                lsra                            ; fetch high 4 bits
+                lsra
+                lsra
+                lsra
+                asla                            ; two bytes per mask (this is NOT redundant - this and above clears bit 0)
+                ldd a,y                         ; get two byte mask for these four bits
+                jsr SF00A                       ; show upper 2 pixels
+                tfr b,a                         ; show lower 2 pixels
+                jsr SF00A
+                puls a                          ; get back font data
+                anda #0x0f                      ; lost upper bits
+                asla                            ; two bytes per mask
+                ldd a,y                         ; get mask data
+                jsr SF00A                       ; show upper 2 pixels
+                tfr b,a                         ; show lower 2 pixels
+                jsr SF00A
+                puls y                          ; restore buffer pointer
+                rts
+SF06C           fdb 0x0000,0x000f,0x00f0,0x00ff ; combined pixel masks for 16 possibilities for a 4 bpp double byte
+                fdb 0x0f00,0x0f0f,0x0ff0,0x0fff
+                fdb 0xf000,0xf00f,0xf0f0,0xf0ff
+                fdb 0xff00,0xff0f,0xfff0,0xffff
+SF08C           ldd HORBEG                      ; get horizontal character cell coordinate
+                aslb                            ; times 8 - 8x8 font data; note first shift can't cause carry with max 79 for column number
+                aslb
+                rola
+                aslb
+                rola
+                std HORBEG                      ; save actual horizontal pixel position of print position
+                lda VERBEG+1                    ; get vertical character cell coordinate
+                asla                            ; times 8 - 8x8 font data
+                asla
+                asla
+                sta VERBEG+1                    ; save actual vertical pixel position of print position
+                rts
+; This is the HPRINT font, which is basically equivalent to the hardware font in the GIME for character codes
+; 0x20 through 0x7f. It does not include the extra characters in the 0x00-0x1f range of the hardware character
+; set. However, glyphs for those are actually included in the ROM above the end of the actual code.
+SF09D           fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00     ; SPACE
+                fcb 0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00     ; !
+                fcb 0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00     ; "
+                fcb 0x28,0x28,0x7C,0x28,0x7C,0x28,0x28,0x00     ; #
+                fcb 0x10,0x3C,0x50,0x38,0x14,0x78,0x10,0x00     ; $
+                fcb 0x60,0x64,0x08,0x10,0x20,0x4C,0x0C,0x00     ; %
+                fcb 0x20,0x50,0x50,0x20,0x54,0x48,0x34,0x00     ; &
+                fcb 0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00     ; '
+                fcb 0x08,0x10,0x20,0x20,0x20,0x10,0x08,0x00     ; (
+                fcb 0x20,0x10,0x08,0x08,0x08,0x10,0x20,0x00     ; )
+                fcb 0x00,0x10,0x54,0x38,0x38,0x54,0x10,0x00     ; *
+                fcb 0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00     ; +
+                fcb 0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x20     ; ,
+                fcb 0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00     ; -
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00     ; .
+                fcb 0x00,0x04,0x08,0x10,0x20,0x40,0x00,0x00     ; /
+                fcb 0x38,0x44,0x4C,0x54,0x64,0x44,0x38,0x00     ; 0
+                fcb 0x10,0x30,0x10,0x10,0x10,0x10,0x38,0x00     ; 1
+                fcb 0x38,0x44,0x04,0x38,0x40,0x40,0x7C,0x00     ; 2
+                fcb 0x38,0x44,0x04,0x08,0x04,0x44,0x38,0x00     ; 3
+                fcb 0x08,0x18,0x28,0x48,0x7C,0x08,0x08,0x00     ; 4
+                fcb 0x7C,0x40,0x78,0x04,0x04,0x44,0x38,0x00     ; 5
+                fcb 0x38,0x40,0x40,0x78,0x44,0x44,0x38,0x00     ; 6
+                fcb 0x7C,0x04,0x08,0x10,0x20,0x40,0x40,0x00     ; 7
+                fcb 0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00     ; 8
+                fcb 0x38,0x44,0x44,0x38,0x04,0x04,0x38,0x00     ; 9
+                fcb 0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00     ; :
+                fcb 0x00,0x00,0x10,0x00,0x00,0x10,0x10,0x20     ; ;
+                fcb 0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00     ; <
+                fcb 0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00     ; =
+                fcb 0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x00     ; >
+                fcb 0x38,0x44,0x04,0x08,0x10,0x00,0x10,0x00     ; ?
+                fcb 0x38,0x44,0x04,0x34,0x4C,0x4C,0x38,0x00     ; @
+                fcb 0x10,0x28,0x44,0x44,0x7C,0x44,0x44,0x00     ; A
+                fcb 0x78,0x24,0x24,0x38,0x24,0x24,0x78,0x00     ; B
+                fcb 0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00     ; C
+                fcb 0x78,0x24,0x24,0x24,0x24,0x24,0x78,0x00     ; D
+                fcb 0x7C,0x40,0x40,0x70,0x40,0x40,0x7C,0x00     ; E
+                fcb 0x7C,0x40,0x40,0x70,0x40,0x40,0x40,0x00     ; F
+                fcb 0x38,0x44,0x40,0x40,0x4C,0x44,0x38,0x00     ; G
+                fcb 0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00     ; H
+                fcb 0x38,0x10,0x10,0x10,0x10,0x10,0x38,0x00     ; I
+                fcb 0x04,0x04,0x04,0x04,0x04,0x44,0x38,0x00     ; J
+                fcb 0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00     ; K
+                fcb 0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00     ; L
+                fcb 0x44,0x6C,0x54,0x54,0x44,0x44,0x44,0x00     ; M
+                fcb 0x44,0x44,0x64,0x54,0x4C,0x44,0x44,0x00     ; N
+                fcb 0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00     ; O
+                fcb 0x78,0x44,0x44,0x78,0x40,0x40,0x40,0x00     ; P
+                fcb 0x38,0x44,0x44,0x44,0x54,0x48,0x34,0x00     ; Q
+                fcb 0x78,0x44,0x44,0x78,0x50,0x48,0x44,0x00     ; R
+                fcb 0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00     ; S
+                fcb 0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x00     ; T
+                fcb 0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00     ; U
+                fcb 0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00     ; V
+                fcb 0x44,0x44,0x44,0x44,0x54,0x6C,0x44,0x00     ; W
+                fcb 0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00     ; X
+                fcb 0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00     ; Y
+                fcb 0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00     ; Z
+                fcb 0x38,0x20,0x20,0x20,0x20,0x20,0x38,0x00     ; ]
+                fcb 0x00,0x40,0x20,0x10,0x08,0x04,0x00,0x00     ; \
+                fcb 0x38,0x08,0x08,0x08,0x08,0x08,0x38,0x00     ; [
+                fcb 0x10,0x38,0x54,0x10,0x10,0x10,0x10,0x00     ; UP ARROW
+                fcb 0x00,0x10,0x20,0x7C,0x20,0x10,0x00,0x00     ; LEFT ARROW
+                fcb 0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00     ; ^
+                fcb 0x00,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00     ; a
+                fcb 0x40,0x40,0x58,0x64,0x44,0x64,0x58,0x00     ; b
+                fcb 0x00,0x00,0x38,0x44,0x40,0x44,0x38,0x00     ; c
+                fcb 0x04,0x04,0x34,0x4C,0x44,0x4C,0x34,0x00     ; d
+                fcb 0x00,0x00,0x38,0x44,0x7C,0x40,0x38,0x00     ; e
+                fcb 0x08,0x14,0x10,0x38,0x10,0x10,0x10,0x00     ; f
+                fcb 0x00,0x00,0x34,0x4C,0x4C,0x34,0x04,0x38     ; g
+                fcb 0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x00     ; h
+                fcb 0x00,0x10,0x00,0x30,0x10,0x10,0x38,0x00     ; i
+                fcb 0x00,0x04,0x00,0x04,0x04,0x04,0x44,0x38     ; j
+                fcb 0x40,0x40,0x48,0x50,0x60,0x50,0x48,0x00     ; k
+                fcb 0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00     ; l
+                fcb 0x00,0x00,0x68,0x54,0x54,0x54,0x54,0x00     ; m
+                fcb 0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x00     ; n
+                fcb 0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00     ; o
+                fcb 0x00,0x00,0x78,0x44,0x44,0x78,0x40,0x40     ; p
+                fcb 0x00,0x00,0x3C,0x44,0x44,0x3C,0x04,0x04     ; q
+                fcb 0x00,0x00,0x58,0x64,0x40,0x40,0x40,0x00     ; r
+                fcb 0x00,0x00,0x3C,0x40,0x38,0x04,0x78,0x00     ; s
+                fcb 0x20,0x20,0x70,0x20,0x20,0x24,0x18,0x00     ; t
+                fcb 0x00,0x00,0x44,0x44,0x44,0x4C,0x34,0x00     ; u
+                fcb 0x00,0x00,0x44,0x44,0x44,0x28,0x10,0x00     ; v
+                fcb 0x00,0x00,0x44,0x54,0x54,0x28,0x28,0x00     ; w
+                fcb 0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x00     ; x
+                fcb 0x00,0x00,0x44,0x44,0x44,0x3C,0x04,0x38     ; y
+                fcb 0x00,0x00,0x7C,0x08,0x10,0x20,0x7C,0x00     ; z
+                fcb 0x08,0x10,0x10,0x20,0x10,0x10,0x08,0x00     ; {
+                fcb 0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x00     ; |
+                fcb 0x20,0x10,0x10,0x08,0x10,0x10,0x20,0x00     ; }
+                fcb 0x20,0x54,0x08,0x00,0x00,0x00,0x00,0x00     ; ~
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00     ; _
+; HDRAW command
+HDRAW           tst HRMODE                      ; grahics mode?
+                lbeq SE6EF                      ; brif not
+                lbrn 0
+                ldx #0                          ; set empty string for "end of DRAW"
+                ldb #1
+                pshs x,b
+                stb SETFLG                      ; set up for "set" mode
+                stx VD5                         ; clear update and draw flags
+                jsr SE731                       ; set up color byte
+                jsr LB156                       ; evaluate command string
+SF3B8           jsr LB654                       ; fetch command string details
+                bra SF3C5                       ; interpret command string
+SF3BD           jsr SF591                       ; fetch command character
+                jmp SF5A7                       ; evaluate number
+SF3C3           puls b,x                        ; get "caller" command string details
+SF3C5           stb VD8                         ; save string pointer
+                beq SF3C3                       ; brif end of string - try another
+                stx VD9                         ; set string data pointer
+                lbeq SF4D0                      ; brif we hit the top of the stack
+SF3CF           tst VD8                         ; is there anything left?
+                beq SF3C3                       ; brif not
+                jsr SF591                       ; get command character
+                cmpa #';                        ; separator?
+                beq SF3CF                       ; brif so - ignore it
+                cmpa #''                        ; '?
+                beq SF3CF                       ; brif so - ignore that too
+                cmpa #'N                        ; update toggle?
+                bne SF3E6                       ; brif not
+                com VD5                         ; toggle the "update" flag (if set, return to original position after)
+                bra SF3CF                       ; process more
+SF3E6           cmpa #'B                        ; blank modifier?
+                bne SF3EE                       ; brif not
+                com VD6                         ; toggle "draw" flag - 0 = draw, nonzero = don't draw
+                bra SF3CF                       ; process more
+SF3EE           cmpa #'X                        ; substring call?
+                lbeq SF4A1                      ; brif so - process it
+                cmpa #'M                        ; M (move)?
+                lbeq SF54C                      ; brif so - process "move"
+                pshs a                          ; save command character
+                ldb #1                          ; default count if no number follows
+                clr VD3                         ; clear MS byte of count
+                stb VD4                         ; save LS byte of count
+                tst VD8                         ; is there anything left?
+                beq SF417                       ; brif not
+                jsr SF591                       ; get command character
+                jsr LB3A2                       ; set C if not alpha
+                pshs cc                         ; save alpha flag
+                jsr SF5F2                       ; back up command pointer
+                puls cc                         ; get back alpha flag
+                bcc SF417                       ; brif command is alpha
+                bsr SF3BD                       ; evaluate decimal string
+SF417           puls a                          ; get command back
+                cmpa #'C                        ; C (colour)?
+                beq SF445                       ; brif so
+                cmpa #'A                        ; A (angle)?
+                beq SF451                       ; brif so
+                cmpa #'S                        ; S (scale)?
+                beq SF45C                       ; brif so
+                cmpa #'U                        ; U (up)?
+                beq SF496                       ; brif so
+                cmpa #'D                        ; D (down)?
+                beq SF492                       ; brif so
+                cmpa #'L                        ; L (left)?
+                beq SF48C                       ; brif so
+                cmpa #'R                        ; R (right)?
+                beq SF485                       ; brif so
+                suba #'E                        ; shift E,F,G,H to be 0-3
+                beq SF473                       ; brif E (UR)
+                deca                            ; F (DR)
+                beq SF46D                       ; brif so
+                deca                            ; G (DL)
+                beq SF47D                       ; brif so
+                deca                            ; H (UL)
+                beq SF467                       ; brif so
+                jmp LB44A                       ; raise error if unrecognized command
+SF445           jsr SE711                       ; adjust colour code for graphics mode
+                stb H.FCOLOR                    ; set new foreground
+                jsr SE731                       ; set up colour byte
+                lbra SF3CF                      ; handle another command
+SF451           cmpb #4                         ; only 4 angles valid
+                lbhs LB44A                      ; brif invalid angle
+                stb ANGLE                       ; save draw angle
+                lbra SF3CF                      ; go handle another command
+SF45C           cmpb #63                        ; only 0-62 are valid scale factors
+                lbhs LB44A                      ; brif invalid scale
+                stb SCALE                       ; set scale factor
+                lbra SF3CF                      ; process another command
+SF467           lda VD3                         ; get count MSB
+                bsr NEGACCD                     ; negate horizontal difference (go left)
+                bra SF46F                       ; go the same distance up
+SF46D           lda VD3                         ; get count MSB
+SF46F           tfr d,x                         ; go same distance right as down
+                bra SF4D4                       ; go handle movement/drawing
+SF473           lda VD3                         ; get MSB of count
+                tfr d,x                         ; going same distance on both axes
+                bsr NEGACCD                     ; negate the vertical distance
+                exg d,x                         ; put vertical in X, horizontal in D
+                bra SF4D4                       ; go handle drawing and moving
+SF47D           lda VD3                         ; get MSB of count
+                tfr d,x                         ; go same distance on both axes
+                bsr NEGACCD                     ; go left horizontally (and down vertically)
+                bra SF4D4                       ; go handle drawing and moving
+SF485           lda VD3                         ; get MSB of difference (going right)
+SF487           ldx #0                          ; no vertical movement
+                bra SF4D4                       ; handle drawing/moving
+SF48C           lda VD3                         ; get MSB of count
+                bsr NEGACCD                     ; negate because going left
+                bra SF487                       ; set no vertical difference, handle drawing/moving
+SF492           lda VD3                         ; get MSB of count
+                bra SF49A                       ; go make horizontal difference 0, use positive distance for down
+SF496           lda VD3                         ; get MSB of count
+                bsr NEGACCD                     ; use negative distance for up
+SF49A           ldx #0                          ; use 0 horizontal distance
+                exg x,d                         ; put horizontal and vertical in the right places
+                bra SF4D4                       ; go move/draw
+SF4A1           jsr SF611                       ; interpret command as a variable
+                ldb #2                          ; see if we're about to run out of memory
+                jsr LAC33
+                ldb VD8                         ; get remaining characters in current command string
+                ldx VD9                         ; get current command string pointer
+                pshs x,b                        ; save the stack frame
+                jmp SF3B8                       ; go evaluate the string
+SF4B2           ldb SCALE                       ; get scaling factor
+                beq SF4D1                       ; brif none - use full scale
+                clra                            ; zero extend scale
+                exg d,x                         ; put distance in D, save scale factor
+                sta ,-s                         ; save MSB of distance and set flags on sign
+                bpl SF4BF                       ; brif positive distance
+                bsr NEGACCD                     ; make it positive if negative
+SF4BF           jsr SEBCB                       ; multiply D and X
+                tfr U,D                         ; save LSW in D
+                lsra                            ; divide by 4
+                rorb
+                lsra
+                rorb
+                tst ,s+                         ; was original positive?
+                bpl SF4D0                       ; brif so
+NEGACCD         nega                            ; negate D
+                negb
+                sbca #0
+SF4D0           rts
+SF4D1           tfr x,d                         ; keep unmodified distance
+                rts
+SF4D4           pshs d                          ; save horizontal distance
+                bsr SF4B2                       ; apply scale factor to vertical distance
+                puls x                          ; get back horizontal distance
+                pshs d                          ; save scaled vertical distance
+                bsr SF4B2                       ; apply scale to horizontal distance
+                puls x                          ; get back the vertical distance
+                ldy ANGLE                       ; get draw angle (using Y to avoid clobbering D)
+                pshs y                          ; save it
+SF4E5           tst ,s                          ; check angle
+                beq SF4F1                       ; brif no angle
+                exg x,d                         ;* swap horizontal and vertical distances then negate new horizontal
+                bsr NEGACCD                     ;* distance, which rotates 90° counterclockwise
+                dec ,s                          ; count down the angle
+                bra SF4E5                       ; see if we have rotated enough times
+SF4F1           puls y                          ; clean up stack
+                ldu #0                          ; default end position to 0
+                addd HORDEF                     ; add distance to current draw position
+                bmi SF4FC                       ; brif we went negative - use minimal 0
+                tfr d,u                         ; use calculated draw coordinate
+SF4FC           tfr x,d                         ; fetch vertical distance for calculation
+                ldx #0                          ; default end position to 0
+                addd VERDEF                     ; add distance to draw position
+                bmi SF507                       ; brif we went negative - use minimal 0
+                tfr d,x                         ; use calculated coordinate
+SF507           cmpu #640                       ; is it out of range completely?
+                blo SF510                       ; brif not
+                ldu #639                        ; maximize to right edge of screen
+SF510           lda HRMODE                      ; get graphics mode
+                cmpa #2                         ; is it a 320 mode?
+                bgt SF51F                       ; brif not
+                cmpu #320                       ; out of range for 320 mode?
+                blo SF51F                       ; brif not
+                ldu #319                        ; maximize to right edge of screen
+SF51F           cmpx #192                       ; out of range vertically?
+                blo SF527                       ; brif not
+                ldx #191                        ; maximize to bottom of screen
+SF527           ldd HORDEF                      ; set start position to current draw position
+                std HORBEG
+                ldd VERDEF
+                std VERBEG
+                stx VEREND                      ; set calculated position as end position
+                stu HOREND
+                tst VD5                         ; are we going to update draw position?
+                bne SF53B                       ; brif not
+                stx VERDEF                      ; set new draw position
+                stu HORDEF
+SF53B           jsr SEA0D                       ; "normalize" coordinates
+                tst VD6                         ; are we doing to draw a line?
+                bne SF545                       ; brif not
+                jsr SE94E                       ; draw a line
+SF545           clr VD5                         ; reset the "update" flag
+                clr VD6                         ; reset the "draw" flag
+                jmp SF3CF                       ; go handle another command
+SF54C           jsr SF591                       ; get input character
+                pshs a                          ; save it
+                jsr SF578                       ; evaluate horizontal distance
+                pshs d                          ; save it
+                jsr SF591                       ; get a character
+                cmpa #',                        ; is it a comma separator?
+                lbne LB44A                      ; brif not - raise error
+                jsr SF575                       ; evaluate the vertical distance
+                tfr d,x                         ; save vertical distance
+                puls u                          ; get horizontal distance
+                puls a                          ; get first command character
+                cmpa #'+                        ; +?
+                beq SF570                       ; treat coordinates as relative displacements
+                cmpa #'-                        ; -?
+                bne SF507                       ; brif neither + or -; treat as absolute coordinates
+SF570           tfr u,d                         ; put horizontal distance in D
+                jmp SF4D4                       ; treat distances as offsets
+SF575           jsr SF591                       ; get character
+SF578           cmpa #'+                        ; +?
+                beq SF583                       ; brif so - do positive
+                cmpa #'-                        ; -?
+                beq SF584                       ; brif so - do negative
+                jsr SF5F2                       ; back up input pointer
+SF583           clra                            ; flag positive
+SF584           pshs a                          ; save sign flag
+                jsr SF3BD                       ; evaluate decimal number
+                tst ,s+                         ; is it positive?
+                beq SF590                       ; brif so
+                negb                            ; negate the value - BUG: should be JSR NEGACCD; this code sequence doesn't work
+                sbca #0
+SF590           rts
+SF591           pshs x                          ; save register
+SF593           tst VD8                         ; is there anything to fetch?
+                lbeq LB44A                      ; brif not - raise error
+                ldx VD9                         ; get command pointer
+                lda ,x+                         ; get command character
+                stx VD9                         ; save updated pointer
+                dec VD8                         ; account for character consumed
+                cmpa #0x20                      ; space?
+                beq SF593                       ; brif so - skip it
+                puls x,pc                       ; restore register and return
+SF5A7           cmpa #'=                        ; is it variable equate?
+                bne SF5B6                       ; brif not
+                pshs u,y                        ; save registers
+                bsr SF611                       ; interpret variable in command string
+                jsr LB3E9                       ; convert to integer in D
+                std VD3                         ; save as count
+                puls y,u,pc                     ; restore registers and return
+SF5B6           jsr SF608                       ; clear carry if numeric
+                lbcs LB44A                      ; bail if not numeric
+                clr VD3                         ; initialize count to 0
+                clr VD4
+SF5C1           suba #'0                        ; remove ASCII bias
+                sta VD7                         ; save digit value
+                ldd VD3                         ; get accumulated value
+                bsr SF5FD                       ; multiply by 10
+                addb VD7                        ; add digit value
+                adca #0                         ; propagate carry
+                std VD3                         ; save accumulated count value
+                lda HRMODE                      ; get graphics mode
+                cmpa #2                         ; is it a 640 mode?
+                bgt SF5DA                       ; brif so
+                ldd #319                        ; get max for 320 mode
+                bra SF5DD
+SF5DA           ldd #639                        ; get max for 640 mode
+SF5DD           cmpd VD3                        ; is the value in range for a horizontal coordinate?
+                lblt LB44A                      ; brif not
+                ldd VD3                         ; get accumulated value
+                tst VD8                         ; is there anything more to parse?
+                beq SF5FA                       ; brif not
+                jsr SF591                       ; get a character
+                jsr SF608                       ; set C if not digit
+                bcc SF5C1                       ; brif digit - add to accumulated value
+SF5F2           inc VD8                         ; account for character being unfetched
+                ldx VD9                         ; move command pointer back
+                leax -1,x
+                stx VD9
+SF5FA           ldd VD3                         ; get accumulated value
+                rts
+SF5FD           aslb                            ; times 2
+                rola
+                pshs d                          ; save 2D
+                aslb                            ; times 4
+                rola
+                aslb                            ; times 8
+                rola
+                addd ,s++                       ; 8D+2D=10D
+                rts
+SF608           cmpa #'0                        ; is it less than ASCII 0?
+                blo SF610                       ; brif so - sets C
+                suba #'9+1                      ; set C if > ASCII 9
+                suba #-('9+1)
+SF610           rts
+SF611           ldx VD9                         ; get command pointer
+                pshs x                          ; save it
+                jsr SF591                       ; get command character
+                jsr LB3A2                       ; set C if not alpha
+                lbcs LB44A                      ; brif not variable name
+SF61F           jsr SF591                       ; get command character
+                cmpa #';                        ; is it end of variable string?
+                bne SF61F                       ; brif not
+                puls x                          ; get back start of variable
+                ldu CHARAD                      ; save interpreter input pointer
+                pshs u
+                stx CHARAD                      ; save command string pointer as interpeter input
+                jsr LB284                       ; evaluate variable
+                puls x                          ; restore interpreter input pointer
+                stx CHARAD
+                rts
+; WIDTH command
+WIDTH           clr HRMODE                      ; turn off graphics
+                lbrn 0
+                cmpa #0                         ; end of line? (BUG: should do a BEQ before the CLR above)
+                beq SF64F                       ; brif so - raise error if no argument (won't trigger on :)
+                jsr EVALEXPB                    ; evaluate width argument
+                cmpb #32                        ; 32 columns?
+                beq COL32                       ; brif so
+                cmpb #40                        ; 40 columns?
+                beq COL40                       ; brif so
+                cmpb #80                        ; 80 columns?
+                beq COL80                       ; brif so
+SF64F           jmp LB44A                       ; raise FC error
+COL32           clra                            ; set text mode to 32 columns
+                sta HRWIDTH
+                jsr LA928                       ; clear screen
+                lbsr SETTEXT                    ; set up display for 32 column screen
+                rts
+COL40           lda #1                          ; mode number for 40 columns
+                sta HRWIDTH                     ; set text screen mode
+                lbsr SF772                      ; map text screen
+                lda #40                         ; set up scren size in character cells
+                ldb #ROWMAX
+                std H.COLUMN
+                ldd #HRESSCRN+40*ROWMAX*2       ; set end address of screen
+SF66D           std H.DISPEN                    ; save end address
+                bsr SF68C                       ; clear the screen
+                lbsr SF778                      ; unmap text screen
+                lbsr SETTEXT                    ; set up display for the text screen
+                rts
+COL80           lda #2                          ; mode number for 80 columns
+                sta HRWIDTH                     ; set text screen mode
+                lbsr SF772                      ; map the screen
+                lda #80                         ; set up screen size in character cells
+                ldb #ROWMAX
+                std H.COLUMN
+                ldd #HRESSCRN+80*ROWMAX*2       ; set end address of screen
+                bra SF66D                       ; set up rest of parameters
+SF68C           ldx #HRESSCRN                   ; set cursor address to top left corner
+                lbrn 0
+                stx H.CRSLOC
+                lda #0x20                       ; use space to clear screen
+                ldb H.CRSATT                    ; get current attributes
+SF69B           std ,x++                        ; blank a character cell
+                cmpx H.DISPEN                   ; end of screen?
+                blo SF69B                       ; brif not
+                ldx #HRESSCRN                   ; reset to top of screen
+                clra                            ; reset cursor coordinates to 0,0
+                sta H.CURSX
+                sta H.CURSY
+                rts
+; CLS patch entered from the other patch in the ECB area
+ALINK23         puls cc                         ; restore zero flag
+                lbrn 0
+                beq SF6E0                       ; brif no arguments
+                jsr EVALEXPB                    ; get colour number
+                tstb                            ; 0?
+                beq SF6E0                       ; brif so - treat as no arguments
+                cmpb #8                         ; valid colour?
+                bhi SF6E7                       ; brif not - do the easter egg or the other easter egg
+                decb                            ; zero-base the colour
+                leay IM.PALET,pcr               ; point to current palette settings
+                lda b,y                         ; get the real colour
+                sta V.BORDER                    ; set border colour
+                lbsr SF766                      ; set border colour in GIME initializers
+                stb H.CRSATT                    ; set attributes to foreground 0, background as selected, no blink or underline
+                lda #0x20                       ; get space character
+                lbsr SF772                      ; map screen
+                ldx #HRESSCRN                   ; get address of start of screen
+                stx H.CRSLOC                    ; put cursor there
+                bsr SF69B                       ; clear screen
+SF6DC           lbsr SF778                      ; unmap screen
+                rts
+SF6E0           lbsr SF772                      ; map screen
+                bsr SF68C                       ; clear screen
+                bra SF6DC                       ; ummap screen and return
+SF6E7           clr H.CRSATT                    ; reset attributes to colours 0,0, no blink or underline
+                lda IM.PALET                    ; get colour in register 0
+                sta V.BORDER                    ; set border colour
+                bsr SF766                       ; reset border colour in GIME initializers
+                cmpb #100                       ; is it CLS 100?
+SF6F4           beq SF730                       ; brif so - do the easter egg
+                bsr SF772                       ; map the screen
+                bsr SF68C                       ; clear screen
+                bsr SF778                       ; unmap screen
+                ldx #MICROMS-1                  ; point to Microware commercial
+                jmp STRINOUT                    ; display it
+MICROMS         fcc 'Microware Systems Corp.'
+                fcb 0x0d,0x00
+AUTHORMS        fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00     ; the ROM/RAM copy sets this to the actual easter egg text
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00
+SF730           bsr SF772                       ; map the screen
+                lbsr SF68C                      ; clear it
+                bsr SF778                       ; unmap the screen
+                ldx #AUTHORMS-1                 ; point to the easter egg
+                jsr STRINOUT                    ; display it
+                pshs x                          ; save X for some reason
+                leax >SF6F4,pcr                 ; point to start of easter egg code
+                lda #0x12                       ; NOP opcode
+                sta ,x+                         ; blank out the branch that brings us here
+                sta ,x
+                leax >AUTHORMS,pcr              ; point to author message
+SF74D           sta ,x+                         ; blank out character in string or this code
+                cmpx #SF74D                     ; end of string or display code?
+                blo SF74D                       ; brif not
+                puls x                          ; restore X
+                rts
+; Line input routine patch for handling CLEAR
+ALINK27         tst HRWIDTH                     ; is it 40/80 column screen?
+                bne SF761                       ; brif so
+                jsr LA928                       ; clear 32 column screen
+SF75E           jmp LA390                       ; go make to mainline
+SF761           lbsr SF6E0                      ; clear the screen
+                bra SF75E                       ; return to mainline
+SF766           pshs y                          ; save register
+                leay SE03B,pcr                  ; point to text initializers
+                sta 3,y                         ; set border in 40 column initializer
+                sta 12,y                        ; set border in 80 column initializer
+                puls y,pc                       ; restore registers and return
+SF772           orcc #0x50                      ; clobber interrupts
+                lbsr SELTEXT                    ; map the text screen (by setting *all 16* MMU registers)
+                rts
+SF778           lbsr SETMMU                     ; unmap text screen (by setting *all 16* MMU registers)
+                andcc #0xaf                     ; restart interrupts
+                rts
+; The driver for putting characters on the 40 and 80 column screen is here, modulo the WIDTH command and clear
+; screen routines above.
+;
+; There are several major problems with this driver:
+;
+; * Cursor handling is overly complicated. Instead of doing what Color Basic does and only show the cursor
+; when waiting for input in the generic input routine, this driver displays it almost all of the time and, thus,
+; has all manner of code for managing the cursor that would not be needed otherwise.
+; * The system goes out of its way to set up the screen height and width values. Then, it doesn't bother using
+; them consistently, especially during the screen scrolling routine. Indeed, the screen scrolling routine could
+; be made completely general purpose by using two pointers, say U for the destination and X for the source. Then
+; the column count could be used to decide the line width (to calculate the offset betwen U and X) and then the
+; row count could be used to set the row number after the scrolling is done. This would remove any hard coded
+; offsets or screen size assumptions.
+; * The routines for mapping and unmapping the text screen are inexcusably slow. Only one MMU register needs to
+; be changed in either routine. However, instead of doing that, the routines use an inefficient routine that
+; sets *all 16* MMU registers (both tasks!). This reduces screen output speed so much that a fast reader can
+; actually keep up with the output going full speed. Simply replacing these two routines with simpler ones that
+; do not do that dumbassery gets performance on par with the 32 column VDG screen.
+;
+; Along with the above, some of the code is far more convoluted than it needs to be, but that is relatively
+; benign compared to everything else.
+;
+; Blink cursor patch
+ALINK24         bsr SF787                       ; blink the cursor
+                jsr KEYIN                       ; get keypress
+                beq ALINK24                     ; brif no key pressed
+                puls b,x,pc                     ; return to caller
+SF787           dec BLKCNT                      ; time to blink cursor?
+                bne SF7A8                       ; brif not
+                ldb #11                         ; reset blink counter
+                stb BLKCNT
+                bsr SF772                       ; map screen
+                ldx H.CRSLOC                    ; get cursor pointer
+                lda 1,x                         ; get current attributes
+                bita #0x40                      ; is underline on?
+                beq SF79F                       ; brif not - enable it
+                lda H.CRSATT                    ; use current attributes if it is
+                bra SF7A4
+SF79F           lda H.CRSATT                    ; get current attributes
+                ora #0x40                       ; turn on underline
+SF7A4           sta 1,x                         ; save new attributes
+                bsr SF778                       ; unmap screen
+SF7A8           ldx #DEBDEL                     ; do a delay
+                jmp LA7D3
+; Put character on screen patch
+ALINK22         bsr SF772                       ; map the screen
+                lbrn 0
+                ldx H.CRSLOC                    ; get cursor location
+                cmpa #0x08                      ; backspace?
+                bne SF7C4                       ; brif not
+                cmpx #HRESSCRN                  ; at start of screen?
+                beq SF7DE                       ; brif so - do nothing
+                bsr SF7E2                       ; do a backspace
+                bra SF7DE                       ; finish up
+SF7C4           cmpa #0x0d                      ; carriage return?
+                bne SF7CC                       ; brif not
+                bsr SF827                       ; do a carriage return
+                bra SF7D7                       ; finish up with scroll check
+SF7CC           cmpa #0x20                      ; is it a control code?
+                blo SF7DE                       ; brif so - do nothing
+                ldb H.CRSATT                    ; get current attributes
+                std ,x                          ; put character on screen
+                bsr SF807                       ; move cursor forward
+SF7D7           cmpx H.DISPEN                   ; end of screen?
+                blo SF7DE                       ; brif not
+                bsr SF854                       ; scroll screen
+SF7DE           bsr SF778                       ; unmap the screen
+                puls a,b,x,pc                   ; restore registers and return
+SF7E2           pshs b,a                        ; save registers
+                lda #0x20                       ; space character
+                ldb H.CRSATT                    ; get attributes
+                std ,x                          ; turns off cursor at this position and blanks it
+                orb #0x40                       ; turn on underline (we'll put a cursor in the previous position)
+                std -2,x                        ; put blank and cursor back one
+                leax -2,x                       ; move pointer back
+                stx H.CRSLOC                    ; save new cursor pointer
+                ldd H.CURSX                     ; get coordinates
+                deca                            ; move horizontal back
+                bpl SF802                       ; brif we didn't wrap
+                decb                            ; move vertical back
+                stb H.CURSY                     ; save it
+                lda H.COLUMN                    ; get screen width
+                deca                            ; coordinates are zero-based so now we have the max horizontal coord
+SF802           sta H.CURSX                     ; save new horizontal position
+                puls a,b,pc                     ; restore registers and return
+SF807           pshs a,b                        ; save registers
+                lda #0x20                       ; we'll blank a character for the cursor
+                ldb H.CRSATT                    ; get attributes
+                orb #0x40                       ; force underline for cursor
+                leax 2,x                        ; move pointer forward
+                std ,x                          ; put blank and cursor on screen
+                stx H.CRSLOC                    ; save new cursor position
+                ldd H.CURSX                     ; get coordinates
+                inca                            ; move right
+                cmpa H.COLUMN                   ; did we hit the edge?
+                blo SF802                       ; brif not - save new horizontal coordinate and return
+                incb                            ; bump line
+                stb H.CURSY                     ; save new line
+                clra                            ; reset to left side of screen
+                bra SF802                       ; save new horizontal coordinate and return
+SF827           pshs a,b                        ; save registers
+                lda #0x20                       ; get space character
+                ldb H.CRSATT                    ; get attributes
+SF82E           std ,x++                        ; blank a character
+                pshs a                          ; save character
+                lda H.CURSX                     ; get horizontal position
+                inca                            ; bump it
+                sta H.CURSX                     ; save new position
+                cmpa H.COLUMN                   ; edge of screen?
+                puls a                          ; restore character
+                blo SF82E                       ; brif not end of line yet
+                stx H.CRSLOC                    ; save cursor location
+                clr H.CURSX                     ; reset to left edge
+                inc H.CURSY                     ; bump row
+                lda #0x20                       ; space character
+                ldb H.CRSATT                    ; get attributes
+                orb #0x40                       ; turn on underline
+                std ,x                          ; put a cursor on screen
+                puls a,b,pc                     ; restore registers and return
+SF854           pshs a,b                        ; save registers
+                ldx #HRESSCRN                   ; point to start of screen
+                lda H.COLUMN                    ; get screen width
+                cmpa #40                        ; is it 40 columns?
+                bne SF86E                       ; brif not - do 80 column scroll
+SF860           ldd 2*40,x                      ; get character cell from one line down
+                std ,x++                        ; move it here
+                cmpx #HRESSCRN+(ROWMAX-1)*40*2  ; at start of last row?
+                blo SF860                       ; brif not
+SF86A           bsr SF87B                       ; fill last row with spaces
+                puls a,b,pc                     ; restore registers and return
+SF86E           ldd 80*2,x                      ; get a character cell from next row
+                std ,x++                        ; put it here
+                cmpx #HRESSCRN+(ROWMAX-1)*80*2  ; at start of last row?
+                blo SF86E                       ; brif not
+                bra SF86A                       ; blank out last row and finish up
+SF87B           clr H.CURSX                     ; reset column to 0
+                lda #ROWMAX-1                   ; reset row number to bottom of screen
+                sta H.CURSY
+                lda #0x20                       ; get space character
+                ldb H.CRSATT                    ; get attributes
+                pshs x                          ; save pointer to start of row
+SF88A           std ,x++                        ; blank a character
+                cmpx H.DISPEN                   ; at end of screen?
+                bne SF88A                       ; brif not
+                clr H.CURSX                     ; reset horizontal position to margin
+                puls x                          ; get start of line pointer
+                lda #0x20                       ; space haracter
+                ldb H.CRSATT                    ; get attributes
+                orb #0x40                       ; turn on underline
+                std ,x                          ; put a bleeping cursor at start of line
+                stx H.CRSLOC                    ; set cursor position
+                rts
+; Conditional newline patch. Note that this maps and unmaps the text screen in 40/80 column mode
+; but that is completely unneeded to just test the X coordinate.
+ALINK26         tst DEVNUM                      ; is it screen?
+                bne SF8AB                       ; brif not
+                tst HRWIDTH                     ; VDG screen?
+                bne SF8B1                       ; brif not
+SF8AB           jsr LA35F                       ; set up print parameters
+                jmp LB95F                       ; re-enter mainline code
+SF8B1           lbsr SF772                      ; map screen
+                tst H.CURSX                     ; at left margin?
+                pshs cc                         ; save Z flag
+                lbsr SF778                      ; unmap screen
+                puls cc                         ; get back Z flag
+                lbne LB958                      ; brif not at left margine - do CR
+                rts
+; PRINT @ patch
+ALINK25         tst HRWIDTH                     ; VDG screen?
+                bne SF8CD                       ; brif not - raise error
+                jsr LA554                       ; move cursor to specified position
+                jmp LB905                       ; return to mainline code
+SF8CD           ldb #39*2                       ; code for HP error
+                jmp LAC46                       ; raise error
+; LOCATE command
+; The parameter checking here could simply use the H.COLUMN and H.ROW variables and it would
+; be loads simpler. Also, if the dumbassery with the cursor wasn't a thing, this routine wouldn't
+; need to mess with mapping the screen or screwing around with the cursor.
+LOCATE          ldb HRWIDTH                     ; is it 40/80 column screen?
+                lbrn 0
+                beq SF8CD                       ; brif not - raise error
+                pshs b                          ; save screen mode
+                jsr SE7B2                       ; evaluate coordinates
+                lda BINVAL+1                    ; get X coordinate
+                puls b                          ; get back screen mode
+                cmpb #1                         ; is it 40 column screen?
+                bne SF8EB                       ; brif not
+                cmpa #40                        ; in range for 40 columns?
+                bra SF8ED
+SF8EB           cmpa #80                        ; in range for 80 columns?
+SF8ED           lbhs LB44A                      ; brif not - raise error
+                ldb VERBEG+1                    ; get Y coordinate
+                cmpb #ROWMAX                    ; is it in range?
+                bhs SF8ED                       ; brif not - raise error
+                pshs d                          ; save new coordinates
+                lbsr SF772                      ; map screen
+                std H.CURSX                     ; set screen coordinates
+                ldx H.CRSLOC                    ; get pointer to old position
+                lda H.CRSATT                    ; replace attributes with current ones
+                sta 1,x
+                lda H.COLUMN                    ; get number of columns (why not use this above?)
+                asla                            ; two bytes per character cell
+                mul                             ; now D is offset to start of row
+                ldx #HRESSCRN                   ; get start of screen
+                leax d,x                        ; now X points to the start of the line
+                puls a,b                        ; get back column and row numbers
+                asla                            ; two bytes per character cell
+                tfr a,b                         ; need this in B since we'll overflow singed 8 bits
+                abx                             ; offset to correct cursor position
+                lda H.CRSATT                    ; get attributes
+                ora #0x40                       ; enable underline
+                sta 1,x                         ; enable cursor
+                stx H.CRSLOC                    ; save new cursor pointer
+                lbsr SF778                      ; unmap screen
+                rts
+; HSTAT command
+HSTAT           tst HRWIDTH                     ; is it 40/80 column screen?
+                lbrn 0
+                beq SF8CD                       ; brif not - raise error
+                lbsr SF772                      ; map the screen
+                ldx H.CRSLOC                    ; get cursor pointer
+                ldd ,x                          ; get character and attributes
+                std VCB                         ; save them
+                ldd H.CURSX                     ; get screen coordinates
+                std VCD                         ; save them
+                lbsr SF778                      ; unmap screen
+                jsr LB357                       ; evaluate variable for character
+                stx VARDES                      ; saveit
+                jsr SYNCOMMA                    ; insist on a comma
+                ldb #1                          ; make a single character string
+                jsr LB56D
+                lda VCB                         ; get character on screen
+                jsr LB511                       ; get string details
+                sta ,x                          ; save character in string
+                jsr LB54C                       ; put string on string stack
+                ldx VARDES                      ; point to variable descriptor
+                tst -1,x                        ; is it a string? (should have checked after evaluating instead)
+                lbpl LB151                      ; do type mismatch if number
+                ldy FPA0+2                      ; point to destination string descriptor
+                ldb #5                          ; copy 5 bytes from newly created string into variable
+SF963           lda ,y+                         ; copy byte
+                sta ,x+
+                decb                            ; done all?
+                bne SF963                       ; brif not
+                LDX TEMPPT                      ; point to new string descriptor
+                leax -5,x                       ; BUG: should just call LB675 to remove string from string stack
+                stx TEMPPT
+                jsr LB357                       ; evaluate a variable (for X coord)
+                stx VARDES                      ; save pointer to it
+                jsr SYNCOMMA                    ; insist on a comma after it
+                clra                            ; zero extend attributes
+                ldb VCB+1                       ; get attribute byte
+                jsr GIVABF                      ; convert to float
+                ldx VARDES                      ; point to variable
+                tst -1,x                        ; test if numeric (should have tested VALTYP above)
+                lbmi LB151                      ; TM error if not number
+                jsr LBC35                       ; pack FPA0 to variable
+                jsr LB357                       ; evaluate another variable
+                stx VARDES                      ; save it
+                jsr SYNCOMMA                    ; insist on a comma
+                clra                            ; zero extend the X coordinate
+                ldb VCD                         ; get X coordinate
+                jsr GIVABF                      ; turn into a FP number
+                ldx VARDES                      ; get variable
+                tst -1,x                        ; is it a number (should have tested VALTYP above)
+                LBMI LB151                      ; brif not - TM error
+                jsr LBC35                       ; pack FPA0 to variable
+                jsr LB357                       ; evaluate another variable
+                stx VARDES                      ; save it
+                clra                            ; zero extend Y coordinate
+                ldb VCD+1                       ; get Y coordinate
+                jsr GIVABF                      ; turn into a FP number
+                ldx VARDES                      ; get variable descriptor back
+                tst -1,x                        ; is it a number (should have tested VALTYP above)
+                lbmi LB151                      ; brif not - TM error
+                jsr LBC35                       ; pack FPA0 to variable
+                rts
+; ATTR command
+ATTR            jsr EVALEXPB                    ; evaluate foreground colour
+                lbrn 0
+                cmpb #8                         ; there are 8 valid colours (0-7)
+                lbhs LB44A                      ; brif out of range - raise error
+                aslb                            ; shift over to bits 5,4,3
+                aslb
+                aslb
+                pshs b                          ; save partial attribute byte
+                jsr GETCCH                      ; fetch current character (useless call)
+                jsr SYNCOMMA                    ; insist on comma
+                jsr EVALEXPB                    ; evaluate background colour
+                cmpb #8                         ; is it valid (0-7)?
+                lbhs LB44A                      ; brif not - raise error
+                orb ,s                          ; merge with partial attribute byte
+                leas 1,s                        ; clean up stack (could use ,s+ above)
+                andb #0x3f                      ; make sure we have zeros in bit 7,6 - unneeded
+                pshs b                          ; save colour attributes
+                jsr GETCCH                      ; is there mode?
+SF9E3           beq SFA06                       ; brif no more flags
+                jsr SYNCOMMA                    ; insist on a comma
+                cmpa #'B                        ; B (blink)?
+                bne SF9F6                       ; brif not
+                puls b                          ; set blink bit in accumulated attributes
+                orb #0x80
+                pshs b
+                jsr GETNCH                      ; eat the flag
+                bra SF9E3                       ; look for another flag
+SF9F6           cmpa #'U                        ; U (underline)?
+                lbne LB44A                      ; invalid flag - raise error
+                puls b                          ; get accumulated attributes and set underline bit
+                orb #0x40
+                pshs b
+                jsr GETNCH                      ; eat the flag
+                bra SF9E3                       ; look for another flag
+SFA06           puls b                          ; get new attributes
+                stb H.CRSATT                    ; set them as default
+                rts
+                fcb 0x00,0x00,0x00,0x00         ; unused bytes
+; These are extra glyphs that should be part of the HPRINT font but aren't.
+                fcb 0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x10     ; Ç
+                fcb 0x44,0x00,0x44,0x44,0x44,0x4C,0x34,0x00     ; ü
+                fcb 0x08,0x10,0x38,0x44,0x7C,0x40,0x38,0x00     ; é
+                fcb 0x10,0x28,0x38,0x04,0x3C,0x44,0x3C,0x00     ; â
+                fcb 0x28,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00     ; ä
+                fcb 0x20,0x10,0x38,0x04,0x3C,0x44,0x3C,0x00     ; à
+                fcb 0x10,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00     ; ȧ (or å maybe?)
+                fcb 0x00,0x00,0x38,0x44,0x40,0x44,0x38,0x10     ; ç
+                fcb 0x10,0x28,0x38,0x44,0x7C,0x40,0x38,0x00     ; ê
+                fcb 0x28,0x00,0x38,0x44,0x7C,0x40,0x38,0x00     ; ë
+                fcb 0x20,0x10,0x38,0x44,0x7C,0x40,0x38,0x00     ; è
+                fcb 0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00     ; ï
+                fcb 0x10,0x28,0x00,0x30,0x10,0x10,0x38,0x00     ; î
+                fcb 0x00,0x18,0x24,0x38,0x24,0x24,0x38,0x40     ; ẞ
+                fcb 0x44,0x10,0x28,0x44,0x7C,0x44,0x44,0x00     ; Ä
+                fcb 0x10,0x10,0x28,0x44,0x7C,0x44,0x44,0x00     ; Ȧ (or Å maybe?)
+                fcb 0x08,0x10,0x38,0x44,0x44,0x44,0x38,0x00     ; ó
+                fcb 0x00,0x00,0x68,0x14,0x3C,0x50,0x3C,0x00     ; æ
+                fcb 0x3C,0x50,0x50,0x78,0x50,0x50,0x5C,0x00     ; Æ
+                fcb 0x10,0x28,0x38,0x44,0x44,0x44,0x38,0x00     ; ô
+                fcb 0x28,0x00,0x38,0x44,0x44,0x44,0x38,0x00     ; ö
+                fcb 0x00,0x00,0x38,0x4C,0x54,0x64,0x38,0x00     ; ø
+                fcb 0x10,0x28,0x00,0x44,0x44,0x4C,0x34,0x00     ; û
+                fcb 0x20,0x10,0x44,0x44,0x44,0x4C,0x34,0x00     ; ù
+                fcb 0x38,0x4C,0x54,0x54,0x54,0x64,0x38,0x00     ; Ø
+                fcb 0x44,0x38,0x44,0x44,0x44,0x44,0x38,0x00     ; Ö
+                fcb 0x28,0x44,0x44,0x44,0x44,0x44,0x38,0x00     ; Ü
+                fcb 0x38,0x40,0x38,0x44,0x38,0x04,0x38,0x00     ; §
+                fcb 0x08,0x14,0x10,0x38,0x10,0x50,0x3C,0x00     ; £
+                fcb 0x10,0x10,0x7C,0x10,0x10,0x00,0x7C,0x00     ; ±
+                fcb 0x10,0x28,0x10,0x00,0x00,0x00,0x00,0x00     ; °
+                fcb 0x08,0x14,0x10,0x38,0x10,0x10,0x20,0x40     ; ſ (long s)
+; These are some extra symbol glyphs
+                fcb 0x00,0x10,0x18,0x1C,0x1C,0x18,0x10,0x00     ; solid right pointing triangle
+                fcb 0x00,0x08,0x18,0x38,0x38,0x18,0x08,0x00     ; solid left pointing triangle
+                fcb 0x00,0x00,0x00,0x7E,0x3C,0x18,0x00,0x00     ; solid down pointing triangle
+                fcb 0x00,0x00,0x18,0x3C,0x7E,0x00,0x00,0x00     ; solid up pointing triangle
+                fcb 0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00     ; three horizontal lines with middle one double thick
+                fcb 0x00,0x00,0x30,0x3C,0x14,0x1C,0x00,0x00     ; solid square on top left of open square
+                fcb 0x00,0x7E,0x42,0x5A,0x5A,0x42,0x7E,0x00     ; solid box inside larger box
+                fcb 0x00,0x7E,0x7E,0x00,0x00,0x7E,0x7E,0x00     ; thick equals sign
+                fcb 0x00,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x00     ; solid vertical rectangle
+                fcb 0x00,0x00,0x7E,0x7E,0x7E,0x7E,0x00,0x00     ; solid horizontal rectangle
+                fcb 0x00,0x7E,0x24,0x18,0x18,0x24,0x7E,0x00     ; hour glass
+                fcb 0x00,0x7F,0x00,0x7F,0x7F,0x00,0x7F,0x00     ; left end three horizontal lines with middle one double thick
+                fcb 0x00,0xFE,0x00,0xFE,0xFE,0x00,0xFE,0x00     ; right end three horizontal lines with middle one double thick
+; The above 45 glyphs are duplicated below
+                fcb 0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x10
+                fcb 0x44,0x00,0x44,0x44,0x44,0x4C,0x34,0x00
+                fcb 0x08,0x10,0x38,0x44,0x7C,0x40,0x38,0x00
+                fcb 0x10,0x28,0x38,0x04,0x3C,0x44,0x3C,0x00
+                fcb 0x28,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00
+                fcb 0x20,0x10,0x38,0x04,0x3C,0x44,0x3C,0x00
+                fcb 0x10,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00
+                fcb 0x00,0x00,0x38,0x44,0x40,0x44,0x38,0x10
+                fcb 0x10,0x28,0x38,0x44,0x7C,0x40,0x38,0x00
+                fcb 0x28,0x00,0x38,0x44,0x7C,0x40,0x38,0x00
+                fcb 0x20,0x10,0x38,0x44,0x7C,0x40,0x38,0x00
+                fcb 0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00
+                fcb 0x10,0x28,0x00,0x30,0x10,0x10,0x38,0x00
+                fcb 0x00,0x18,0x24,0x38,0x24,0x24,0x38,0x40
+                fcb 0x44,0x10,0x28,0x44,0x7C,0x44,0x44,0x00
+                fcb 0x10,0x10,0x28,0x44,0x7C,0x44,0x44,0x00
+                fcb 0x08,0x10,0x38,0x44,0x44,0x44,0x38,0x00
+                fcb 0x00,0x00,0x68,0x14,0x3C,0x50,0x3C,0x00
+                fcb 0x3C,0x50,0x50,0x78,0x50,0x50,0x5C,0x00
+                fcb 0x10,0x28,0x38,0x44,0x44,0x44,0x38,0x00
+                fcb 0x28,0x00,0x38,0x44,0x44,0x44,0x38,0x00
+                fcb 0x00,0x00,0x38,0x4C,0x54,0x64,0x38,0x00
+                fcb 0x10,0x28,0x00,0x44,0x44,0x4C,0x34,0x00
+                fcb 0x20,0x10,0x44,0x44,0x44,0x4C,0x34,0x00
+                fcb 0x38,0x4C,0x54,0x54,0x54,0x64,0x38,0x00
+                fcb 0x44,0x38,0x44,0x44,0x44,0x44,0x38,0x00
+                fcb 0x28,0x44,0x44,0x44,0x44,0x44,0x38,0x00
+                fcb 0x38,0x40,0x38,0x44,0x38,0x04,0x38,0x00
+                fcb 0x08,0x14,0x10,0x38,0x10,0x50,0x3C,0x00
+                fcb 0x10,0x10,0x7C,0x10,0x10,0x00,0x7C,0x00
+                fcb 0x10,0x28,0x10,0x00,0x00,0x00,0x00,0x00
+                fcb 0x08,0x14,0x10,0x38,0x10,0x10,0x20,0x40
+                fcb 0x00,0x10,0x18,0x1C,0x1C,0x18,0x10,0x00
+                fcb 0x00,0x08,0x18,0x38,0x38,0x18,0x08,0x00
+                fcb 0x00,0x00,0x00,0x7E,0x3C,0x18,0x00,0x00
+                fcb 0x00,0x00,0x18,0x3C,0x7E,0x00,0x00,0x00
+                fcb 0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00
+                fcb 0x00,0x00,0x30,0x3C,0x14,0x1C,0x00,0x00
+                fcb 0x00,0x7E,0x42,0x5A,0x5A,0x42,0x7E,0x00
+                fcb 0x00,0x7E,0x7E,0x00,0x00,0x7E,0x7E,0x00
+                fcb 0x00,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x00
+                fcb 0x00,0x00,0x7E,0x7E,0x7E,0x7E,0x00,0x00
+                fcb 0x00,0x7E,0x24,0x18,0x18,0x24,0x7E,0x00
+                fcb 0x00,0x7F,0x00,0x7F,0x7F,0x00,0x7F,0x00
+                fcb 0x00,0xFE,0x00,0xFE,0xFE,0x00,0xFE,0x00
+; The glyphs above repeat one more time here but the set is incomplete
+                fcb 0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x10
+                fcb 0x44,0x00,0x44,0x44,0x44,0x4C,0x34,0x00
+                fcb 0x08,0x10,0x38,0x44,0x7C,0x40,0x38,0x00
+                fcb 0x10,0x28,0x38,0x04,0x3C,0x44,0x3C,0x00
+                fcb 0x28,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00
+                fcb 0x20,0x10,0x38,0x04,0x3C,0x44,0x3C,0x00
+                fcb 0x10,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00
+                fcb 0x00,0x00,0x38,0x44,0x40,0x44,0x38,0x10
+                fcb 0x10,0x28,0x38,0x44,0x7C,0x40,0x38,0x00
+                fcb 0x28,0x00,0x38,0x44,0x7C,0x40,0x38,0x00
+                fcb 0x20,0x10,0x38,0x44,0x7C,0x40,0x38,0x00
+                fcb 0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00
+                fcb 0x10,0x28,0x00,0x30,0x10,0x10,0x38,0x00
+                fcb 0x00,0x18,0x24,0x38,0x24,0x24,0x38,0x40
+                fcb 0x44,0x10,0x28,0x44,0x7C,0x44,0x44,0x00
+                fcb 0x10,0x10,0x28,0x44,0x7C,0x44,0x44,0x00
+                fcb 0x08,0x10,0x38,0x44,0x44,0x44,0x38,0x00
+                fcb 0x00,0x00,0x68,0x14,0x3C,0x50,0x3C,0x00
+                fcb 0x3C,0x50,0x50,0x78,0x50,0x50,0x5C,0x00
+                fcb 0x10,0x28,0x38,0x44,0x44,0x44,0x38,0x00
+                fcb 0x28,0x00,0x38,0x44,0x44,0x44,0x38,0x00
+                fcb 0x00,0x00,0x38,0x4C,0x54,0x64,0x38,0x00
+                fcb 0x10,0x28,0x00,0x44,0x44,0x4C,0x34,0x00
+                fcb 0x20,0x10,0x44,0x44,0x44,0x4C,0x34,0x00
+                fcb 0x38,0x4C,0x54,0x54,0x54,0x64,0x38,0x00
+                fcb 0x44,0x38,0x44,0x44,0x44,0x44,0x38,0x00
+                fcb 0x28,0x44,0x44,0x44,0x44,0x44,0x38,0x00
+                fcb 0x38,0x40,0x38,0x44,0x38,0x04,0x38,0x00
+                fcb 0x08,0x14,0x10,0x38,0x10,0x50,0x3C,0x00
+                fcb 0x10,0x10,0x7C,0x10,0x10,0x00,0x7C,0x00
+                fcb 0x10,0x28,0x10,0x00,0x00,0x00,0x00,0x00
+                fcb 0x08,0x14,0x10,0x38,0x10,0x10,0x20,0x40
+                fcb 0x00,0x10,0x18,0x1C,0x1C,0x18,0x10,0x00
+                fcb 0x00,0x08,0x18,0x38,0x38,0x18,0x08,0x00     ; final duplicated glyph: left pointing solid triangle
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00     ; junk unused (or blank space)
+                fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF     ; junk unused (or solid block)
+; This is where the constant page (FExx) would start. It's just garbage in the ROM.
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+; This is where the I/O page would start. It's just garbage in the ROM until the interrupt vectors.
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+                fill 0x00,8
+                fill 0xff,8
+; These are the actual CPU interrupt vectors
+                fdb 0x0000                      ; would be the 6309 illegal instruction trap
+                fdb INT.SWI3                    ; SWI3 bounce vector address
+                fdb INT.SWI2                    ; SWI2 bounce vector address
+                fdb INT.FIRQ                    ; FIRQ bounce vector address
+                fdb INT.IRQ                     ; IRQ bounce vector address
+                fdb INT.SWI                     ; SWI bounce vector address
+                fdb INT.NMI                     ; NMI bounce vector address
+                fdb L8C1B                       ; this is where execution starts on RESET or power on