comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:605ff82c4618
1 *pragma nolist
2 include defs.s
3 DC0DC equ 0xC0DC ; needed for Disk Basic path jump backs
4 *pragma list
5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6 ; EXTENDED COLOR BASIC ROM area
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 org EXBAS
9 fcc 'EX' ; magic number that Color Basic uses to identify the presence of Extended Basic
10 L8002 ldx #L80DE ; point to command interpretation table information
11 ldu #COMVEC+10 ; point to command interpretation table location
12 ldb #10 ; 10 bytes to move
13 jsr LA59A ; copy command interpretation table
14 ldx #LB277 ; initialize Disk Basic's entries to error
15 stx 3,u
16 stx 8,u
17 ldx #XIRQSV ; set up IRQ service routine
18 stx IRQVEC+1
19 ldx ZERO ; reset the TIMER value
20 stx TIMVAL
21 jsr XVEC18 ; do a bunch of initialization
22 ldd #0x2c05 ; initialize DLOAD baud rate constant and timeout
23 std DLBAUD
24 ldx #USR0 ; set up pointer to USR routine addresses
25 stx USRADR
26 ldu #LB44A ; set up USR routine addresses to "FC error"
27 ldb #10 ; there are 10 routines
28 L8031 stu ,x++ ; set a routine to FC error
29 decb ; done all?
30 bne L8031 ; brif not
31 lda #0x7e ; op code of JMP extended (for RAM hook intialization)
32 sta RVEC20 ; command interpretation loop
33 ldx #XVEC20
34 stx RVEC20+1
35 sta RVEC15 ; expression evaluation
36 ldx #XVEC15
37 stx RVEC15+1
38 sta RVEC19 ; number parsing
39 ldx #XVEC19
40 stx RVEC19+1
41 sta RVEC9 ; PRINT
42 ldx #XVEC9
43 stx RVEC9+1
44 sta RVEC17 ; error handler
45 ldx #XVEC17
46 stx RVEC17+1
47 sta RVEC4 ; generic input
48 ldx #XVEC4
49 stx RVEC4+1
50 sta RVEC3 ; generic output
51 ldx #XVEC3
52 stx RVEC3+1
53 sta RVEC8 ; close file
54 ldx #XVEC8
55 stx RVEC8+1
56 sta RVEC23 ; tokenize line
57 ldx #XVEC23
58 stx RVEC23+1
59 sta RVEC18 ; RUN
60 ldx #XVEC18
61 stx RVEC18+1
62 sta EXPJMP ; exponentiation
63 ldx #L8489
64 stx EXPJMP+1
65 jsr L96E6 ; initialize graphics stuff
66 lda PIA0+3 ; enable 60Hz interrupt
67 ora #1
68 sta PIA0+3
69 ldx #'D*256+'K ; magic number for a Disk Basic ROM
70 cmpx DOSBAS ; do we have a Disk Basic ROM?
71 lbeq DOSBAS+2 ; brif so - launch it
72 andcc #0xaf ; enable interrupts
73 L80B2 ldx #L80E8-1 ; show sign on message
74 jsr STRINOUT
75 L80B8 ldx #XBWMST ; install warm start handler
76 stx RSTVEC
77 jmp LA0E2 ; set up warm start flag and launch immediate mode
78 ; Extended Basic warm start code
79 XBWMST fcb 0xff ; mark routine as invalid so that ROMs are always copied to RAM on RESET
80 clr PLYTMR ; cancel any PLAY command in progress
81 clr PLYTMR+1
82 lda PIA0+3 ; enable 60Hz interrupt
83 ora #1
84 sta PIA0+3
85 jmp BAWMST ; let Color Basic's warm start process run
86 ; This code is to fix the famous PCLEAR bug. It replaces dead code in the 1.0 ROM. This patch corrects
87 ; the input pointer so that it points to the correct place after the program has been relocated by
88 ; PCLEAR instead of continuing with something that, in the best case, is a syntax error.
89 L80D0 lda CURLIN ; immediate mode?
90 inca
91 beq L80DD ; brif so
92 tfr y,d ; save offset to D
93 subd TXTTAB ; see how far into the program we are
94 addd CHARAD ; now adjust the input pointer based on that
95 std CHARAD ; save corrected input pointer
96 L80DD rts
97 L80DE fcb 25 ; 25 Extended Basic commands
98 fdb L8183 ; reserved word table (commands)
99 fdb L813C ; interpretation handler (commands)
100 fcb 14 ; 14 Extended Basic functions
101 fdb L821E ; reserved word table (functions)
102 fdb L8168 ; function handler
103 L80E8 fcc 'EXTENDED COLOR BASIC 2.0'
104 fcb 0x0d
105 fcc 'COPR. 1982, 1986 BY TANDY '
106 fcb 0x0d
107 fcc 'UNDER LICENSE FROM MICROSOFT'
108 fcb 0x0d,0x0d,0x00
109 ; Extended Basic command interpretation loop
110 L813C cmpa #0xcb ; is it an Extended Basic command?
111 bhi L8148 ; brif not
112 ldx #L81F0 ; point to dispatch table
113 suba #0xb5 ; normalize the token number so 0 is the first entry
114 jmp LADD4 ; go transfer control to the command
115 L8148 cmpa #0xff ; is it a function token?
116 beq L8154 ; brif so - for MID$()=, TIMER=
117 cmpa #0xcd ; is it a token for a keyword that isn't a command?
118 bls L8165 ; brif so - error for USING and FN
119 L8150 jmp [COMVEC+23] ; transfer control to Disk Basic if it is present
120 L8154 jsr GETNCH ; get token after the function flag
121 cmpa #0x90 ; MID$?
122 lbeq L86D6 ; brif so (substring replacement)
123 cmpa #0x9f ; TIMER?
124 lbeq L8960 ; brif so - TIMER setting
125 jsr RVEC22 ; do a RAM hook in case something wants to extend this
126 L8165 jmp LB277 ; we have nothing valid here
127 ; Function handler
128 L8168 cmpb #2*33 ; is it a valid Extended Basic function?
129 bls L8170 ; brif so
130 L816C jmp [COMVEC+28] ; transfer control to Disk Basic if it is present
131 L8170 subb #2*20 ; normalize Extended Basic functions to 0
132 cmpb #2*8 ; Above HEX$?
133 bhi L817D ; brif so - we don't pre-evaluate an argument
134 pshs b ; save token value
135 jsr LB262 ; evaluate the function parameter
136 puls b ; get back token value
137 L817D ldx #L8257 ; point to dispatch table
138 jmp LB2CE ; go transfer control to the function
139 ; Reserved words (commands)
140 L8183 fcs 'DEL' ; 0xb5
141 fcs 'EDIT' ; 0xb6
142 fcs 'TRON' ; 0xb7
143 fcs 'TROFF' ; 0xb8
144 fcs 'DEF' ; 0xb9
145 fcs 'LET' ; 0xba
146 fcs 'LINE' ; 0xbb
147 fcs 'PCLS' ; 0xbc
148 fcs 'PSET' ; 0xbd
149 fcs 'PRESET' ; 0xbe
150 fcs 'SCREEN' ; 0xbf
151 fcs 'PCLEAR' ; 0xc0
152 fcs 'COLOR' ; 0xc1
153 fcs 'CIRCLE' ; 0xc2
154 fcs 'PAINT' ; 0xc3
155 fcs 'GET' ; 0xc4
156 fcs 'PUT' ; 0xc5
157 fcs 'DRAW' ; 0xc6
158 fcs 'PCOPY' ; 0xc7
159 fcs 'PMODE' ; 0xc8
160 fcs 'PLAY' ; 0xc9
161 fcs 'DLOAD' ; 0xca
162 fcs 'RENUM' ; 0xcb
163 fcs 'FN' ; 0xcc
164 fcs 'USING' ; 0xcd
165 ; Dispatch table (commands)
166 L81F0 fdb DEL ; 0xb5 DEL
167 fdb EDIT ; 0xb6 EDIT
168 fdb TRON ; 0xb7 TRON
169 fdb TROFF ; 0xb8 TROFF
170 fdb DEF ; 0xb9 DEF
171 fdb LET ; 0xba LET (note: implemented by Color Basic!)
172 fdb LINE ; 0xbb LINE
173 fdb PCLS ; 0xbc PCLS
174 fdb PSET ; 0xbd PSET
175 fdb PRESET ; 0xbe PRESET
176 fdb SCREEN ; 0xbf SCREEN
177 fdb PCLEAR ; 0xc0 PCLEAR
178 fdb COLOR ; 0xc1 COLOR
179 fdb CIRCLE ; 0xc2 CIRCLE
180 fdb PAINT ; 0xc3 PAINT
181 fdb GET ; 0xc4 GET
182 fdb PUT ; 0xc5 PUT
183 fdb DRAW ; 0xc6 DRAW
184 fdb PCOPY ; 0xc7 PCOPY
185 fdb PMODETOK ; 0xc8 PMODE
186 fdb PLAY ; 0xc9 PLAY
187 fdb DLOAD ; 0xca DLOAD
188 fdb RENUM ; 0xcb RENUM
189 ; Reserved words (functions)
190 L821E fcs 'ATN' ; 0x94
191 fcs 'COS' ; 0x95
192 fcs 'TAN' ; 0x96
193 fcs 'EXP' ; 0x97
194 fcs 'FIX' ; 0x98
195 fcs 'LOG' ; 0x99
196 fcs 'POS' ; 0x9a
197 fcs 'SQR' ; 0x9b
198 fcs 'HEX$' ; 0x9c
199 fcs 'VARPTR' ; 0x9d
200 fcs 'INSTR' ; 0x9e
201 fcs 'TIMER' ; 0x9f
202 fcs 'PPOINT' ; 0xa0
203 fcs 'STRING$' ; 0xa1
204 ; Dispatch table (functions)
205 L8257 fdb ATN ; 0x94 ATN
206 fdb COS ; 0x95 COS
207 fdb TAN ; 0x96 TAN
208 fdb EXP ; 0x97 EXP
209 fdb FIX ; 0x98 FIX
210 fdb LOG ; 0x99 LOG
211 fdb POS ; 0x9a POS
212 fdb SQR ; 0x9b SQR
213 fdb HEXDOL ; 0x9c HEX$
214 fdb VARPTRTOK ; 0x9d VARPTR
215 fdb INSTR ; 0x9e INSTR
216 fdb TIMER ; 0x9f TIMER
217 fdb PPOINT ; 0xa0 PPOINT
218 fdb STRING ; 0xa1 STRING$
219 ; Generic output handler
220 XVEC3 tst DEVNUM ; screen?
221 lbeq L95AC ; brif so - force text screen active
222 pshs b ; save register
223 ldb DEVNUM ; get output device
224 cmpb #-3 ; check for DLOAD
225 puls b ; restore register
226 bne L8285 ; brif not DLOAD
227 leas 2,s ; bail out of output handler if DLOAD
228 L8285 rts
229 ; Close file handler. This corrects a bug in Color Basic 1.0 which didn't handle writing the
230 ; end of file block correctly. That bug is fixed in Color Basic 1.1 so this isn't required
231 ; if a recent enough version of Color Basic is installed.
232 XVEC8 lda DEVNUM ; get device number
233 inca ; is it tape?
234 bne L8285 ; brif not - we aren't going to mess with it
235 lda FILSTA ; get tape file status
236 cmpa #2 ; output file?
237 bne L8285 ; brif not
238 lda CINCTR ; is there anything waiting to be written out?
239 bne L8285 ; brif so - mainline code will handle it properly
240 clr DEVNUM ; reset output to screen
241 leas 2,s ; don't return to mainline code
242 jmp LA444 ; write EOF block
243 ; RUN handler - sets up some Extended Basic stuff to defaults at program start
244 XVEC18 ldd #0xba42 ; initialize PLAY volume
245 std VOLHI
246 lda #2 ; set PLAY tempo to 2, PLAY octave to 3
247 sta TEMPO
248 sta OCTAVE
249 asla ; set default note length to 5
250 sta NOTELN
251 clr DOTVAL ; don't do any note length extension
252 ldd ZERO ; initialize DRAW angle and scale to default 1
253 std ANGLE
254 ldb #128 ; initialize horizontal and vertical default coordinates to the middle of the screen
255 std HORDEF
256 ldb #96
257 std VERDEF
258 rts
259 ; Command interpretation loop handler; we need to intercept this to implement TRON/TROFF
260 XVEC20 leas 2,s ; don't return to the mainline code
261 L82BB andcc #0xaf ; make sure interrupts are running
262 jsr LADEB ; do a BREAK/pause check
263 ldx CHARAD ; save input pointer
264 stx TINPTR
265 lda ,x+ ; get current input character
266 beq L82CF ; brif end of line
267 cmpa #': ; statement separator?
268 beq L82F1 ; brif so
269 jmp LB277 ; raise error we got here with extra junk
270 L82CF lda ,x++ ; get first byte of next line address
271 sta ENDFLG ; use it to set "END" flag to "END"
272 bne L82D8 ; brif not end of program
273 jmp LAE15 ; go do the "END"
274 L82D8 ldd ,x+ ; get line number of next line (and leave pointer one before line text)
275 std CURLIN ; set current line number
276 stx CHARAD ; save input pointer
277 lda TRCFLG ; are we tracing?
278 beq L82F1 ; brif not
279 lda #'[ ; show opening marker for TRON line number
280 jsr PUTCHR
281 lda CURLIN ; restore MSB of line number
282 jsr LBDCC ; show line number
283 lda #'] ; show closing marker for TRON line number
284 jsr PUTCHR
285 L82F1 jsr GETNCH ; get the start of the statement
286 tfr cc,b ; save status flags
287 cmpa #0x98 ; is it CSAVE?
288 beq L8316 ; brif so - go to Extended Basic patch (adds CSAVEM)
289 cmpa #0x97 ; is it CLOAD?
290 beq L8311 ; brif so - go to Extended Basic patch (adds multi-origin binaries)
291 tfr b,cc ; restore character status
292 jsr LADC6 ; go process command
293 bra L82BB ; restart interpretation loop
294 ; Tokenizaton handler. This is actually a hack to intercept CLOAD and CSAVE during immediate mode by causing the
295 ; tokenization routine to return to the interpretation loop above instead of the mainline interpretation loop. This
296 ; is necessary because the first command encountered on a line in immediate mode is executed BEFORE the interpretation
297 ; loop RAM hook is called. This patch doesn't actually affect tokenization itself at all.
298 XVEC23 ldx 2,s ; get return address of caller to the tokenizer
299 cmpx #LAC9D ; is it coming from immediate mode prior to executing the line?
300 bne L8310 ; brif not
301 ldx #L82F1 ; force return to Extended Basic's main loop patch above
302 stx 2,s
303 L8310 rts
304 ; These two patches are set up this way so that control can be transferred back to the original Color Basic
305 ; implementations if the Extended Basic addons are not triggered.
306 L8311 jsr L8C62 ; transfer control to Extended Basic's CLOAD handler
307 bra L82BB ; go do another command
308 L8316 bsr L831A ; go do Extended Basic's CSAVE handler
309 bra L82BB ; go do another command
310 ; Extended Basic's CSAVE handler which implements CSAVEM (which Color Basic does not have)
311 L831A jsr GETNCH ; get character after CSAVE
312 cmpa #'M ; is it CSAVEM?
313 lbne CSAVE ; brif not - Color Basic can handle this
314 jsr GETNCH ; eat the "M"
315 jsr LA578 ; parse file name
316 bsr L836C ; get start address
317 stx CASBUF+13 ; save it in file header
318 bsr L836C ; get end address
319 cmpx 2,s ; compare to start address
320 lblo LB44A ; brif end address is before the start address
321 bsr L836C ; get execution address
322 stx CASBUF+11 ; put in file header
323 jsr GETCCH ; are we at the end of the commmand?
324 bne L8310 ; brif not
325 lda #2 ; file type to machine language
326 ldx ZERO ; set to binary and single block
327 jsr LA65F ; write header
328 clr FILSTA ; mark any open tape file closed
329 inc BLKTYP ; set block type to data
330 jsr WRLDR ; write a data leader
331 ldx 4,s ; get starting address
332 L834D stx CBUFAD ; set start of data address
333 lda #255 ; try a full length block by default
334 sta BLKLEN
335 ldd 2,s ; get ending address
336 subd CBUFAD ; see how much is left
337 bhs L835E ; brif we have more to write
338 leas 6,s ; clean up stack
339 jmp LA491 ; write EOF block
340 L835E cmpd #255 ; do we have a full block left?
341 bhs L8367 ; brif so
342 incb ; set block size to remainder
343 stb BLKLEN
344 L8367 jsr SNDBLK ; write a data block
345 bra L834D ; go see if we have more to write
346 L836C jsr SYNCOMMA ; make sure we have a comma
347 jsr LB73D ; evaluate unsigned expression to X
348 ldu ,s ; get return address
349 stx ,s ; save result on stack
350 tfr u,pc ; return to caller
351 ; COS function
352 COS ldx #L83AB ; point to PI/2 constant
353 jsr LB9C2 ; add to argument ( cos(x) = sin((pi/2)+x) )
354 L837E jmp SIN ; now calculate sin((pi/2)+x)
355 ; TAN function. This is determined by the identity TAN(X) = SIN(X)/COS(X)
356 TAN jsr LBC2F ; save FPA0 in FPA3
357 clr RELFLG ; reset quadrant flag
358 bsr L837E ; calculate SIN(x)
359 ldx #V4A ; save result in FPA5
360 jsr LBC35
361 ldx #V40 ; get back original argument
362 jsr LBC14
363 clr FP0SGN ; force result positive
364 lda RELFLG ; get quadrant flag
365 bsr L83A6 ; calculate COS(x)
366 tst FP0EXP ; did we get 0 for COS(x)
367 lbeq LBA92 ; brif so - overflow
368 ldx #V4A ; point to sin(x)
369 L83A3 jmp LBB8F ; divide the sin(x) value by the cos(x) value
370 L83A6 pshs a ; save sign flag
371 jmp LBFA6 ; expand polynomial
372 L83AB fcb 0x81,0x49,0x0f,0xda,0xa2 ; pi/2 constant
373 ; ATN function (inverse tangent). There are two calculation streams used to improve precision.
374 ; One if the parameter is >= 1.0 and the other if it is < 1.0
375 ATN lda FP0SGN ; get sign of argument
376 pshs a ; save it
377 bpl L83B8 ; brif positive
378 bsr L83DC ; flip sign of argument
379 L83B8 lda FP0EXP ; get exponent
380 pshs a ; save it
381 cmpa #0x81 ; exponent for 1.0
382 blo L83C5 ; brif less - value is less than 1.0
383 ldx #LBAC5 ; point to FP constant 1.0
384 bsr L83A3 ; calculate reciprocal
385 L83C5 ldx #L83E0 ; point to polynomical coefficients
386 jsr LBEF0 ; expand polynomial
387 puls a ; get exponent of argument
388 cmpa #0x81 ; did we do a reciprocal calculation?
389 blo L83D7 ; brif not
390 ldx #L83AB ; subtract result from pi/2 if we did
391 jsr LB9B9
392 L83D7 puls a ; get sign of original
393 tsta ; was it positive?
394 bpl L83DF ; brif so
395 L83DC jmp LBEE9 ; flip sign of result
396 L83DF rts
397 ; Chebyshev modified taylor series coefficients for inverse tangent. Note that these diverge quite significantly
398 ; 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
399 ; so on. These modified coefficients yield reasonable accuracy for the precision available, presumably with
400 ; fewer coefficients.
401 L83E0 fcb 11 ; 12 coefficients
402 fcb 0x76,0xb3,0x83,0xbd,0xd3 ; -0.000684793912
403 fcb 0x79,0x1e,0xf4,0xa6,0xf5 ; 0.00485094216
404 fcb 0x7b,0x83,0xfc,0xb0,0x10 ; -0.0161117018
405 fcb 0x7c,0x0c,0x1f,0x67,0xca ; 0.0342096381
406 fcb 0x7c,0xde,0x53,0xcb,0xc1 ; -0.0542791328
407 fcb 0x7d,0x14,0x64,0x70,0x4c ; 0.0724571965
408 fcb 0x7d,0xb7,0xea,0x51,0x7a ; -0.0898023954
409 fcb 0x7d,0x63,0x30,0x88,0x7e ; 0.110932413
410 fcb 0x7e,0x92,0x44,0x99,0x3a ; -0.142839808
411 fcb 0x7e,0x4c,0xcc,0x91,0xc7 ; 0.199999121
412 fcb 0x7f,0xaa,0xaa,0xaa,0x13 ; -0.333333316
413 fcb 0x81,0x00,0x00,0x00,0x00 ; 1.0
414 ; Chebyshev modified taylor series coefficients for the ln(x)/ln(2) (base 2 log of x)
415 L841D fcb 3 ; four coefficients
416 fcb 0x7f,0x5e,0x56,0xcb,0x79 ; 0.434255942 from (2/7)/ln(2)
417 fcb 0x80,0x13,0x9b,0x0b,0x64 ; 0.576584541 from (2/5)/ln(2)
418 fcb 0x80,0x76,0x38,0x93,0x16 ; 0.961800759 from (2/3)/ln(2)
419 fcb 0x82,0x38,0xaa,0x3b,0x20 ; 2.88539007 from 2/ln(2)
420 L8432 fcb 0x80,0x35,0x04,0xf3,0x34 ; 1/sqrt(2)
421 L8437 fcb 0x81,0x35,0x04,0xf3,0x34 ; sqrt(2)
422 L843C fcb 0x80,0x80,0x00,0x00,0x00 ; -0.5
423 L8441 fcb 0x80,0x31,0x72,0x17,0xf8 ; ln(2)
424 ; LOG function (natural log, ln)
425 ; FP representation is of the form A*2^B. Thus, the log routine determines the value of
426 ; ln(A*2^B).
427 ;
428 ; ln(A*2^B) = ln(A) + ln(2^B) = ln(A) + B*ln(2) = (ln(A)/ln(2) + B)*ln(2), OR:
429 ; (log2(A) + B)*ln(2)
430 ; Now if we write A as A*(sqrt(2)/sqrt(2)), we haven't changed anything so:
431 ; (log2(A*sqrt(2)/sqrt(2)) + B)*ln(2) = (log2(A*sqrt(2)) - log2(sqrt(2)) + B) * ln(2)
432 ; which gives: (-1/2 + log2(A*sqrt(2)) + B) * ln(2)
433 ;
434 ; Everything except log2(A*sqrt(2)) is either constant or trivial.
435 ;
436 ; What the actual code below feeds into the modified taylor series is actually:
437 ; 1 - (sqrt(2)/(A + sqrt(2)) which algebra reveals to be (A*sqrt(2)-1)/(A*sqrt(2)+1)
438 ;
439 ; Thus, the code is using (A*sqrt(2)-1)/(A*sqrt(2)+1) instead of A*sqrt(2) as one would
440 ; expect from the identities. However, the modified coefficients in the series above
441 ; could be correcting for that or the introduced error was deemed acceptable.
442 ; NOTE: this routine does NOT return 0 for LOG(1)
443 LOG jsr LBC6D ; get status of FPA0
444 lble LB44A ; brif <= 0 - logarithms don't exist in that case
445 ldx #L8432 ; point to 1/sqrt(2)
446 lda FP0EXP ; get exponent of argument
447 suba #0x80 ; remove bias
448 pshs a ; save it for later
449 lda #0x80 ; force exponent to 0 (this turns FPA0 into A in the above description)
450 sta FP0EXP
451 jsr LB9C2 ; add 1/sqrt(2) to A
452 ldx #L8437 ; point to sqrt(2)
453 jsr LBB8F ; divide that by FPA0
454 ldx #LBAC5 ; point to 1.0
455 jsr LB9B9 ; subtract result from 1.0: Now FPA0 is 1-(sqrt(2)/(A+1/sqrt(2)))
456 ldx #L841D ; point to coefficients
457 jsr LBEF0 ; expand polynomial (calculate base 2 log of modified argument)
458 ldx #L843C ; point to -0.5
459 jsr LB9C2 ; add result
460 puls b ; get original exponent back
461 jsr LBD99 ; add B to FPA0
462 ldx #L8441 ; point to ln(2)
463 jmp LBACA ; multiply by ln(2) which gives us the result in base e
464 ; SQR function (square root) - returns the principle root (positive)
465 SQR jsr LBC5F ; move argument to FPA1 (first argument for exponentiation)
466 ldx #LBEC0 ; point to 0.5 (exponent for square root)
467 jsr LBC14 ; set up second argument to exponentiation (the exponent)
468 ; Exponentiation operator
469 ; This is calculated as A^x = e^(x*ln(A)) where A is in FPA1 and x is in FPA0
470 L8489 beq EXP ; do "EXP" if exponent is 0 (this will catch 0^0)
471 tsta ; check that the base is not 0
472 bne L8491 ; brif base is not 0
473 jmp LBA3A ; 0^(nonzero) is 0
474 L8491 ldx #V4A ; save exponent (to FPA5)
475 jsr LBC35
476 clrb ; result sign will default to positive
477 lda FP1SGN ; check if base is positive
478 bpl L84AC ; brif so
479 jsr INT ; convert exponent to integer
480 ldx #V4A ; point to original expoent
481 lda FP1SGN ; get sign of FPA1
482 jsr LBCA0 ; compare original exponent with truncated one
483 bne L84AC ; brif not equal
484 coma ; flip sign
485 ldb CHARAC ; get LS byte of integer exponent (result sign flag)
486 L84AC jsr LBC4C ; copy FPA1 (base) to FPA0 (A = sign)
487 pshs b ; save result sign
488 jsr LOG ; get natural log of the base
489 ldx #V4A ; multiply the log by the exponent
490 jsr LBACA
491 bsr EXP ; now raise e to the resulting power
492 puls a ; get result sign
493 rora ; brif it was negative
494 lbcs LBEE9 ; brif negative - flip sign
495 rts
496 L84C4 fcb 0x81,0x38,0xaa,0x3b,0x29 ; 1.44269504 (correction factor for exponential function)
497 ; Chebyshev modified taylor series coefficients for e^x
498 L84C9 fcb 7 ; eight coefficients
499 fcb 0x71,0x34,0x58,0x3e,0x56 ; 1/(7!*(CF^7))
500 fcb 0x74,0x16,0x7e,0xb3,0x1b ; 1/(6!*(CF^6))
501 fcb 0x77,0x2f,0xee,0xe3,0x85 ; 1/(5!*(CF^5))
502 fcb 0x7a,0x1d,0x84,0x1c,0x2a ; 1/(4!*(CF^4))
503 fcb 0x7c,0x63,0x59,0x58,0x0a ; 1/(3!*(CF^3))
504 fcb 0x7e,0x75,0xfd,0xe7,0xc6 ; 1/(2!*(CF^2))
505 fcb 0x80,0x31,0x72,0x18,0x10 ; 1/(1!*(CF^1))
506 fcb 0x81,0x00,0x00,0x00,0x00 ; 1
507 ; EXP function (e^x)
508 EXP ldx #L84C4 ; point to correction factor
509 jsr LBACA ; multiply it
510 jsr LBC2F ; save corrected argument to FPA3
511 lda FP0EXP ; get exponent of FPA0
512 cmpa #0x88 ; is it too big?
513 blo L8504 ; brif not
514 L8501 jmp LBB5C ; to 0 (underflow) or overflow error
515 L8504 jsr INT ; convert argument to an integer
516 lda CHARAC ; get ls byte of integer
517 adda #0x81 ; was argument 127? if so, the OV error; adds bias
518 beq L8501
519 deca ; adjust for the extra +1 above
520 pshs a ; save integer exponent
521 ldx #V40 ; get fractional part of argument
522 jsr LB9B9
523 ldx #L84C9 ; point to coefficients
524 jsr LBEFF ; evaluate polynomial on the fractional part
525 clr RESSGN ; force result to be positive
526 puls a ; get back original exponent
527 jsr LBB48 ; add original exponent to the fractional result
528 rts
529 ; FIX function (truncate/round toward 0) (NOTE: INT() always rounds down so INT(-0.5) gives -1 but FIX(-0.5) gives 0)
530 FIX jsr LBC6D ; get status of argument
531 bmi L852C ; brif negative
532 L8529 jmp INT ; do regular "int" if positive
533 L852C com FP0SGN ; flip the sign
534 bsr L8529 ; do "INT" on this
535 jmp LBEE9 ; flip the sign back
536 ; EDIT command
537 EDIT jsr L89AE ; get line number
538 leas 2,s ; we're not going to return to the main loop
539 L8538 lda #1 ; "LIST" flag
540 sta VD8 ; set to list the line
541 jsr LAD01 ; find line number
542 lbcs LAED2 ; brif line wasn't found
543 jsr LB7C2 ; go unpack the line into the buffer
544 tfr y,d ; calculate the actual length of the line
545 subd #LINBUF+2
546 stb VD7 ; save line length (it will only be 8 bits)
547 L854D ldd BINVAL ; get the line number
548 jsr LBDCC ; display it
549 jsr LB9AC ; put a space after it
550 ldx #LINBUF+1 ; point to iput uffer
551 ldb VD8 ; are we listing?
552 bne L8581 ; brif so
553 L855C clrb ; reset digit accumulator
554 L855D jsr L8687 ; get a keypress
555 jsr L90AA ; set carry if not numeric
556 bcs L8570 ; brif not a number
557 suba #'0 ; remove ASCII bias
558 pshs a ; save digit value
559 lda #10 ; multiply accumulator by 10
560 mul
561 addb ,s+ ; add in new digit
562 bra L855D ; go check for another digit
563 L8570 subb #1 ; this converts 0 to 1, but *only* 0 to 1
564 adcb #1
565 cmpa #'A ; abort?
566 bne L857D ; brif not
567 jsr LB958 ; to a CR
568 bra L8538 ; restart EDIT process
569 L857D cmpa #'L ; list?
570 bne L858C ; brif not
571 L8581 bsr L85B4 ; list the line
572 clr VD8 ; reset to "not listing"
573 jsr LB958 ; do a CR
574 bra L854D ; start editing
575 L858A leas 2,s ; lose return address
576 L858C cmpa #0x0d ; ENTER?
577 bne L859D ; brif not
578 bsr L85B4 ; echo out the line
579 L8592 jsr LB958 ; do a CR
580 ldx #LINBUF+1 ; reset input pointer to start of buffer
581 stx CHARAD
582 jmp LACA8 ; join immediate mode to replace the line in the program
583 L859D cmpa #'E ; exit?
584 beq L8592 ; brif so - end edit with no echo
585 cmpa #'Q ; quit?
586 bne L85AB ; brif not
587 jsr LB958 ; do a CR
588 jmp LAC73 ; go to immediate mode with no fanfare - no changes saved
589 L85AB bsr L85AF ; go do commands
590 bra L855C ; go handle another command
591 L85AF cmpa #0x20 ; space?
592 bne L85C3 ; brif not
593 skip2
594 L85B4 ldb #LBUFMX-1 ; display up to a whole line
595 L85B6 lda ,x ; get buffer chracter
596 beq L85C2 ; brif end of line
597 jsr PUTCHR ; output character
598 leax 1,x ; move to next character
599 decb ; done?
600 bne L85B6 ; brif not
601 L85C2 rts
602 L85C3 cmpa #'D ; delete?
603 bne L860F ; brif not
604 L85C7 tst ,x ; end of line?
605 beq L85C2 ; brif so - can't delete
606 bsr L85D1 ; remove a character
607 decb ; done all requested?
608 bne L85C7 ; brif not
609 rts
610 L85D1 dec VD7 ; account for character being removed
611 leay -1,x ; set pointer and compensate for increment below
612 L85D5 leay 1,y ; move to next character
613 lda 1,y ; get next character
614 sta ,y ; move it forward
615 bne L85D5 ; brif we didn't hit the end of the buffer
616 rts
617 L85DE cmpa #'I ; insert?
618 beq L85F5 ; brif so
619 cmpa #'X ; extend?
620 beq L85F3 ; brif so
621 cmpa #'H ; "hack"?
622 bne L8646 ; brif not
623 clr ,x ; mark current location as end of line
624 tfr x,d ; calculate new line length
625 subd #LINBUF+2
626 stb VD7 ; save new length
627 L85F3 bsr L85B4 ; display the line
628 L85F5 jsr L8687 ; read a character
629 cmpa #0x0d ; ENTER?
630 beq L858A ; brif so - terminate entry
631 cmpa #0x1b ; ESC?
632 beq L8625 ; brif so - back to command mode
633 cmpa #0x08 ; backspace?
634 bne L8626 ; brif no
635 cmpx #LINBUF+1 ; are we at the start of the buffer?
636 beq L85F5 ; brif so - it's a no-op
637 bsr L8650 ; move pointer back one, do a BS
638 bsr L85D1 ; remove character from the buffer
639 bra L85F5 ; go handle more input
640 L860F cmpa #'C ; change?
641 bne L85DE ; brif not
642 L8613 tst ,x ; is there something to change?
643 beq L8625 ; brif not
644 jsr L8687 ; get a key stroke
645 bcs L861E ; brif valid key
646 bra L8613 ; try again if invalid key
647 L861E sta ,x+ ; put new character in the buffer
648 bsr L8659 ; echo it
649 decb ; changed number requested?
650 bne L8613 ; brif not
651 L8625 rts
652 L8626 ldb VD7 ; get length of line
653 cmpb #LBUFMX-1 ; at maximum line length?
654 bne L862E ; brif not
655 bra L85F5 ; process another input character
656 L862E pshs x ; save input pointer
657 L8630 tst ,x+ ; are we at the end of the line?
658 bne L8630 ; brif not
659 L8634 ldb ,-x ; get character before current pointer, move back
660 stb 1,x ; move it forward
661 cmpx ,s ; at the original buffer pointer?
662 bne L8634 ; brif not
663 leas 2,s ; remove saved buffer pointer
664 sta ,x+ ; save input character in newly made hole
665 bsr L8659 ; echo it
666 inc VD7 ; bump line length counter
667 bra L85F5 ; go handle more stuff
668 L8646 cmpa #0x08 ; backspace?
669 bne L865C ; brif not
670 L864A bsr L8650 ; move pointer back, echo BS
671 decb ; done enough of them?
672 bne L864A ; brif not
673 rts
674 L8650 cmpx #LINBUF+1 ; at start of buffer?
675 beq L8625 ; brif so
676 leax -1,x ; move pointer back
677 lda #0x08 ; character to echo - BS
678 L8659 jmp PUTCHR ; echo character to screen
679 L865C cmpa #'K ; "kill"?
680 beq L8665 ; brif so
681 suba #'S ; search?
682 beq L8665 ; brif so
683 rts
684 L8665 pshs a ; save kill/search flag
685 bsr L8687 ; read target
686 pshs a ; save search character
687 L866B lda ,x ; get current character in buffer
688 beq L8685 ; brif end of line - nothing more to search
689 tst 1,s ; is it KILL?
690 bne L8679 ; brif so
691 bsr L8659 ; echo the character
692 leax 1,x ; move ahead
693 bra L867C ; check next character
694 L8679 jsr L85D1 ; remove character from buffer
695 L867C lda ,x ; get character in buffer
696 cmpa ,s ; are we at the target?
697 bne L866B ; brif not
698 decb ; have we found enough of them?
699 bne L866B ; brif not
700 L8685 puls y,pc ; clean up stack and return to main EDIT routine
701 L8687 jsr LA171 ; get input from the generic input handler (will show the cursor)
702 cmpa #0x7f ; graphics (or DEL)?
703 bhs L8687 ; brif so - ignore it
704 cmpa #0x5f ; SHIFT-UP?
705 bne L8694 ; brif not
706 lda #0x1b ; replace with ESC
707 L8694 cmpa #0x0d ; carriage return?
708 beq L86A6 ; brif so (C=0)
709 cmpa #0x1b ; ESC
710 beq L86A6 ; brif so (C=0)
711 cmpa #0x08 ; backspace?
712 beq L86A6 ; brif so (C=0)
713 cmpa #32 ; control code?
714 blo L8687 ; brif control code - try again
715 orcc #1 ; set C for "valid" (printable) character
716 L86A6 rts
717 ; TRON and TROFF commands
718 TRON skip1lda ; load flag with nonzero for trace enabled (and skip next)
719 TROFF clra ; clear flag for trace disabled
720 sta TRCFLG ; save trace status
721 rts
722 ; POS function
723 POS lda DEVNUM ; get original device number
724 pshs a ; save it for later
725 jsr LA5AE ; fetch device number
726 jsr LA406 ; check for open file
727 jsr LA35F ; set up print parameters
728 ldb DEVPOS ; get current line position for the device
729 jmp LA5E4 ; return position in B as unsigned
730 ; VARPTR function
731 VARPTRTOK jsr LB26A ; make sure we have (
732 ldd ARYEND ; get address of end of arrays
733 pshs d ; save it
734 jsr LB357 ; parse variable descriptor
735 jsr LB267 ; make sure there is a )
736 puls d ; get original end of arrays
737 exg x,d ; swap original end of arrays and the discovered variable pointer
738 cmpx ARYEND ; did array end move (variable created?)
739 bne L8724 ; brif so (FC error)
740 jmp GIVABF ; return the pointer (NOTE: as signed)
741 ; MID$() assignment; note that this cannot make the string longer or shorter and if the replacement is shorter
742 ; than the specified size, only the number of characters actually in the replacement will be used.
743 L86D6 jsr GETNCH ; eat the MID$ token
744 jsr LB26A ; force (
745 jsr LB357 ; evaluate the variable
746 pshs x ; save variable descriptor
747 ldd 2,x ; point to start of original string
748 cmpd FRETOP ; is it in string space?
749 bls L86EB ; brif not
750 subd MEMSIZ ; is it still in string space (top end)?
751 bls L86FD ; brif so
752 L86EB ldb ,x ; get length of original string
753 jsr LB56D ; allocate space in string space
754 pshs x ; save pointer to string space
755 ldx 2,s ; get to original string descriptor
756 jsr LB643 ; move the string into string space
757 puls x,u ; get new string address and string descriptor
758 stx 2,u ; save new data address for the string
759 pshs u ; save descriptor address again
760 L86FD jsr LB738 ; evaluate ",start"
761 pshs b ; save start offset
762 tstb ; is start 0?
763 beq L8724 ; brif so - strings offsets are 1-based
764 ldb #255 ; default use the entire string
765 cmpa #') ; end of parameters?
766 beq L870E ; brif so
767 jsr LB738 ; evaluate ",length"
768 L870E pshs b ; save length
769 jsr LB267 ; make sure we have a )
770 ldb #0xb3 ; make sure we have =
771 jsr LB26F
772 bsr L8748 ; evaluate replacement string
773 tfr x,u ; save replacement string address
774 ldx 2,s ; get original string descriptor
775 lda ,x ; get length of original string
776 suba 1,s ; subtract start position
777 bhs L8727 ; brif within the string - insert replacement
778 L8724 jmp LB44A ; raise illegal function call
779 L8727 inca ; A is now number of characters to the right of the position parameter
780 cmpa ,s ; compare to length desired
781 bhs L872E ; brif new length fits
782 sta ,s ; only use as much of the length as will fit
783 L872E lda 1,s ; get position offset
784 exg a,b ; swap replacement length and position
785 ldx 2,x ; point to original string address
786 decb ; we work with 0-based offsets
787 abx ; now X points to start of replacement
788 tsta ; replacing 0?
789 beq L8746 ; brif so - done
790 cmpa ,s ; is replacement shorter than the hole?
791 bls L873F ; brif so
792 lda ,s ; use copy the maximum number specified
793 L873F tfr a,b ; save number to move in B
794 exg u,x ; swap pointers so they are right for the routine
795 jsr LA59A ; copy string data
796 L8746 puls a,b,x,pc ; clean up stack and return
797 L8748 jsr LB156 ; evaluate expression
798 jmp LB654 ; make sure it's a string and return string details
799 ; STRING$ function
800 STRING jsr LB26A ; make sure we have (
801 jsr EVALEXPB ; evaluate repeat count (error if > 255)
802 pshs b ; save repeat count
803 jsr SYNCOMMA ; make sure there's a comma
804 jsr LB156 ; evaluate the thing to repeat
805 jsr LB267 ; make sure we have a )
806 lda VALTYP ; is it string?
807 bne L8768 ; brif so
808 jsr LB70E ; get 8 bit character code
809 bra L876B ; use that
810 L8768 jsr LB6A4 ; get first character of string
811 L876B pshs b ; save repeat character
812 ldb 1,s ; get repeat count
813 jsr LB50F ; reserve space for the string
814 puls a,b ; get character and repeat count
815 beq L877B ; brif NULL string
816 L8776 sta ,x+ ; put character into string
817 decb ; put enough?
818 bne L8776 ; brif not
819 L877B jmp LB69B ; return the newly created string
820 ; INSTR function
821 INSTR jsr LB26A ; evaluate (
822 jsr LB156 ; evaluate first argument
823 ldb #1 ; default start position is 1 (start of string)
824 pshs b ; save start position
825 lda VALTYP ; get type of first argument
826 bne L879C ; brif string - use default starting position
827 jsr LB70E ; convert first argument into string offset
828 stb ,s ; save offset
829 beq L8724 ; brif starting at 0 - not allowed
830 jsr SYNCOMMA ; make sure there's a comma
831 jsr LB156 ; evaluate the search string
832 jsr LB146 ; make sure it *is* a string
833 L879C ldx FPA0+2 ; get search string descriptor
834 pshs x ; save it
835 jsr SYNCOMMA ; make sure we have a comma
836 jsr L8748 ; evalute the target string
837 pshs x,b ; save address and length of target string
838 jsr LB267 ; make sure we have a )
839 ldx 3,s ; get search string address
840 jsr LB659 ; get string details
841 pshs b ; save search string length
842 cmpb 6,s ; compare length of search string to the start
843 blo L87D9 ; brif start position is beyond the search string - return 0
844 lda 1,s ; get length of target string
845 beq L87D6 ; brif targetstring is NULL - match will be immediate
846 ldb 6,s ; get start position
847 decb ; zero-base it
848 abx ; now X points to the start position for the search
849 L87BE leay ,x ; point to start of search
850 ldu 2,s ; get target string pointer
851 ldb 1,s ; get targetlength
852 lda ,s ; get length of serach
853 suba 6,s ; see how much is left in searh
854 inca ; add one for "inclusivity"
855 cmpa 1,s ; do we have less than the target string?
856 blo L87D9 ; brif so - we obviously won't match
857 L87CD lda ,x+ ; compare a byte
858 cmpa ,u+
859 bne L87DF ; brif no match
860 decb ; compared all of target?
861 bne L87CD ; brif not
862 L87D6 ldb 6,s ; get position where we matched
863 skip1
864 L87D9 clrb ; flag no match
865 leas 7,s ; clean up stack
866 jmp LB4F3 ; return unsigned B
867 L87DF inc 6,s ; bump start position
868 leax 1,y ; move starting pointer
869 bra L87BE ; see if we match now
870 ; Number parsing handler
871 XVEC19 cmpa #'& ; do we have & (hex or octal)?
872 L87E7 bne L8845 ; brif not
873 leas 2,s ; we won't return to the original invoker
874 L87EB clr FPA0+2 ; clear bottom of FPA0 for 16 bit value
875 clr FPA0+3
876 ldx #FPA0+2 ; point to accumulator
877 jsr GETNCH ; eat the &
878 cmpa #'O ; octal?
879 beq L880A ; brif so
880 cmpa #'H ; hex?
881 beq L881F ; brif so
882 jsr GETCCH ; reset flags on input
883 bra L880C ; go process octal (default)
884 L8800 cmpa #'8 ; is it a valid octal character?
885 lbhi LB277 ; brif not (BUG: should be LBHS or above be #'7)
886 ldb #3 ; base 8 multiplier
887 bsr L8834 ; add digit to accumulator
888 L880A jsr GETNCH ; get input character
889 L880C bcs L8800 ; brif numeric
890 L880E clr FPA0 ; clear upper bytes of FPA0
891 clr FPA0+1
892 clr VALTYP ; result is numeric
893 clr FPSBYT ; clear out any extra precision
894 clr FP0SGN ; make it positive
895 ldb #0xa0 ; exponent for integer aligned to right of FPA0
896 stb FP0EXP
897 jmp LBA1C ; go normalize the result and return
898 L881F jsr GETNCH ; get input character
899 bcs L882E ; brif digit
900 jsr LB3A2 ; set carry if not alpha
901 L8826 bcs L880E ; brif not alpha
902 cmpa #'G ; is it valid HEX digit?
903 bhs L880E ; brif not
904 suba #7 ; normalize A-F to be just above 0-9
905 L882E ldb #4 ; four bits per digit
906 bsr L8834 ; add digit to accumlator
907 bra L881F ; process another digit
908 L8834 asl 1,x ; shift accumulator one bit left
909 rol ,x
910 lbcs LBA92 ; brif too big - overflow
911 decb ; done enough bit shifts?
912 bne L8834 ; brif not
913 L883F suba #'0 ; remove ASCII bias
914 adda 1,x ; merge digit into accumlator (this cannot cause carry)
915 sta 1,x
916 L8845 rts
917 ; Expression evaluation handler
918 XVEC15 puls u ; get back return address
919 clr VALTYP ; set result to numeric
920 ldx CHARAD ; save input pointer
921 jsr GETNCH ; get the input character
922 cmpa #'& ; HEX or OCTAL?
923 beq L87EB ; brif so
924 cmpa #0xcc ; FN?
925 beq L88B4 ; brif so - do "FNx()"
926 cmpa #0xff ; function token?
927 bne L8862 ; brif not
928 jsr GETNCH ; get function token value
929 cmpa #0x83 ; USR?
930 lbeq L892C ; brif so - short circuit Color Basic's USR handler
931 L8862 stx CHARAD ; restore input pointer
932 jmp ,u ; return to mainline code
933 L8866 ldx CURLIN ; are we in immediate mode?
934 leax 1,x
935 L886A bne L8845 ; brif not - we're good
936 ldb #2*11 ; code for illegal direct statement
937 L886E jmp LAC46 ; raise error
938 ; DEF command (DEF FN, DEF USR)
939 DEF ldx [CHARAD] ; get two input characters
940 cmpx #0xff83 ; USR?
941 lbeq L890F ; brif so - do DEF USR
942 bsr L88A1 ; get descriptor address for FN variable
943 bsr L8866 ; disallow DEF FN in immediate mode
944 jsr LB26A ; make sure we have (
945 ldb #0x80 ; disallow arrays as arguments
946 stb ARYDIS
947 jsr LB357 ; evaluate variable
948 bsr L88B1 ; make sure it's numeric
949 jsr LB267 ; make sure we have )
950 ldb #0xb3 ; make sure we have =
951 jsr LB26F
952 ldx V4B ; get variable descriptor address
953 ldd CHARAD ; get input pointer
954 std ,x ; save address of the actual function code in variable descriptor
955 ldd VARPTR ; get descriptor address of argument
956 std 2,x ; save argument descriptor address
957 jmp DATA ; move to the end of this statement
958 L88A1 ldb #0xcc ; make sure we have FN
959 jsr LB26F
960 ldb #0x80 ; disable array lookup
961 stb ARYDIS
962 ora #0x80 ; set bit 7 of first character (to indicate FN variable)
963 jsr LB35C ; find the variable
964 stx V4B ; save descriptor pointer
965 L88B1 jmp LB143 ; make sure we have a numeric variable
966 ; Evaluate an FN call
967 L88B4 bsr L88A1 ; parse the FNx bit and get the descriptor
968 pshs x ; save descriptor
969 jsr LB262 ; evaluate parameter
970 bsr L88B1 ; make sure it's a number
971 puls u ; get FN descriptor
972 ldb #2*25 ; code for undefined function
973 ldx 2,u ; point to argument variable descriptor
974 beq L886E ; brif nothing doing there (if it was just created, this will be NULL)
975 ldy CHARAD ; save current input pointer
976 ldu ,u ; point to start of FN definition
977 stu CHARAD ; put input pointer there
978 lda 4,x ; save original value of argument and save it with current input, and variable pointers
979 pshs a
980 ldd ,x
981 ldu 2,x
982 pshs u,y,x,d
983 jsr LBC35 ; set argument variable to the argument
984 L88D9 jsr LB141 ; go evaluate the FN expression
985 puls d,x,y,u ; get back variable pointers, input pointer, and original variable value
986 std ,x
987 stu 2,x
988 puls a
989 sta 4,x
990 jsr GETCCH ; test end of FN formula
991 lbne LB277 ; brif not end of statement - problem with the function
992 sty CHARAD ; restore input pointer
993 L88EF rts
994 ; Error handler
995 XVEC17 cmpb #2*25 ; is it a valid Extended Basic error code?
996 blo L88EF ; brif not - return to mainline
997 jsr LA7E9 ; turn off tape
998 jsr LA974 ; turn off sound
999 jsr LAD33 ; clean up stack and other bits
1000 clr DEVNUM ; reset output to screen
1001 jsr LB95C ; do a newline if needed
1002 jsr LB9AF ; do a ?
1003 ldx #L890B-25*2 ; point to error message table
1004 jmp LAC60 ; go display error message
1005 ; Extended Basic error codes. Yes, NE is defined here even though it is only actually documented in the
1006 ; Disk Basic documentation. It is here for the use of DLOAD.
1007 L890B fcc 'UF' ; 25 undefined function call
1008 fcc 'NE' ; 26 File not found
1009 ; DEF USR
1010 L890F jsr GETNCH ; eat the USR token
1011 bsr L891C ; get pointer to USR call
1012 pshs x ; save FN exec address location
1013 bsr L8944 ; calculate execution address
1014 puls u ; get FN address pointer
1015 stx ,u ; save new address
1016 rts
1017 L891C clrb ; default routine number is 0
1018 jsr GETNCH ; fetch the call number
1019 bcc L8927 ; brif not a number
1020 suba #'0 ; remove ASCII bias
1021 tfr a,b ; save it in the right place
1022 jsr GETNCH ; eat the call number
1023 L8927 ldx USRADR ; get start address of USR jump table
1024 aslb ; two bytes per address
1025 abx ; now X points to the right entry
1026 rts
1027 ; Evaluate a USR call
1028 L892C bsr L891C ; find the correct routine address location
1029 ldx ,x ; get routine address
1030 pshs x ; save it
1031 jsr LB262 ; evaluate argument
1032 ldx #FP0EXP ; point to FPA0 (argument value)
1033 lda VALTYP ; is it string?
1034 beq L8943 ; brif not
1035 jsr LB657 ; fetch string details (removes it from the string stack)
1036 ldx FPA0+2 ; get string descriptor pointer
1037 lda VALTYP ; set flags for the value type
1038 L8943 rts ; call the routine and return to mainline code
1039 L8944 ldb #0xb3 ; check for "="
1040 jsr LB26F
1041 jmp LB73D ; evaluate integer expression to X and return
1042 ; Extended Basic IRQ handler
1043 XIRQSV lda PIA0+3 ; is it VSYNC interrupt?
1044 bmi L8952 ; brif so
1045 rti ; really should clear the HSYNC interrupt here
1046 L8952 lda PIA0+2 ; clear VSYNC interrupt
1047 ldx TIMVAL ; increment the TIMER value
1048 leax 1,x
1049 stx TIMVAL
1050 jmp L9C3E ; check for other stuff
1051 ; TIMER=
1052 L8960 jsr GETNCH ; eat the TIMER token
1053 bsr L8944 ; evaluate =nnnn to X
1054 stx TIMVAL ; set the timer
1055 rts
1056 ; TIMER function
1057 TIMER ldx TIMVAL ; get timer value
1058 stx FPA0+2 ; set it in FPA0
1059 jmp L880E ; return as positive 16 bit value
1060 ; DEL command
1061 DEL lbeq LB44A ; raise error if no argument (probably to avoid accidentally deleting line 0)
1062 jsr LAF67 ; parse line number
1063 jsr LAD01 ; find line
1064 stx VD3 ; save address of line
1065 jsr GETCCH ; is there something more?
1066 beq L8990 ; brif not
1067 cmpa #0xac ; dash?
1068 bne L89BF ; brif not - error out
1069 jsr GETNCH ; each the -
1070 beq L898C ; brif no ending line - use default line number
1071 bsr L89AE ; parse second line number and save in BINVAL
1072 bra L8990 ; do the deletion
1073 L898C lda #0xff ; set to maximum line number
1074 sta BINVAL
1075 L8990 ldu VD3 ; point end to start
1076 skip2
1077 L8993 ldu ,u ; point to start of next line
1078 ldd ,u ; check for end of program
1079 beq L899F ; brif end of program
1080 ldd 2,u ; get line number
1081 subd BINVAL ; is it in range?
1082 bls L8993 ; brif so
1083 L899F ldx VD3 ; get starting line address
1084 bsr L89B8 ; close up gap
1085 jsr LAD21 ; reset input pointer and erase variables
1086 ldx VD3 ; get start of program after the deletion
1087 jsr LACF1 ; recompute netl ine pointers
1088 jmp LAC73 ; return to immediate mode
1089 L89AE jsr LAF67 ; parse a line number
1090 jmp LA5C7 ; make sure there's nothing more
1091 L89B4 lda ,u+ ; copy a byte
1092 sta ,x+
1093 L89B8 cmpu VARTAB ; end of program?
1094 bne L89B4 ; brif not
1095 stx VARTAB ; save new start of variables/end of program
1096 L89BF rts
1097 ; LINE INPUT
1098 L89C0 jsr L8866 ; raise error if in immediate mode
1099 jsr GETNCH ; eat the "INPUT" token
1100 cmpa #'# ; device number?
1101 bne L89D2 ; brif not
1102 jsr LA5A5 ; parse device number
1103 jsr LA3ED ; make sure it's valid for input
1104 jsr SYNCOMMA ; make sure there's a comma after the device number
1105 L89D2 cmpa #'" ; is there a prompt?
1106 bne L89E1 ; brif not
1107 jsr LB244 ; parse the string
1108 ldb #'; ; make sure there's a semicolon after the prompt
1109 jsr LB26F
1110 jsr LB99F ; go actually display the prompt
1111 L89E1 leas -2,s ; make a hole on the stack (so number of return adddresses is right)
1112 jsr LB035 ; read an input line from current device
1113 leas 2,s ; clean up stack
1114 clr DEVNUM ; reset to screen/keyboard
1115 jsr LB357 ; parse a variable
1116 stx VARDES ; save pointer to it
1117 jsr LB146 ; make sure it's a string
1118 ldx #LINBUF ; point to input buffer
1119 clra ; make sure we terminate on NUL only
1120 jsr LB51A ; parse string and store it in string space
1121 jmp LAFA4 ; go assign the string to its final resting place
1122 ; RENUM command
1123 L89FC jsr LAF67 ; read a line number
1124 ldx BINVAL ; get value
1125 rts
1126 L8A02 ldx VD1 ; get current old number being renumbered
1127 L8A04 stx BINVAL ; save number being searched for
1128 jmp LAD01 ; go find line number
1129 RENUM jsr LAD26 ; erase variables
1130 ldd #10 ; default line number interval and start
1131 std VD5 ; set starting line number
1132 std VCF ; set number interval
1133 clrb ; now D is 0
1134 std VD1 ; save default start for renumbering
1135 jsr GETCCH ; are there any arguments
1136 bcc L8A20 ; brif not numeric
1137 bsr L89FC ; fetch line number
1138 stx VD5 ; save line beginning number
1139 jsr GETCCH ; get input character
1140 L8A20 beq L8A3D ; brif end of line
1141 jsr SYNCOMMA ; make sure we have a comma
1142 bcc L8A2D ; brif next isn't numeric
1143 bsr L89FC ; fetch starting line number
1144 stx VD1 ; save the number where we start working
1145 jsr GETCCH ; fetch input character
1146 L8A2D beq L8A3D ; brif end of line
1147 jsr SYNCOMMA ; make sure we have a comma
1148 bcc L8A3A ; brif we don't have a number
1149 bsr L89FC ; parse the number
1150 stx VCF ; save interval
1151 beq L8A83 ; brif we ave a zero interval
1152 L8A3A jsr LA5C7 ; raise error if more stuff
1153 L8A3D bsr L8A02 ; get address of old number to process
1154 stx VD3 ; save address
1155 ldx VD5 ; get the next renumbered line to use
1156 bsr L8A04 ; find that line
1157 cmpx VD3 ; is it before the previous one?
1158 blo L8A83 ; brif so - raise error
1159 bsr L8A67 ; make sure renumbered line numbers will be in range
1160 jsr L8ADD ; convert line numbers to "expanded" binary
1161 jsr LACEF ; recalculate next line pointers
1162 bsr L8A02 ; get address of first line to renumber
1163 stx VD3 ; save it
1164 bsr L8A91 ; make sure line numbers exist
1165 bsr L8A68 ; renumber the actual lines
1166 bsr L8A91 ; update line numbers in program text
1167 jsr L8B7B ; convert packed binary line numbers to text
1168 jsr LAD26 ; erase variables, reset stack, etc.
1169 jsr LACEF ; recalculate next line pointers
1170 jmp LAC73 ; bounce back to immediate mode
1171 L8A67 skip1lda ; set line number flag to nonzero (skip next instruction)
1172 L8A68 clra ; set line number flag to zero (insert new numbers)
1173 sta VD8 ; save line number flag
1174 ldx VD3 ; get address of line being renumbered
1175 ldd VD5 ; get the current renumbering number
1176 bsr L8A86 ; return if end of program
1177 L8A71 tst VD8 ; test line number flag
1178 bne L8A77 ; brif not adding new numbers
1179 std 2,x ; set new number
1180 L8A77 ldx ,x ; point to next line
1181 bsr L8A86 ; return if end of program
1182 addd VCF ; add interval to current number
1183 bcs L8A83 ; brif we overflowed - bad line number
1184 cmpa #MAXLIN ; maximum legal number?
1185 blo L8A71 ; brif so - do another
1186 L8A83 jmp LB44A ; raise FC error
1187 L8A86 pshs d ; save D (we're going to clobber it)
1188 ldd ,x ; get next line pointer
1189 puls d ; unclobber D
1190 bne L8A90 ; brif not end of program
1191 leas 2,s ; return to caller's caller
1192 L8A90 rts
1193 L8A91 ldx TXTTAB ; get start of program
1194 leax -1,x ; move pointer back one (compensate for leax 1,x below)
1195 L8A95 leax 1,x ; move to next line
1196 bsr L8A86 ; return if end of program
1197 L8A99 leax 3,x ; move past next line address and line number, go one before line
1198 L8A9B leax 1,x ; move to next character
1199 lda ,x ; check input character
1200 beq L8A95 ; brif end of line
1201 stx TEMPTR ; save current pointer
1202 deca ; is it start of packed numeric line number?
1203 beq L8AB2 ; brif so
1204 deca ; does line exist?
1205 beq L8AD3 ; brif line number exists
1206 deca ; not part of something to process?
1207 bne L8A9B ; brif so
1208 L8AAC lda #3 ; set 1st byte to 3 to indicate line number not existing
1209 sta ,x+
1210 bra L8A99 ; go process another
1211 L8AB2 ldd 1,x ; get MSB of line number
1212 dec 2,x ; is MS byte zero?
1213 beq L8AB9 ; brif not
1214 clra ; set MS byte to 0
1215 L8AB9 ldb 3,x ; get LSB of line number
1216 dec 4,x ; is it zero?
1217 beq L8AC0 ; brif not
1218 clrb ; clear byte
1219 L8AC0 std 1,x ; save binary number
1220 std BINVAL ; save trial number
1221 jsr LAD01 ; find the line number
1222 L8AC7 ldx TEMPTR ; get start of packed line
1223 bcs L8AAC ; brif line number not found
1224 ldd V47 ; get address of line number
1225 inc ,x+ ; bump first byte to 2 (exists if checking) or 1 if inserting
1226 std ,x ; save address of correct number
1227 bra L8A99 ; go process more
1228 L8AD3 clr ,x ; clear carry and first byte
1229 ldx 1,x ; point to address of correct line
1230 ldx 2,x ; get correct line number
1231 stx V47 ; save it
1232 bra L8AC7 ; insert into line
1233 L8ADD ldx TXTTAB ; get beginning of program
1234 bra L8AE5
1235 L8AE1 ldx CHARAD ; get input pointer
1236 leax 1,x ; move it forward
1237 L8AE5 bsr L8A86 ; return if end of program
1238 leax 2,x ; move past line address
1239 L8AE9 leax 1,x ; move forward
1240 L8AEB stx CHARAD ; save input pointer
1241 L8AED jsr GETNCH ; get an input character
1242 L8AEF tsta ; is it actual 0?
1243 beq L8AE1 ; brif end of line
1244 bpl L8AED ; brif not a token
1245 ldx CHARAD ; get input pointer
1246 cmpa #0xff ; function?
1247 beq L8AE9 ; brif so - ignore it (and following byte)
1248 jsr RVEC22 ; do the RAM hook thing
1249 cmpa #0xa7 ; THEN?
1250 beq L8B13 ; brif so
1251 cmpa #0x84 ; ELSE?
1252 beq L8B13 ; brif so
1253 cmpa #0x81 ; GO(TO|SUB)?
1254 bne L8AED ; brif not - we don't have a line number
1255 jsr GETNCH ; get TO/SUB
1256 cmpa #0xa5 ; GOTO?
1257 beq L8B13 ; brif so
1258 cmpa #0xa6 ; GOSUB?
1259 bne L8AEB ; brif not
1260 L8B13 jsr GETNCH ; fetch character after token
1261 bcs L8B1B ; brif numeric (line number)
1262 L8B17 jsr GETCCH ; set flags on input character
1263 bra L8AEF ; keep checking for line numbers
1264 L8B1B ldx CHARAD ; get input pointer
1265 pshs x ; save it
1266 jsr LAF67 ; parse line number
1267 ldx CHARAD ; get input pointer after line
1268 L8B24 lda ,-x ; get character before pointer
1269 jsr L90AA ; set C if numeric
1270 bcs L8B24 ; brif not numeric
1271 leax 1,x ; move pointer up
1272 tfr x,d ; calculate size of line number
1273 subb 1,s
1274 subb #5 ; make sure at least 5 bytes
1275 beq L8B55 ; brif exactly 5 bytes - no change
1276 blo L8B41 ; brif less than 5 bytes
1277 leau ,x ; move remainder of program backward
1278 negb ; negate extra number of bytes (to subtract from X)
1279 leax b,x ; now X is the correct position to move program to
1280 jsr L89B8 ; shift program backward
1281 bra L8B55
1282 L8B41 stx V47 ; save end of line number space (end of copy)
1283 ldx VARTAB ; get end of program
1284 stx V43 ; set source pointer
1285 negb ; get positive difference
1286 leax b,x ; now X is the top of the destination block
1287 stx V41 ; set copy destination
1288 stx VARTAB ; save new end of program
1289 jsr LAC1E ; make sure enough room and make a hole in the program
1290 ldx V45 ; get end address of destination block
1291 stx CHARAD ; set input there
1292 L8B55 puls x ; get starting address of the line number
1293 lda #1 ; set "new number" flag
1294 sta ,x
1295 sta 2,x
1296 sta 4,x
1297 ldb BINVAL ; get MS byte of line number
1298 bne L8B67 ; brif it is not zero
1299 ldb #1 ; set to 1 if MSB is 0
1300 inc 2,x ; flag MSB as 0
1301 L8B67 stb 1,x ; set MSB of line number
1302 ldb BINVAL+1 ; get LSB of number
1303 bne L8B71 ; brif nonzero
1304 ldb #1 ; set to 1 if LSB is 0
1305 inc 4,x ; flag LSB as 0
1306 L8B71 stb 3,x ; save LSB of line number
1307 jsr GETCCH ; get input character
1308 cmpa #', ; multiple line numbers? (ON GOTO, ON GOSUB)
1309 beq L8B13 ; brif so - process another
1310 bra L8B17 ; go look for more line numbers
1311 L8B7B ldx TXTTAB ; point to start of program
1312 leax -1,x ; move back (compensate for inc below)
1313 L8B7F leax 1,x ; move forward
1314 ldd 2,x ; get this line number
1315 std CURLIN ; save it (for error message)
1316 jsr L8A86 ; return if end of program
1317 leax 3,x ; skip address and line number, stay one before line text
1318 L8B8A leax 1,x ; move to next character
1319 L8B8C lda ,x ; get input character
1320 beq L8B7F ; brif end of line
1321 deca ; valid line new line number?
1322 beq L8BAE ; brif so
1323 suba #2 ; undefined line?
1324 bne L8B8A ; brif not
1325 pshs x ; save line number pointer
1326 ldx #L8BD9-1 ; show UL message
1327 jsr STRINOUT
1328 ldx ,s ; get input pointer
1329 ldd 1,x ; get undefined line number
1330 jsr LBDCC ; display line number
1331 jsr LBDC5 ; print out "IN XXXX"
1332 jsr LB958 ; do a newline
1333 puls x ; get input pointer back
1334 L8BAE pshs x ; save input pointer
1335 ldd 1,x ; get binary value of line number
1336 std FPA0+2 ; save it in FPA0
1337 jsr L880E ; adjust FPA0 as integer
1338 jsr LBDD9 ; convert to text string
1339 puls u ; get previous input pointer address
1340 ldb #5 ; each expanded line uses 5 bytes
1341 L8BBE leax 1,x ; move pointer forward (in string number) past sign
1342 lda ,x ; do we have a digit?
1343 beq L8BC9 ; brif not - end of number
1344 decb ; mark a byte consumed
1345 sta ,u+ ; put digit in program
1346 bra L8BBE ; copy another digit
1347 L8BC9 leax ,u ; point to address at end of text number
1348 tstb ; did number fill whole space?
1349 beq L8B8C ; brif so - move on
1350 leay ,u ; save end of number pointer
1351 leau b,u ; point to the end of the original expanded number
1352 jsr L89B8 ; close up gap in program
1353 leax ,y ; get end of line number pointer back
1354 bra L8B8C ; go process more
1355 L8BD9 fcn 'UL '
1356 ; HEX$ function
1357 HEXDOL jsr LB740 ; convert argument to positive integer
1358 ldx #STRBUF+2 ; point to string buffer
1359 ldb #4 ; convert 4 nibbles
1360 L8BE5 pshs b ; save nibble counter
1361 clrb ; clear digit accumulator
1362 lda #4 ; do 4 shifts
1363 L8BEA asl FPA0+3 ; shift a bit off the left of the value into low bits of B
1364 rol FPA0+2
1365 rolb
1366 deca ; done all shifts?
1367 bne L8BEA ; brif not
1368 tstb ; do we have a nonzero digit?
1369 bne L8BFF ; brif so
1370 lda ,s ; is it last digit?
1371 deca
1372 beq L8BFF ; brif so - keep the 0
1373 cmpx #STRBUF+2 ; is it a middle zero?
1374 beq L8C0B ; brif not
1375 L8BFF addb #'0 ; add ASCII bias
1376 cmpb #'9 ; above 9?
1377 bls L8C07 ; brif not
1378 addb #7 ; adjust into alpha range
1379 L8C07 stb ,x+ ; save digit in output
1380 clr ,x ; make sure we have a NUL term
1381 L8C0B puls b ; get back nibble counter
1382 decb ; done all?
1383 bne L8BE5 ; brif not
1384 leas 2,s ; don't return mainline (we're returning a string)
1385 ldx #STRBUF+1 ; point to start of converted number
1386 jmp LB518 ; save string in string space, etc., and return it
1387 ; DLOAD command; this is eliminated on the Coco3. It was basically useless anyway so it was
1388 ; a good candidate to overwrite for some extra code space in the lower 16K of the internal
1389 ; ROM. Now, DLOAD functions as another entry into the RESET sequence.
1390 DLOAD jsr LA429 ; close tape file
1391 L8C1B orcc #0x50 ; make sure interrupts are disabled
1392 lda #MC3+MC1 ; disable MMU, 32K internal ROM, not "coco" compatible
1393 sta INIT0
1394 clr TYCLR ; go to ROM mapping mode
1395 jmp SC000 ; transfer control to the "hidden" init code
1396 L8C28 clr INT.FLAG ; set the interrupt flag to not valid
1397 clr PIA1+3 ; disable cartridge interrupt
1398 L8C2E lda #COCO+MMUEN+MC3+MC2 ; enable SCS, 16K split, MMU, COCO mode
1399 sta INIT0
1400 clr TYCLR ; go to ROM mode
1401 L8C36 rts
1402 L8C37 pshs a,b,x ; save registers
1403 ldx CURPOS ; get cursor position
1404 ldb HRWIDTH ; hi-res mode?
1405 lbne ALINK22 ; brif so
1406 ldb 1,s ; restore B
1407 jmp LA30E ; go back to mainline code
1408 L8C46 pshs cc ; save Z
1409 tst HRWIDTH ; hi-res?
1410 beq L8C4F ; brif not
1411 jmp ALINK23 ; go to hi-res handler
1412 L8C4F puls cc ; get back Z
1413 jmp LA913 ; go back to mainline code
1414 nop
1415 fcb 0xc7 ; junk byte (too few NOPs above)
1416 ; This returns to the remainder of the original ECB 1.1 DLOAD code
1417 tstb ; ASCII?
1418 beq L8C5F ; brif not - do error
1419 jsr LAD19 ; clear out program
1420 jmp LAC7C ; go read program
1421 L8C5F jmp LA616 ; raise bad file mode
1422 ; CLOADM patch for Extended Basic
1423 L8C62 jsr GETNCH ; get character after CLOAD
1424 cmpa #'M ; CLOADM?
1425 lbne CLOAD ; brif not - Color Basic's CLOAD can handle it
1426 clr FILSTA ; close tape file
1427 jsr GETNCH ; eat the "M"
1428 jsr LA578 ; parse file name
1429 jsr LA648 ; find the file
1430 tst CASBUF+10 ; is it a chunked file?
1431 lbeq LA505 ; brif not - Color Basic's CLOADM can handle it
1432 ldu CASBUF+8 ; get file type and ASCII flag
1433 dec DEVNUM ; set source device to tape
1434 jsr LA635 ; go read the first block
1435 tfr u,d ; put type and ASCII flag somewhere more useful
1436 ; NOTE: DLOADM comes here to do the final processing
1437 L8C85 subd #0x200 ; is it binary and "machine language"?
1438 bne L8C5F ; brif not - raise an error
1439 ldx ZERO ; default load offset
1440 jsr GETCCH ; is there any offset?
1441 beq L8C96 ; brif not
1442 jsr SYNCOMMA ; make sure there's a comma
1443 jsr LB73D ; evaluate offset in X
1444 L8C96 stx VD3 ; save offset
1445 jsr LA5C7 ; raise error if more stuff follows
1446 L8C9B bsr L8CC6 ; get type of "amble"
1447 pshs a ; save it
1448 bsr L8CBF ; read in block length
1449 tfr d,y ; save it
1450 bsr L8CBF ; read in load address
1451 addd VD3 ; add in offset
1452 std EXECJP ; save it as the execution address
1453 tfr d,x ; put load address in a pointer
1454 lda ,s+ ; get "amble" type
1455 lbne LA42D ; brif postamble - close file
1456 L8CB1 bsr L8CC6 ; read a data byte
1457 sta ,x ; save in memory
1458 cmpa ,x+ ; did it actually save?
1459 bne L8CCD ; brif not RAM - raise error
1460 leay -1,y ; done yet?
1461 bne L8CB1 ; brif not
1462 bra L8C9B ; look for another "amble"
1463 L8CBF bsr L8CC1 ; read a character to B
1464 L8CC1 bsr L8CC6 ; read character to A
1465 exg a,b ; swap character with previously read one
1466 L8CC5 rts
1467 L8CC6 jsr LA176 ; read a character from input
1468 tst CINBFL ; EOF?
1469 beq L8CC5 ; brif not
1470 L8CCD jmp LA619 ; raise I/O error if EOF
1471 L8CD0 bsr L8D14 ; transmit file name
1472 pshs b,a ; save file status
1473 inca ; was file found?
1474 beq L8CDD ; brif not
1475 ldu ZERO ; zero U - first block
1476 bsr L8CE4 ; read block
1477 puls a,b,pc ; restore status and return
1478 L8CDD ldb #2*26 ; code for NE error
1479 jmp LAC46 ; raise error
1480 L8CE2 ldu CBUFAD ; get block number
1481 L8CE4 leax 1,u ; bump block number
1482 stx CBUFAD ; save new block number
1483 ldx #CASBUF ; use cassette buffer
1484 jsr L8D7C ; read a block
1485 jmp LA644 ; reset input buffer pointers
1486 ; Generic input handler for Extended Basic
1487 XVEC4 lda DEVNUM ; get device number
1488 cmpa #-3 ; DLOAD?
1489 bne L8D01 ; brif not
1490 leas 2,s ; don't return to mainline code
1491 clr CINBFL ; reset EOF flag to not EOF
1492 tst CINCTR ; anything available?
1493 bne L8D02 ; brif so - fetch one
1494 com CINBFL ; flag EOF
1495 L8D01 rts
1496 L8D02 pshs u,y,x,b ; save registers
1497 ldx CINPTR ; get buffer pointer
1498 lda ,x+ ; get character from buffer
1499 pshs a ; save it for return
1500 stx CINPTR ; save new input pointer
1501 dec CINCTR ; account for byte removed from buffer
1502 bne L8D12 ; brif buffer not empty
1503 bsr L8CE2 ; go read a block
1504 L8D12 puls a,b,x,y,u,pc ; restore registers, return value, and return
1505 L8D14 clra ; clear attempt counter
1506 pshs x,b,a ; make a hole for variables
1507 leay ,s ; set up frame pointer
1508 bra L8D1D ; go read block
1509 L8D1B bsr L8D48 ; bump attempt counter
1510 L8D1D lda #0x8a ; send file request control code
1511 bsr L8D58
1512 bne L8D1B ; brif no echo or error
1513 ldx #CFNBUF+1 ; point to file name
1514 L8D26 lda ,x+ ; get file name characater
1515 jsr L8E04 ; send it
1516 cmpx #CFNBUF+9 ; end of file name?
1517 bne L8D26 ; brif not
1518 bsr L8D62 ; output check byte and look for response
1519 bne L8D1B ; transmit name again if not ack
1520 bsr L8D72 ; get file type (0xff is not found)
1521 bne L8D1B ; brif error
1522 sta 2,y ; save file type
1523 bsr L8D72 ; read ASCII flag
1524 bne L8D1B ; brif error
1525 sta 3,y ; save ASCII flag
1526 bsr L8D6B ; read check byte
1527 bne L8D1B ; brif error
1528 leas 2,s ; lose attempt counter and check byte
1529 puls a,b,pc ; return file type and ascii flag
1530 L8D48 inc ,y ; bump attempt counter
1531 lda ,y ; get new count
1532 cmpa #5 ; done 5 times?
1533 blo L8D6A ; brif not
1534 lda #0xbc ; send abort code
1535 jsr L8E0C
1536 jmp LA619 ; raise an I/O error
1537 L8D58 pshs a ; save compare character
1538 bsr L8DB8 ; send character
1539 bne L8D60 ; brif read error
1540 cmpa ,s ; does it match? (set Z if good)
1541 L8D60 puls a,pc ; restore character and return
1542 L8D62 lda 1,y ; get XOR check byte
1543 bsr L8DB8 ; send it and read
1544 bne L8D6A ; brif read error
1545 cmpa #0xc8 ; is it ack? (set Z if so)
1546 L8D6A rts
1547 L8D6B bsr L8D72 ; read character from rs232
1548 bne L8D6A ; brif error
1549 lda 1,y ; get check byte
1550 rts
1551 L8D72 bsr L8DBC ; read a character from rs232
1552 pshs a,cc ; save result (and flags)
1553 eora 1,y ; accumulate xor checksum
1554 sta 1,y
1555 puls cc,a,pc ; restore byte, flags, and return
1556 L8D7C clra ; reset attempt counter
1557 pshs u,y,x,b,a ; make a stack frame
1558 asl 7,s ; split block number into two 7 bit chuncks
1559 rol 6,s
1560 lsr 7,s
1561 leay ,s ; set up frame pointer
1562 bra L8D8B
1563 L8D89 bsr L8D48 ; bump attempt counter
1564 L8D8B lda #0x97 ; send block request code
1565 bsr L8D58
1566 bne L8D89 ; brif error
1567 lda 6,y ; send out block number (high bits first)
1568 bsr L8E04
1569 lda 7,y
1570 bsr L8E04
1571 bsr L8D62 ; send check byte and get ack
1572 bne L8D89 ; brif error
1573 bsr L8D72 ; read block size
1574 bne L8D89 ; brif read error
1575 sta 4,y ; save character count
1576 ldx 2,y ; get buffer pointer
1577 ldb #128 ; length of data block
1578 L8DA7 bsr L8D72 ; read a data byte
1579 bne L8D89 ; brif error
1580 sta ,x+ ; save byte in buffer
1581 decb ; done a whole block?
1582 bne L8DA7 ; brif not
1583 bsr L8D6B ; read check byte
1584 bne L8D89 ; brif error
1585 leas 4,s ; lose attempt counter, check byte, and buffer pointer
1586 puls a,b,x,pc ; return with character count in A, clean rest of stack
1587 L8DB8 clr 1,y ; clear check byte
1588 bsr L8E0C ; output character
1589 L8DBC clra ; clear attempt counter
1590 pshs x,b,cc ; save registers and interrupt status
1591 orcc #0x50 ; disable interrupts
1592 lda TIMOUT ; get timout delay (variable)
1593 ldx ZERO ; get constant timeout value
1594 L8DC5 bsr L8DE6 ; get RS232 status
1595 bcc L8DC5 ; brif "space" - waiting for "mark"
1596 L8DC9 bsr L8DE6 ; get RS232 status
1597 bcs L8DC9 ; brif "mark" - waiting for "space" (start bit)
1598 bsr L8DF9 ; delay for half of bit time
1599 ldb #1 ; set bit probe
1600 pshs b ; save it
1601 clra ; reset data byte
1602 L8DD4 bsr L8DF7 ; wait one bit time
1603 ldb PIA1+2 ; get input bit to carry
1604 rorb
1605 bcc L8DDE ; brif "space" (0)
1606 ora ,s ; merge bit probe in
1607 L8DDE asl ,s ; shift bit probe over
1608 bcc L8DD4 ; brif we haven't done 8 bits
1609 leas 1,s ; remove bit probe
1610 puls cc,b,x,pc ; restore interrupts, registers, and return
1611 L8DE6 ldb PIA1+2 ; get RS232 value
1612 rorb ; put in C
1613 leax 1,x ; bump timeout
1614 bne L8DF6 ; brif nonzero
1615 deca ; did the number of waits expire?
1616 bne L8DF6 ; brif not
1617 leas 2,s ; don't return - we timed out
1618 puls cc,b,x ; restore interrupts and registers
1619 inca ; clear Z (A was zero above)
1620 L8DF6 rts
1621 L8DF7 bsr L8DF9 ; do first half of bit delay then fall through for second
1622 L8DF9 pshs a ; save register
1623 lda DLBAUD ; get baud rate constant
1624 L8DFD brn L8DFD ; do nothing - delay
1625 deca ; time expired?
1626 bne L8DFD ; brif not
1627 puls a,pc ; restore register and return
1628 L8E04 pshs a ; save character to send
1629 eora 1,y ; accumulate chechsum
1630 sta 1,y
1631 puls a ; get character back
1632 L8E0C pshs b,a,cc ; save registers and interrupt status
1633 orcc #0x50 ; disable interrupts
1634 bsr L8DF7 ; do a bit delay
1635 bsr L8DF7 ; do another bit delay
1636 clr PIA1 ; set output to space (start bit)
1637 bsr L8DF7 ; do a bit delay
1638 ldb #1 ; bit probe start at LSB
1639 pshs b ; save bitprobe
1640 L8E1D lda 2,s ; get output byte
1641 anda ,s ; see what our current bit is
1642 beq L8E25 ; brif output is 0
1643 lda #2 ; set output to "marking"
1644 L8E25 sta PIA1 ; send bit
1645 bsr L8DF7 ; do a bit delay
1646 asl ,s ; shift bit probe
1647 bcc L8E1D ; brif not last bit
1648 lda #2 ; set output to marking ("stop" bit)
1649 sta PIA1
1650 leas 1,s ; lose bit probe
1651 puls cc,a,b,pc ; restore registers, interrupts, and return
1652 ; PRINT USING
1653 ; This is a massive block of code for something that has limited utility. It is *almost* flexible enough to
1654 ; be truly useful outside of a narrow range of use cases. Indeed, this comes in at about 1/8 of the total
1655 ; Extended Color Basic ROM.
1656 ;
1657 ; This uses several variables:
1658 ; VD5: pointer to format string descriptor
1659 ; VD7: next print item flag
1660 ; VD8: right digit counter
1661 ; VD9: left digit counter (or length of string argument)
1662 ; VDA: status byte (bits as follows):
1663 ; 6: force comma
1664 ; 5: force leading *
1665 ; 4: floating $
1666 ; 3: pre-sign
1667 ; 2: post-sign
1668 ; 0: scientific notation
1669 L8E37 lda #1 ; set length to use to 1
1670 sta VD9
1671 L8E3B decb ; consume character from format string
1672 jsr L8FD8 ; show error flag if flags set
1673 jsr GETCCH ; get input character
1674 lbeq L8ED8 ; brif end of line - bail
1675 stb VD3 ; save remaining string length
1676 jsr LB156 ; evaluate the argument
1677 jsr LB146 ; error if numeric
1678 ldx FPA0+2 ; get descriptor for argument
1679 stx V4D ; save it for later
1680 ldb VD9 ; get length counter to use
1681 jsr LB6AD ; get B bytes of string space (do a LEFT$)
1682 jsr LB99F ; print the formatted string
1683 ldx FPA0+2 ; get formatted string descriptor
1684 ldb VD9 ; get requested length
1685 subb ,x ; see if we have any left over
1686 L8E5F decb ; have we got the right width?
1687 lbmi L8FB3 ; brif so - go process more
1688 jsr LB9AC ; output a space
1689 bra L8E5F ; go see if we're done yet
1690 L8E69 stb VD3 ; save current format string counter and pointer
1691 stx TEMPTR
1692 lda #2 ; initial spaces count = 2 (for the two %s)
1693 sta VD9 ; save length counter
1694 L8E71 lda ,x ; get character in string
1695 cmpa #'% ; is it the end of the sequence?
1696 beq L8E3B ; brif so - display requested part of the strign
1697 cmpa #0x20 ; space?
1698 bne L8E82 ; brif not
1699 inc VD9 ; bump spaces count
1700 leax 1,x ; move format pointer forward
1701 decb ; consume character
1702 bne L8E71 ; brif not end of format string
1703 L8E82 ldx TEMPTR ; restore format string pointer
1704 ldb VD3 ; get back format string length
1705 lda #'% ; show % as debugging aid
1706 L8E88 jsr L8FD8 ; send error indicator if flags set
1707 jsr PUTCHR ; output character
1708 bra L8EB9 ; go process more format string
1709 ; PRINT extension for USING
1710 XVEC9 cmpa #0xcd ; USING?
1711 beq L8E95 ; brif so
1712 rts ; return to mainline code
1713 ; This is the main entry point for PRINT USING
1714 L8E95 leas 2,s ; don't return to the mainline code
1715 jsr LB158 ; evaluate the format string
1716 jsr LB146 ; error if numeric
1717 ldb #'; ; make sure there's a ; after the string
1718 jsr LB26F
1719 ldx FPA0+2 ; get format string descriptor
1720 stx VD5 ; save it for later
1721 bra L8EAE ; process format string
1722 L8EA8 lda VD7 ; is there a print item?
1723 beq L8EB4 ; brif not
1724 ldx VD5 ; get back format string descriptor
1725 L8EAE clr VD7 ; reset next print item flag
1726 ldb ,x ; get length of format string
1727 bne L8EB7 ; brif string is non-null
1728 L8EB4 jmp LB44A ; raise FC error
1729 L8EB7 ldx 2,x ; point to start of string
1730 L8EB9 clr VDA ; clear status (new item)
1731 L8EBB clr VD9 ; clear left digit counter
1732 lda ,x+ ; get character from format string
1733 cmpa #'! ; ! (use first character of string)?
1734 lbeq L8E37 ; brif so
1735 cmpa #'# ; digit?
1736 beq L8F24 ; brif so - handle numeric
1737 decb ; consume format character
1738 bne L8EE2 ; brif not done
1739 jsr L8FD8 ; show a "+" if any flags set - indicates error at end of string
1740 jsr PUTCHR ; output format string character
1741 L8ED2 jsr GETCCH ; get current input character
1742 bne L8EA8 ; brif not end of statement
1743 lda VD7 ; get next item flag
1744 L8ED8 bne L8EDD ; brif more print items
1745 jsr LB958 ; do newline
1746 L8EDD ldx VD5 ; point to format string descriptor
1747 jmp LB659 ; remove from string stack, etc., if appropriate (and return)
1748 L8EE2 cmpa #'+ ; is it + (pre-sign)?
1749 bne L8EEF ; brif not
1750 jsr L8FD8 ; send a "+" if flags set
1751 lda #8 ; flag for pre-sign
1752 sta VDA ; set flags
1753 bra L8EBB ; go interpret some more stuff
1754 L8EEF cmpa #'. ; decimal?
1755 beq L8F41 ; brif so - numeric
1756 cmpa #'% ; % (show string)?
1757 lbeq L8E69 ; brif so
1758 cmpa ,x ; do we have two identical characters?
1759 L8EFB bne L8E88 ; brif not - invalid format character
1760 cmpa #'$ ; double $?
1761 beq L8F1A ; brif so - floating $
1762 cmpa #'* ; double *?
1763 bne L8EFB ; brif not
1764 lda VDA ; get status byte
1765 ora #0x20 ; enable * padding
1766 sta VDA
1767 cmpb #2 ; is $$ the last two?
1768 blo L8F20 ; brif so
1769 lda 1,x ; is it $ after?
1770 cmpa #'$
1771 bne L8F20 ; brif not
1772 decb ; consume the "$"
1773 leax 1,x
1774 inc VD9 ; add to digit counter * pad + $ counter
1775 L8F1A lda VDA ; indicate floating $
1776 ora #0x10
1777 sta VDA
1778 L8F20 leax 1,x ; consume the second format character
1779 inc VD9 ; add one more left place
1780 L8F24 clr VD8 ; clear right digit counter
1781 L8F26 inc VD9 ; bump left digit counter
1782 decb ; consume character
1783 beq L8F74 ; brif end of string
1784 lda ,x+ ; get next format character
1785 cmpa #'. ; decimal?
1786 beq L8F4F ; brif so
1787 cmpa #'# ; digit?
1788 beq L8F26 ; brif so
1789 cmpa #', ; comma flag?
1790 bne L8F5A ; brif not
1791 lda VDA ; set commas flag
1792 ora #0x40
1793 sta VDA
1794 bra L8F26 ; handle more characters to left of decimal
1795 L8F41 lda ,x ; get character after .
1796 cmpa #'# ; digit?
1797 lbne L8E88 ; brif not - invalid
1798 lda #1 ; set right digit counter to 1 (for the .)
1799 sta VD8
1800 leax 1,x ; consume the .
1801 L8F4F inc VD8 ; add one to right digit counter
1802 decb ; consume character
1803 beq L8F74 ; brif end of format string
1804 lda ,x+ ; get another format character
1805 cmpa #'# ; digit?
1806 beq L8F4F ; brif so
1807 L8F5A cmpa #0x5e ; up arrow?
1808 bne L8F74 ; brif not
1809 cmpa ,x ; two of them?
1810 bne L8F74 ; brif not
1811 cmpa 1,x ; three of them?
1812 bne L8F74 ; brif not
1813 cmpa 2,x ; four of them?
1814 bne L8F74 ; brif not
1815 cmpb #4 ; string actually has the characters?
1816 blo L8F74 ; brif not
1817 subb #4 ; consome them
1818 leax 4,x
1819 inc VDA ; set scientific notation bit
1820 L8F74 leax -1,x ; back up input pointer
1821 inc VD9 ; add one digit for pre-sign force
1822 lda VDA ; is it pre-sign?
1823 bita #8
1824 bne L8F96 ; brif so
1825 dec VD9 ; undo pre-sign adjustment
1826 tstb ; end of string?
1827 beq L8F96 ; brif so
1828 lda ,x ; get next character
1829 suba #'- ; post sign force?
1830 beq L8F8F ; brif so
1831 cmpa #'+-'- ; plus?
1832 bne L8F96 ; brif not
1833 lda #8 ; trailing + is a pre-sign force
1834 L8F8F ora #4 ; add in post sign flag
1835 ora VDA ; merge with flags
1836 sta VDA
1837 decb ; consume character
1838 L8F96 jsr GETCCH ; do we have an argument
1839 lbeq L8ED8 ; brif not
1840 stb VD3 ; save format string length
1841 jsr LB141 ; evluate numeric expression
1842 lda VD9 ; get left digit counter
1843 adda VD8 ; add in right digit counter
1844 cmpa #17 ; is it more than 16 digits + decimal?
1845 lbhi LB44A ; brif so - this is a problem
1846 jsr L8FE5 ; format value according to settings
1847 leax -1,x ; move buffer pointer back
1848 jsr STRINOUT ; display formatted number string
1849 L8FB3 clr VD7 ; reset next print item flag
1850 jsr GETCCH ; get current input character
1851 beq L8FC6 ; brif end of statement
1852 sta VD7 ; set next print flag to nonzero
1853 cmpa #'; ; list separator ;?
1854 beq L8FC4 ; brif so
1855 jsr SYNCOMMA ; require a comma between if not ;
1856 bra L8FC6 ; process next item
1857 L8FC4 jsr GETNCH ; munch the semicolon
1858 L8FC6 ldx VD5 ; get format string descriptor
1859 ldb ,x ; get length of string
1860 subb VD3 ; subtract amount left after last item
1861 ldx 2,x ; point to string address
1862 abx ; move pointer to correct spot
1863 ldb VD3 ; get remaining string length
1864 lbne L8EB9 ; if we have more, interpret from there
1865 jmp L8ED2 ; re-interpret from start if we hit the end
1866 L8FD8 pshs a ; save character
1867 lda #'+ ; "error" flag character
1868 tst VDA ; did we have some flags set?
1869 beq L8FE3 ; brif not
1870 jsr PUTCHR ; output error flag
1871 L8FE3 puls a,pc ; restore character and return
1872 L8FE5 ldu #STRBUF+4 ; point to string buffer
1873 ldb #0x20 ; blank space
1874 lda VDA ; get flags
1875 bita #8 ; pre-sign?
1876 beq L8FF2 ; brif not
1877 ldb #'+ ; plus sign
1878 L8FF2 tst FP0SGN ; get sign of value
1879 bpl L8FFA ; brif positive
1880 clr FP0SGN ; make number positive (for later)
1881 ldb #'- ; negative sign
1882 L8FFA stb ,u+ ; put sign in buffer
1883 ldb #'0 ; put a zero there
1884 stb ,u+
1885 anda #1 ; check scientific notation force
1886 lbne L910D ; brif so
1887 ldx #LBDC0 ; point to FP 1E+9
1888 jsr LBCA0 ; is it less?
1889 bmi L9023 ; brif so
1890 jsr LBDD9 ; convert FP number to string (we're doing scientific notation)
1891 L9011 lda ,x+ ; advance pointer to end of string
1892 bne L9011
1893 L9015 lda ,-x ; make a hole at the start
1894 sta 1,x
1895 cmpx #STRBUF+3 ; done yet?
1896 bne L9015 ; brif not
1897 lda #'% ; put "overflow" flag at start
1898 sta ,x
1899 rts
1900 L9023 lda FP0EXP ; get exponent of value
1901 sta V47 ; save it
1902 beq L902C ; brif value is 0
1903 jsr L91CD ; convert to number with 9 significant figures to left of decimal
1904 L902C lda V47 ; get base 10 exponent offset
1905 lbmi L90B3 ; brif < 100,000,000
1906 nega ; get negative difference
1907 adda VD9 ; add to number of left digits
1908 suba #9 ; account for the 9 we actually have
1909 jsr L90EA ; put leading zeroes in buffer
1910 jsr L9263 ; initialize the decimal point and comma counters
1911 jsr L9202 ; convert FPA0 to decimal ASCII in buffer
1912 lda V47 ; get base 10 exponent
1913 jsr L9281 ; put that many zeroes in buffer, stop at decimal point
1914 lda V47 ; get base 10 exponent
1915 jsr L9249 ; check for decimal
1916 lda VD8 ; get right digit counter
1917 bne L9050 ; brif we want stuff after decimal
1918 leau -1,u ; delete decimal if not needed
1919 L9050 deca ; subtract one place (for decimal)
1920 jsr L90EA ; put zeroes in buffer (trailing)
1921 L9054 jsr L9185 ; insert * padding, floating $, and post-sign
1922 tsta ; was there a post sign?
1923 beq L9060 ; brif not
1924 cmpb #'* ; was first character a *?
1925 beq L9060 ; brif so
1926 stb ,u+ ; store the post sign
1927 L9060 clr ,u ; make srue it's NUL terminated
1928 ldx #STRBUF+3 ; point to start of buffer
1929 L9065 leax 1,x ; move to next character
1930 stx TEMPTR ; save it for later
1931 lda VARPTR+1 ; get address of decimal point
1932 suba TEMPTR+1 ; subtract out actual digits left of decimal
1933 suba VD9 ; subtract out required left digits
1934 beq L90A9 ; brif no padding needed
1935 lda ,x ; get current character
1936 cmpa #0x20 ; space?
1937 beq L9065 ; brif so - advance pointer
1938 cmpa #'* ; *?
1939 beq L9065 ; brif so - advance pointer
1940 clra ; zero on stack is end of data ponter
1941 L907C pshs a ; save character on stack
1942 lda ,x+ ; get next character
1943 cmpa #'- ; minus?
1944 beq L907C ; brif so
1945 cmpa #'+ ; plus?
1946 beq L907C ; brif so
1947 cmpa #'$ ; $?
1948 beq L907C ; brif so
1949 cmpa #'0 ; zero?
1950 bne L909E ; brif not
1951 lda 1,x ; get character after 0
1952 bsr L90AA ; clear carry if number
1953 bcs L909E ; brif not number
1954 L9096 puls a ; get character off stack
1955 sta ,-x ; put it back in string buffer
1956 bne L9096 ; brif not - restore another
1957 bra L9065 ; keep cleaning up buffer
1958 L909E puls a ; get the character on the stack
1959 tsta ; is it NUL?
1960 bne L909E ; brif not
1961 ldx TEMPTR ; get string buffer start pointer
1962 lda #'% ; put error flag in front
1963 sta ,-x
1964 L90A9 rts
1965 L90AA cmpa #'0 ; zero?
1966 blo L90B2 ; brif not
1967 suba #'9+1 ; set C if > "9"
1968 suba #-('9+1)
1969 L90B2 rts
1970 L90B3 lda VD8 ; get right digit counter
1971 beq L90B8 ; brif not right digits
1972 deca ; account for decimal point
1973 L90B8 adda V47 ; add base 10 exponent offset
1974 bmi L90BD ; if >= 0, no shifts are required
1975 clra ; force shift counter to 0
1976 L90BD pshs a ; save shift counter
1977 L90BF bpl L90CB ; brif positive count
1978 pshs a ; save shift counter
1979 jsr LBB82 ; divide FPA0 by 10 (shift 1 digit to the right)
1980 puls a ; get shift counter back
1981 inca ; account for the shift
1982 bra L90BF ; see if we're done yet
1983 L90CB lda V47 ; get base 10 exponent offset
1984 suba ,s+ ; account for adjustment
1985 sta V47 ; save new exponent offset
1986 adda #9 ; account for significant places
1987 bmi L90EE ; brif we don't need zeroes to left
1988 lda VD9 ; get left decimal counter
1989 suba #9 ; account for significant figures
1990 suba V47 ; subtract exponent offset
1991 bsr L90EA ; output leading zeroes
1992 jsr L9263 ; initialize decimal and comma counters
1993 bra L90FF ; process remainder of digits
1994 L90E2 pshs a ; save zero counter
1995 lda #'0 ; insert a 0
1996 sta ,u+
1997 puls a ; get back counter
1998 L90EA deca ; do we need more zeroes?
1999 bpl L90E2 ; brif so
2000 rts
2001 L90EE lda VD9 ; get left digit counter
2002 bsr L90EA ; put that many zeroes in
2003 jsr L924D ; put decimal in buffer
2004 lda #-9 ; figure out filler zeroes
2005 suba V47
2006 bsr L90EA ; output required leader zeroes
2007 clr V45 ; clear decimal pointer counter
2008 clr VD7 ; clear comma counter
2009 L90FF jsr L9202 ; decode FPA0 to decimal string
2010 lda VD8 ; get right digit counter
2011 bne L9108 ; brif there are right digits
2012 ldu VARPTR ; point to decimal location of decimal
2013 L9108 adda V47 ; add base 10 exponent
2014 lbra L9050 ; add in leading astrisks, etc.
2015 L910D lda FP0EXP ; get exponent of FPA0
2016 pshs a ; save it
2017 beq L9116 ; brif 0
2018 jsr L91CD ; convert to number with 9 figures
2019 L9116 lda VD8 ; get right digit counter
2020 beq L911B ; brif no right digits
2021 deca ; account for decimal point
2022 L911B adda VD9 ; get left digit counter
2023 clr STRBUF+3 ; use buffer byte as temporary storage
2024 ldb VDA ; get status flags
2025 andb #4 ; post-sign?
2026 bne L9129 ; brif so
2027 com STRBUF+3 ; flip byte if no post sign
2028 L9129 adda STRBUF+3 ; subtract 1 if no post sign
2029 suba #9 ; account for significant figures
2030 pshs a ; save shift counter
2031 L9130 bpl L913C ; brif no more shifts needed
2032 pshs a ; save counter
2033 jsr LBB82 ; divide by 10 (shift right one)
2034 puls a ; get back counter
2035 inca ; account for the shift
2036 bra L9130 ; see if we need more
2037 L913C lda ,s ; get original shift count
2038 bmi L9141 ; brif shifting happened
2039 clra ; flag for no shifting
2040 L9141 nega ; calculate position of decimal (negate shift count, add left digit and post sign if needed)
2041 adda VD9 ; add left digit counter
2042 inca ; and post sign
2043 adda STRBUF+3
2044 sta V45 ; save decimal counter
2045 clr VD7 ; clear comma counter
2046 jsr L9202 ; convert to decimal string
2047 puls a ; get shift counter
2048 jsr L9281 ; put the needed zeroes in
2049 lda VD8 ; get right digit counter
2050 bne L915A ; brif we want some
2051 leau -1,u ; remove te decimal point
2052 L915A ldb ,s+ ; get original exponent
2053 beq L9167 ; brif it was 0
2054 ldb V47 ; get base 10 exponent
2055 addb #9 ; account for significant figures
2056 subb VD9 ; remove left digit count
2057 subb STRBUF+3 ; add one if post sign
2058 L9167 lda #'+ ; positive sign
2059 tstb ; is base 10 exponent positive?
2060 bpl L916F ; brif so
2061 lda #'- ; negative sign
2062 negb ; flip exponent
2063 L916F sta 1,u ; put exponent sign
2064 lda #'E ; put "E" and advance output pointer
2065 sta ,u++
2066 lda #'0-1 ; initialize digit accumulator
2067 L9177 inca ; bump digit
2068 subb #10 ; are we at the right digit?
2069 bcc L9177 ; brif not
2070 addb #'0+10 ; add ASCII bias and undo extra subtraction
2071 std ,u++ ; save exponent in buffer
2072 clr ,u ; clear final byte in buffer
2073 jmp L9054 ; insert *, $, etc.
2074 L9185 ldx #STRBUF+4 ; point to start of result
2075 ldb ,x ; get sign
2076 pshs b ; save it
2077 lda #0x20 ; default pad with spaces
2078 ldb VDA ; get flags
2079 bitb #0x20 ; padding with *?
2080 puls b
2081 beq L919E ; brif no padding
2082 lda #'* ; pad with *
2083 cmpb #0x20 ; do we have a blank? (positive)
2084 bne L919E ; brif not
2085 tfr a,b ; use pad character
2086 L919E pshs b ; save first character
2087 L91A0 sta ,x+ ; store padding
2088 ldb ,x ; get next character
2089 beq L91B6 ; brif end of string
2090 cmpb #'E ; exponent?
2091 beq L91B6 ; brif so - treat as 0
2092 cmpb #'0 ; zero?
2093 beq L91A0 ; brif so - pad it
2094 cmpb #', ; leading comma?
2095 beq L91A0 ; brif so - pad it
2096 cmpb #'. ; decimal?
2097 bne L91BA ; brif so - don't put a 0 before it
2098 L91B6 lda #'0 ; put a zero before
2099 sta ,-x
2100 L91BA lda VDA ; get status byte
2101 bita #0x10 ; floating $?
2102 beq L91C4 ; brif not
2103 ldb #'$ ; stuff a $ in
2104 stb ,-x
2105 L91C4 anda #4 ; pre-sgn?
2106 puls b ; get back first character
2107 bne L91CC ; brif not
2108 stb ,-x ; save leading character (sign)
2109 L91CC rts
2110 L91CD pshs u ; save buffer pointer
2111 clra ; initial exponent offset is 0
2112 L91D0 sta V47 ; save exponent offset
2113 ldb FP0EXP ; get actual exponent
2114 cmpb #0x80 ; is value >= 1.0?
2115 bhi L91E9 ; brif so
2116 ldx #LBDC0 ; point to FP number 1E9
2117 jsr LBACA ; multiply by 1000000000
2118 lda V47 ; account for 9 shifts
2119 suba #9
2120 bra L91D0 ; brif not there yet
2121 L91E4 jsr LBB82 ; divide by 10
2122 inc V47 ; account for shift
2123 L91E9 ldx #LBDBB ; point to 999999999
2124 jsr LBCA0 ; compare it
2125 bgt L91E4 ; brif not in range yet
2126 L91F1 ldx #LBDB6 ; point to 99999999.9
2127 jsr LBCA0 ; compare
2128 bgt L9200 ; brif in range
2129 jsr LBB6A ; multiply by 10
2130 dec V47 ; account for shift
2131 bra L91F1 ; see if we're in range yet
2132 L9200 puls u,pc ; restore buffer pointer and return
2133 L9202 pshs u ; save buffer pointer
2134 jsr LB9B4 ; add .5 (round off)
2135 jsr LBCC8 ; convert to integer format
2136 puls u ; restore buffer pointer
2137 ldx #LBEC5 ; point to 32 bit powers of 10 (alternating signs)
2138 ldb #0x80 ; intitial digit counter is 0 with 0x80 bias
2139 L9211 bsr L9249 ; check for comma
2140 L9213 lda FPA0+3 ; add a power of 10
2141 adda 3,x
2142 sta FPA0+3
2143 lda FPA0+2
2144 adca 2,x
2145 sta FPA0+2
2146 lda FPA0+1
2147 adca 1,x
2148 sta FPA0+1
2149 lda FPA0
2150 adca ,x
2151 sta FPA0
2152 incb ; add one to digit counter
2153 rorb ; set V if carry and sign differ
2154 rolb
2155 bvc L9213 ; brif we haven't "wrapped"
2156 bcc L9235 ; brif subtracting
2157 subb #10+1 ; take 9's complement if adding
2158 negb
2159 L9235 addb #'0-1 ; add in ASCII bias
2160 leax 4,x ; move to next power
2161 tfr b,a ; save digit
2162 anda #0x7f ; mask off subtract flag
2163 sta ,u+ ; save digit
2164 comb ; toggle add/subtract
2165 andb #0x80
2166 cmpx #LBEE9 ; done all places?
2167 bne L9211 ; brif not
2168 clr ,u ; but NUL at end
2169 L9249 dec V45 ; at decimal?
2170 bne L9256 ; brif not
2171 L924D stu VARPTR ; save decimal point pointer
2172 lda #'. ; insert decimal
2173 sta ,u+
2174 clr VD7 ; clear comma counter
2175 rts
2176 L9256 dec VD7 ; do we need a comma?
2177 bne L9262 ; brif not
2178 lda #3 ; reset comma counter
2179 sta VD7
2180 lda #', ; insert comma
2181 sta ,u+
2182 L9262 rts
2183 L9263 lda V47 ; get base 10 exponent offset
2184 adda #10 ; account for significant figures
2185 sta V45 ; save decimal counter
2186 inca ; add one for decimal point
2187 L926A suba #3 ; divide by 3, leave remainder in A
2188 bcc L926A
2189 adda #5 ; renormalize to range 1-3
2190 sta VD7 ; save comma counter
2191 lda VDA ; get status
2192 anda #0x40 ; commas wanted?
2193 bne L927A ; brif not
2194 sta VD7 ; clear comma counter
2195 L927A rts
2196 L927B pshs a ; save zeroes counter
2197 bsr L9249 ; check for decimal
2198 puls a ; get back counter
2199 L9281 deca ; need a zero?
2200 bmi L928E ; brif not
2201 pshs a ; save counter
2202 lda #'0 ; put a zero
2203 sta ,u+
2204 lda ,s+ ; get back counter and set flags
2205 bne L927B ; brif not done enough
2206 L928E rts
2207 ; From here to the end of the Extended Basic ROM is the PMODE graphics system and related
2208 ; infrastructure with the exception of the PLAY command which shares some of its machinery
2209 ; with the DRAW command.
2210 ;
2211 ; Fetch screen address calculation routine address for the selected graphics mode
2212 L928F ldu #L929C ; point to normalization routine jump table
2213 lda PMODE ; get graphics mode
2214 asla ; two bytes per address
2215 ldu a,u ; get routine address
2216 rts
2217 ; Normalize VERBEG/HORBEG coordinates and return screen address in X and pixel mask in A.
2218 L9298 bsr L928F ; fetch normalization routine pointer
2219 jmp ,u ; transfer control to it
2220 L929C fdb L92A6 ; PMODE 0
2221 fdb L92C2 ; PMODE 1
2222 fdb L92A6 ; PMODE 2
2223 fdb L92C2 ; PMODE 3
2224 fdb L92A6 ; PMODE 4
2225 ; Two colour mode address calculatoin
2226 L92A6 pshs u,b ; savce registers
2227 ldb HORBYT ; get number of bytes in each graphics row
2228 lda VERBEG+1 ; get vertical coordinate
2229 mul
2230 addd BEGGRP ; now D is the absolute address of the start of the row
2231 tfr d,x ; get address to the return location
2232 ldb HORBEG+1 ; get horizontal coordinate
2233 lsrb ; divide by 8 (8 pixels per byte in 2 colour mode)
2234 lsrb
2235 lsrb
2236 abx ; now X is the address of the actual pixel byte
2237 lda HORBEG+1 ; get horizontal coordinate
2238 anda #7 ; keep only the low 3 bits which contain the pixel number
2239 ldu #L92DD ; point to pixel mask lookup
2240 lda a,u ; get pixel mask
2241 puls b,u,pc ; restore registers and return result
2242 ; four colour address calculation
2243 L92C2 pshs u,b ; save registers
2244 ldb HORBYT ; get bytes per graphics row
2245 lda VERBEG+1 ; get vertical coordinate
2246 mul
2247 addd BEGGRP ; now D is the address of the start of the row
2248 tfr d,x ; put it in returnlocatin
2249 ldb HORBEG+1 ; get horizontal coordinate
2250 lsrb ; divide by 4 (four colour modes have four pixels per byte)
2251 lsrb
2252 abx ; now X points to the screen byte
2253 lda HORBEG+1 ; get horizontal coordinate
2254 anda #3 ; keep low two bits for pixel number
2255 ldu #L92E5 ; point to four colour pixel masks
2256 lda a,u ; get pixel mask
2257 puls b,u,pc ; restore registers and return result
2258 L92DD fcb 0x80,0x40,0x20,0x10 ; two colour pixel masks
2259 fcb 0x08,0x04,0x02,0x01
2260 L92E5 fcb 0xc0,0x30,0x0c,0x03 ; four colour pixel masks
2261 ; Move X down one graphics row
2262 L92E9 ldb HORBYT ; get bytes per row
2263 abx ; add to screen address
2264 rts
2265 ; Move one pixel right in 2 colour mode
2266 L92ED lsra ; move pixel mask right
2267 bcc L92F3 ; brif same byte
2268 rora ; move pixel mask to left of byte
2269 leax 1,x ; move to next byte
2270 L92F3 rts
2271 ; Move one pixel right in 4 colour mode
2272 L92F4 lsra ; shift mask half a pixel right
2273 bcc L92ED ; brif not past end of byte - shift one more
2274 lda #0xc0 ; set mask on left of byte
2275 leax 1,x ; move to next byte
2276 rts
2277 ; Evaluate two expressions (coordinates). Put first in HORBEG and second in VERBEG.
2278 L92FC jsr LB734 ; evaluate two expressions - first in BINVAL, second in B
2279 ldy #HORBEG ; point to storage location
2280 L9303 cmpb #192 ; is vertical outside range?
2281 blo L9309 ; brif not
2282 ldb #191 ; max it at bottom of screen
2283 L9309 clra ; zero extend vertical coordinate
2284 std 2,y ; save vertical coordinate
2285 ldd BINVAL ; get horizontal coordinate
2286 cmpd #256 ; in range?
2287 blo L9317 ; brif so
2288 ldd #255 ; max it out to right side of screen
2289 L9317 std ,y ; save horizontal coordinate
2290 rts
2291 ; Normalize coordinates for proper PMODE
2292 L931A jsr L92FC ; parse coordinates
2293 L931D ldu #HORBEG ; point to start coordinates
2294 L9320 lda PMODE ; get graphics mode
2295 cmpa #2 ; is it pmode 0 or 1?
2296 bhs L932C ; brif not
2297 ldd 2,u ; get vertical coordinate
2298 lsra ; divide it by two
2299 rorb
2300 std 2,u ; save it back
2301 L932C lda PMODE ; get graphics mode
2302 cmpa #4 ; pmode 4?
2303 bhs L9338 ; brif so
2304 ldd ,u ; cut horizontal coordinate in half
2305 lsra
2306 rorb
2307 std ,u ; save new coordinate
2308 L9338 rts
2309 ; PPOINT function
2310 PPOINT jsr L93B2 ; evaluate two expressions (coordinates)
2311 jsr L931D ; normalize coordinates
2312 jsr L9298 ; get screen address
2313 anda ,x ; get colour value of desired screen coordinate
2314 ldb PMODE ; get graphics mode
2315 rorb ; is it a two colour m ode?
2316 bcc L935B ; brif so
2317 L9349 cmpa #4 ; is it on rightmost bits?
2318 blo L9351 ; brif not
2319 rora ; shift right
2320 rora
2321 bra L9349 ; see if we're there yet
2322 L9351 inca ; colour numbers start at 1
2323 asla ; add in colour set (0 or 8)
2324 adda CSSVAL
2325 lsra ; get colour in range of 0 to 8
2326 L9356 tfr a,b ; put result to B
2327 jmp LB4F3 ; return B as FP number
2328 L935B tsta ; is pixel on?
2329 beq L9356 ; brif not, return 0 (off)
2330 clra ; set colour number to "1"
2331 bra L9351 ; make it 1 or 5 and return
2332 ; PSET command
2333 PSET lda #1 ; PSET flag
2334 bra L9366 ; go turn on the pixel
2335 ; PRESET command
2336 PRESET clra ; PRESET flag
2337 L9366 sta SETFLG ; store whether we're setting or resetting
2338 jsr LB26A ; enforce (
2339 jsr L931A ; evaluate coordinates
2340 jsr L9581 ; evaluate colour
2341 jsr LB267 ; enforce )
2342 jsr L9298 ; get address of pixel
2343 L9377 ldb ,x ; get screen data
2344 pshs b ; save it
2345 tfr a,b ; duplicate pixel mask
2346 coma ; invert mask
2347 anda ,x ; turn off screen pixel
2348 andb ALLCOL ; adjust pixel mask to be the current colour
2349 pshs b ; merge pixel data into the screen data
2350 ora ,s+
2351 sta ,x ; put it on screen
2352 suba ,s+ ; nonzero if screen data changed
2353 ora CHGFLG ; propagate change flag
2354 sta CHGFLG
2355 rts
2356 ; Evaluate two sets of coordinates separated by a minus sign. First at HORBEG,VERBEG and
2357 ; second at HOREND,VEREND. If no first set, use HORDEF,VERDEF.
2358 L938F ldx HORDEF ; set default start coords
2359 stx HORBEG
2360 ldx VERDEF
2361 stx VERBEG
2362 cmpa #0xac ; do we start with a -?
2363 beq L939E ; brif no starting coordinates
2364 jsr L93B2 ; parse coordinates
2365 L939E ldb #0xac ; make sure we have a -
2366 jsr LB26F
2367 jsr LB26A ; require a (
2368 jsr LB734 ; evaluate two expressions
2369 ldy #HOREND ; point to storage location
2370 jsr L9303 ; process coordinates
2371 bra L93B8 ; finish up with a )
2372 L93B2 jsr LB26A ; make sure there's a (
2373 jsr L92FC ; evaluate coordinates
2374 L93B8 jmp LB267 ; force a )
2375 ; LINE command
2376 LINE cmpa #0x89 ; is it LINE INPUT?
2377 lbeq L89C0 ; brif so - go handle it
2378 cmpa #'( ; starting coord?
2379 beq L93CE ; brif so
2380 cmpa #0xac ; leading -?
2381 beq L93CE ; brif so
2382 ldb #'@ ; if it isn't the above, make sure it's @
2383 jsr LB26F
2384 L93CE jsr L938F ; parse coordinates
2385 ldx HOREND ; set ending coordinates as the defaults
2386 stx HORDEF
2387 ldx VEREND
2388 stx VERDEF
2389 jsr SYNCOMMA ; make sure we have a comma
2390 cmpa #0xbe ; PRESET?
2391 beq L93E9 ; brif so
2392 cmpa #0xbd ; PSET?
2393 lbne LB277 ; brif not
2394 ldb #01 ; PSET flag
2395 skip1lda ; skip byte and set A nonzero
2396 L93E9 clrb ; PRESET flag
2397 pshs b ; save PSET/PRESET flag
2398 jsr GETNCH ; eat the PSET/PRESET
2399 jsr L9420 ; normalize coordinates
2400 puls b ; get back PSET/PRESET flag
2401 stb SETFLG ; flag which we're doing
2402 jsr L959A ; set colour byte
2403 jsr GETCCH ; get next bit
2404 lbeq L94A1 ; brif no box option
2405 jsr SYNCOMMA ; make sure it's comma
2406 ldb #'B ; make sure "B" for "box"
2407 jsr LB26F
2408 bne L9429 ; brif something follows the B
2409 bsr L9444 ; draw horizontal line
2410 bsr L946E ; draw vertical line
2411 ldx HORBEG ; save horizontal coordinate
2412 pshs x ; save it
2413 ldx HOREND ; switch in horizontal end
2414 stx HORBEG
2415 bsr L946E ; draw vertical line
2416 puls x ; get back original start
2417 stx HORBEG ; put it back
2418 ldx VEREND ; do the same dance with the vertical end
2419 stx VERBEG
2420 bra L9444 ; draw horizontal line
2421 L9420 jsr L931D ; normalize the start coordinates
2422 ldu #HOREND ; point to end coords
2423 jmp L9320 ; normalize those coordinates
2424 L9429 ldb #'F ; make sure we have "BF" for "filled box"
2425 jsr LB26F
2426 bra L9434 ; fill the box
2427 L9430 leax -1,x ; move vertical coordinate up one
2428 L9432 stx VERBEG ; save new vertical coordinate
2429 L9434 jsr L9444 ; draw a horizontal line
2430 ldx VERBEG ; are we at the end of the box?
2431 cmpx VEREND
2432 beq L9443 ; brif so
2433 bcc L9430 ; brif we're moving up the screen
2434 leax 1,x ; move down the screen
2435 bra L9432 ; go draw another line
2436 L9443 rts
2437 ; Draw a horizontal line from HORBEG to HOREND at VERBEG using color mask in ALLCOL
2438 L9444 ldx HORBEG ; get starting horizontal coordinate
2439 pshs x ; save it
2440 jsr L971D ; get absolute value of HOREND-HORBEG
2441 bcc L9451 ; brif end is > start
2442 ldx HOREND ; copy end coordinate to start it is smaller
2443 stx HORBEG
2444 L9451 tfr d,y ; save difference - it's a pixel count
2445 leay 1,y ; coordinates are inclusive
2446 jsr L9298 ; get screen position of start coord
2447 puls u ; restore original start coordinate
2448 stu HORBEG
2449 bsr L9494 ; point to routine to move pizel pointers to right
2450 L945E sta VD7 ; save pixel mask
2451 jsr L9377 ; turn on pixel
2452 lda VD7 ; get pixel mask back
2453 jsr ,u ; move one pixel right
2454 leay -1,y ; turned on enough pixels yet?
2455 bne L945E ; brif not
2456 L946B rts
2457 L946C puls b,a ; clean up stack
2458 L946E ldd VERBEG ; save original vertical start coordinate
2459 pshs b,a
2460 jsr L9710 ; get vertical difference
2461 bcc L947B ; brif end coordinate > start
2462 ldx VEREND ; swap in end coordinate if not
2463 stx VERBEG
2464 L947B tfr d,y ; save number of pixels to set
2465 leay 1,y ; the coordinates are inclusive
2466 jsr L9298 ; get screen pointer
2467 puls u ; restore start coordinate
2468 stu VERBEG
2469 bsr L949D ; point to routine to move down one row
2470 bra L945E ; draw vertical line
2471 ; Point to routine which will move one pixel right
2472 L948A fdb L92ED ; PMODE 0
2473 fdb L92F4 ; PMODE 1
2474 fdb L92ED ; PMODE 2
2475 fdb L92F4 ; PMODE 3
2476 fdb L92ED ; PMODE 4
2477 L9494 ldu #L948A ; point to jump table
2478 ldb PMODE ; get graphics mode
2479 aslb ; two bytes per address
2480 ldu b,u ; get jump address
2481 rts
2482 ; Point to routine to move down one row
2483 L949D ldu #L92E9 ; point to "move down one row" routien
2484 rts
2485 ; Draw a line from HORBEG,VERBEG to HOREND,VEREND
2486 L94A1 ldy #L950D ; point to increase vertical coord
2487 jsr L9710 ; calculate difference
2488 lbeq L9444 ; brif none - draw a horizontal line
2489 bcc L94B2 ; brif vertical end is > vertical start
2490 ldy #L951B ; point to decrease vertical coord
2491 L94B2 pshs d ; save vertical difference
2492 ldu #L9506 ; point to increase horizontal coord
2493 jsr L971D ; get difference
2494 beq L946C ; brif none - draw a vertical line
2495 bcc L94C1 ; brif horizontal end > horizontal start
2496 ldu #L9514 ; point to decrease hoizontal coord
2497 L94C1 cmpd ,s ; compare vert and horiz differences
2498 puls x ; get X difference
2499 bcc L94CC ; brif horiz diff > vert diff
2500 exg u,y ; swap change routine pointers
2501 exg d,x ; swap differences
2502 L94CC pshs u,d ; save larger difference and routine
2503 pshs d ; save larger difference
2504 lsra ; divide by two
2505 rorb
2506 bcs L94DD ; brif odd number
2507 cmpu #L950D+1 ; increase or decrease?
2508 blo L94DD ; brif increase
2509 subd #1 ; back up one
2510 L94DD pshs x,b,a ; save smallest difference and initial middle offset
2511 jsr L928F ; point to proper coordinate to screen conversion routine
2512 L94E2 jsr ,u ; convert coordinates to screen address
2513 jsr L9377 ; turn on a pixel
2514 ldx 6,s ; get distnace counter
2515 beq L9502 ; brif line is completely drawn
2516 leax -1,x ; account for one pixel drawn
2517 stx 6,s ; save new counter
2518 jsr [8,s] ; increment/decrement larger delta
2519 ldd ,s ; get the minor coordinate increment counter
2520 addd 2,s ; add the smallest difference
2521 std ,s ; save new minor coordinate incrementcounter
2522 subd 4,s ; subtractout the largest difference
2523 bcs L94E2 ; brif not greater - draw another pixel
2524 std ,s ; save new minor coordinate increment
2525 jsr ,y ; adjust minor coordinate
2526 bra L94E2 ; go draw another pixel
2527 L9502 puls x ; clean up stack and return
2528 puls a,b,x,y,u,pc
2529 L9506 ldx HORBEG ; bump horizontal coordinate
2530 leax 1,x
2531 stx HORBEG
2532 rts
2533 L950D ldx VERBEG ; bump vertical coordinate
2534 leax 1,x
2535 stx VERBEG
2536 rts
2537 L9514 ldx HORBEG ; decrement horizontal coordinate
2538 leax -1,x
2539 stx HORBEG
2540 rts
2541 L951B ldx VERBEG ; decrement vertical coordinate
2542 leax -1,x
2543 stx VERBEG
2544 rts
2545 ; Get normalized maximum coordinate values in VD3 and VD5
2546 L9522 ldu #VD3 ; point to temp storage
2547 ldx #255 ; set maximum horizontal
2548 stx ,u
2549 ldx #191 ; set maximum vertical
2550 stx 2,u
2551 jmp L9320 ; normalize them
2552 ; PCLS command
2553 PCLS beq L9542 ; clear to background colour if no argument
2554 bsr L955A ; evaluate colour
2555 L9536 lda #0x55 ; consider each byte as 4 groups of 2 bit sub-nibbles
2556 mul ; now colour is in all four sub-pixels
2557 ldx BEGGRP ; get start of graphics screen
2558 L953B stb ,x+ ; set byte to proper colour
2559 cmpx ENDGRP ; at end of graphics page?
2560 bne L953B ; brif not
2561 rts
2562 L9542 ldb BAKCOL ; get background colour
2563 bra L9536 ; do the clearing dance
2564 ; COLOR command
2565 COLOR cmpa #', ; check for comma
2566 beq L9552 ; brif no foreground colour
2567 bsr L955A ; evaluate first colour
2568 stb FORCOL ; set foreground colour
2569 jsr GETCCH ; is there a background colour?
2570 beq L9559 ; brif not
2571 L9552 jsr SYNCOMMA ; make sure we have a comma
2572 bsr L955A ; evaluate background colour argument
2573 stb BAKCOL ; set background colour
2574 L9559 rts
2575 ; Evaluate a colour agument and convert to proper code based on graphics mode
2576 L955A jsr EVALEXPB ; evaluate colour code
2577 L955D cmpb #9 ; is it in range of 0-8?
2578 lbhs LB44A ; brif not - raise error
2579 clra ; CSS value for first colour set
2580 cmpb #5 ; is it first or second colour set?
2581 blo L956C ; brif first colour set
2582 lda #8 ; flag second colour set
2583 subb #4 ; adjust into basic range
2584 L956C pshs a ; save CSS value
2585 lda PMODE ; get graphics mode
2586 rora ; 4 colour or 2?
2587 bcc L957B ; brif 2 colour
2588 tstb ; was it 0?
2589 bne L9578 ; brif not
2590 L9576 ldb #4 ; if so, make it 4
2591 L9578 decb ; convert to zero based
2592 L9579 puls a,pc ; get back CSS value and return
2593 L957B rorb ; is colour number odd?
2594 bcs L9576 ; brif so - force all bits set colour
2595 clrb ; force colour 0 if not
2596 bra L9579
2597 ; Set all pixel byte and active colour
2598 L9581 jsr L959A ; set colour byte
2599 jsr GETCCH ; is there something to evaluate?
2600 beq L9598 ; brif not
2601 cmpa #') ; )?
2602 beq L9598 ; brif so
2603 jsr SYNCOMMA ; force comma
2604 cmpa #', ; another comma?
2605 beq L9598 ; brif so
2606 jsr L955A ; evaluate expression and return colour
2607 bsr L95A2 ; save colour and pixel byte
2608 L9598 jmp GETCCH ; re-fetch input character and return
2609 L959A ldb FORCOL ; use foreground colour by default
2610 tst SETFLG ; doing PRESET?
2611 bne L95A2 ; brif not
2612 ldb BAKCOL ; default to background colour
2613 L95A2 stb WCOLOR ; save working colour
2614 lda #0x55 ; consider a byte as 4 pixels
2615 mul ; now all pixels are set to the same bit pattern
2616 stb ALLCOL ; set all pixels byte
2617 rts
2618 L95AA bne L95CF ; brif graphics mode
2619 L95AC pshs x,b,a ; save registers
2620 ldx #SAMREG+8 ; point to middle of control register
2621 sta 10,x ; reset display page to 0x400
2622 sta 8,x
2623 sta 6,x
2624 sta 4,x
2625 sta 2,x
2626 sta 1,x
2627 sta -2,x
2628 sta -4,x ; reset to alpha mode
2629 sta -6,x
2630 sta -8,x
2631 lda PIA1+2 ; set VDG to alpha mode, colour set 0
2632 anda #7
2633 sta PIA1+2
2634 puls a,b,x,pc ;restore registers and return
2635 L95CF pshs x,b,a ; save registers
2636 lda PMODE ; get graphics mode
2637 adda #3 ; offset to 3-7 (we don't use the bottom 3 modes)
2638 ldb #0x10 ; shift to high 4 bits
2639 mul
2640 orb #0x80 ; set to graphics mode
2641 orb CSSVAL ; set the desired colour set
2642 lda PIA1+2 ; get get original PIA values
2643 anda #7 ; mask off VDG control
2644 pshs a ; merge with new VDG control
2645 orb ,s+
2646 stb PIA1+2 ; set new VDG mode
2647 lda BEGGRP ; get start of graphics page
2648 lsra ; divide by two - pages are on 512 byte boundaries
2649 jsr L960F ; set SAM control register
2650 lda PMODE ; get graphics mode
2651 adda #3 ; shift to VDG values
2652 cmpa #7 ; PMODE 4?
2653 bne L95F7 ; brif not
2654 deca ; treat PMODE 4 the same as PMODE 3
2655 L95F7 bsr L95FB ; program SAM's VDG bits
2656 puls a,b,x,pc ; restore registers and return
2657 L95FB ldb #3 ; set 3 bits in register
2658 ldx #SAMREG ; point to VDG control bits
2659 L9600 rora ; get bit to set
2660 bcc L9607 ; brif we need to clear the bit
2661 sta 1,x ; set the bit
2662 bra L9609
2663 L9607 sta ,x ; clear the bit
2664 L9609 leax 2,x ; move to next bit
2665 decb ; done all bits?
2666 bne L9600 ; brif not
2667 rts
2668 L960F ldb #7 ; 7 screen address bits
2669 ldx #SAMREG+6 ; point to screen address bits in SAM
2670 bra L9600 ; go program SAM bits
2671 L9616 lda PIA1+2 ; get VDG bits
2672 anda #0xf7 ; keep everything but CSS bit
2673 ora CSSVAL ; set correct CSS bit
2674 sta PIA1+2 ; set desired CSS
2675 rts
2676 ; PMODE command
2677 PMODETOK cmpa #', ; is first argument missing?
2678 beq L9650 ; brif so
2679 jsr EVALEXPB ; evaluate PMODE number
2680 cmpb #5 ; valid (0-4)?
2681 bhs L966D ; brif not
2682 lda GRPRAM ; get start of graphics memory
2683 L962E sta BEGGRP ; set start of graphics page
2684 aslb ; multiply mode by two (table has two bytes per entry)
2685 ldu #L9706+1 ; point to lookup table
2686 adda b,u ; add in number of 256 byte pages used for graphics screen
2687 cmpa TXTTAB ; does it fit?
2688 bhi L966D ; brif not
2689 sta ENDGRP ; save end of graphics
2690 leau -1,u ; point to bytes per horizontal row
2691 lda b,u ; get bytes per row
2692 sta HORBYT ; set it
2693 lsrb ; restore PMODE value
2694 stb PMODE ; set graphics mode
2695 clra ; set background colour to 0
2696 sta BAKCOL
2697 lda #3 ; set foreground colour to maximum (3)
2698 sta FORCOL
2699 jsr GETCCH ; is there a starting page number?
2700 beq L966C ; brif not
2701 L9650 jsr LB738 ; evaluate an expression following a comma
2702 tstb ; page 0?
2703 beq L966D ; brif so - not valid
2704 decb ; zero-base it
2705 lda #6 ; each graphics page is 6*256
2706 mul
2707 addb GRPRAM ; add to start of graphics memory
2708 pshs b ; save start of screen memory
2709 addb ENDGRP ; add current and address
2710 subb BEGGRP ; subtract current start (adds size of screen)
2711 cmpb TXTTAB ; does it fit?
2712 bhi L966D ; brif not
2713 stb ENDGRP ; save new end of graphics
2714 puls b ; get back start of graphics
2715 stb BEGGRP ; set start of graphics
2716 L966C rts
2717 L966D jmp LB44A ; raise FC error
2718 ; SCREEN command
2719 SCREEN cmpa #', ; is there a mode?
2720 beq L967F ; brif no mode
2721 jsr EVALEXPB ; get mode argument
2722 tstb ; set Z if alpha
2723 jsr L95AA ; set SAM/VDG for graphics mode
2724 jsr GETCCH ; is there a second argument?
2725 beq L966C ; brif not
2726 L967F jsr LB738 ; evaluate ,<expr>
2727 tstb ; colour set 0?
2728 beq L9687 ; brif so
2729 ldb #8 ; flag for colour set 1
2730 L9687 stb CSSVAL ; set colour set
2731 bra L9616 ; set up VDG
2732 ; PCLEAR command
2733 PCLEAR jsr EVALEXPB ; evaulate number of pages requested
2734 tstb ; 0?
2735 beq L966D ; brif zero - not allowed
2736 cmpb #9 ; more than 8?
2737 bhs L966D ; brif so - not allowed
2738 lda #6 ; there are 6 "pages" per graphics page
2739 mul ; now B is the number of pages to reserve
2740 addb GRPRAM ; add to start of graphics memory
2741 tfr b,a ; now A is the MSB of the start of free memory
2742 ldb #1 ; program memory always starts one above
2743 tfr d,y ; save pointer to program memory
2744 cmpd ENDGRP ; are we trying to deallocate the current graphics page?
2745 blo L966D ; brif so (note that this prevents PCLEAR 0 anyway)
2746 subd TXTTAB ; subtract out current start of basic program
2747 addd VARTAB ; add in end of program - now D is new top of program
2748 tfr d,x ; save new end of program
2749 inca ; make some extra space (for stack)
2750 subd FRETOP ; see if new top of program fits
2751 bhs L966D ; brif there isn't enough space
2752 jsr L80D0 ; adjust input pointer
2753 nop ; space filler for 1.1 patch (the JSR above)
2754 ldu VARTAB ; get end of program
2755 stx VARTAB ; save new end of program
2756 cmpu VARTAB ; is old end higher?
2757 bhs L96D4 ; brif so
2758 L96BD lda ,-u ; copy a byte upward
2759 sta ,-x
2760 cmpu TXTTAB ; at beginning?
2761 bne L96BD ; brif not
2762 sty TXTTAB ; save new start of program
2763 clr -1,y ; there must always be a NUL before the program
2764 L96CB jsr LACEF ; re-assign basic program addresses
2765 jsr LAD26 ; reset variables and stack
2766 jmp LAD9E ; return to interpretation loop
2767 L96D4 ldu TXTTAB ; get start of program
2768 sty TXTTAB ; save new start of program
2769 clr -1,y ; there must be a NUL at the start of the program
2770 L96DB lda ,u+ ; move a byte downward
2771 sta ,y+
2772 cmpy VARTAB ; at the top of the program?
2773 bne L96DB ; brif not
2774 bra L96CB ; finish up
2775 ; Graphics initialization routine - this really should be up at the start of the ROM with the
2776 ; rest of the initialization code.
2777 L96E6 ldb #0x1e ; set start of program to 0x1e00 ("PCLEAR 4")
2778 stb TXTTAB
2779 lda #6 ; graphics memory starts immediately after the screen
2780 L96EC sta GRPRAM ; set graphics memory start
2781 sta BEGGRP ; set start of current graphics page
2782 clra ; set PMODE to 0
2783 sta PMODE
2784 lda #16 ; 16 bytes per graphics row
2785 sta HORBYT
2786 lda #3 ; set foreground colour to 3
2787 sta FORCOL
2788 lda #0x0c ; set ending graphics page (for PMODE 0)
2789 sta ENDGRP
2790 ldx TXTTAB ; get start of program
2791 clr -1,x ; make sure there's a NUL before it
2792 L9703 jmp LAD19 ; do a "NEW"
2793 ; PMODE data table (bytes per row and number of 256 byte pages required for a screen)
2794 L9706 fcb 16,6 ; PMODE 0
2795 fcb 32,12 ; PMODE 1
2796 fcb 16,12 ; PMODE 2
2797 fcb 32,24 ; PMODE 3
2798 fcb 32,24 ; PMODE 4
2799 ; Calculate absolute value of vertical coordinate difference
2800 L9710 ldd VEREND ; get ending address
2801 subd VERBEG ; get difference
2802 L9714 bcc L9751 ; brif we didn't carry
2803 pshs cc ; save status (C set if start > end)
2804 jsr L9DC3 ; negate the difference to be positive
2805 puls cc,pc ; restore C and return
2806 ; Calculate absolute value of horizontal coordinate difference
2807 L971D ldd HOREND ; get end coordinate
2808 subd HORBEG ; calculate difference
2809 bra L9714 ; turn into absolute value
2810 ; PCOPY command
2811 PCOPY bsr L973F ; fetch address of the source page
2812 pshs d ; save address
2813 ldb #0xa5 ; make sure we have TO
2814 jsr LB26F
2815 bsr L973F ; fetch address of the second page
2816 puls x ; get back source
2817 tfr d,u ; put destination into a pointer
2818 ldy #0x300 ; 0x300 words to copy
2819 L9736 ldd ,x++ ; copy a word
2820 std ,u++
2821 leay -1,y ; done?
2822 bne L9736 ; brif not
2823 rts
2824 L973F jsr EVALEXPB ; evaluate page number
2825 tstb ; zero?
2826 beq L9752 ; brif invalid page number
2827 ; BUG: this should be deferred until after the address is calculated at which point it should
2828 ; be bhs instead of bhi. There should also be a check to make sure the page number is less than
2829 ; or equal to 8 above so we don't have to test for overflows below.
2830 cmpb TXTTAB ; is page number higher than start of program (BUG!)
2831 bhi L9752 ; brif so - error
2832 decb ; zero-base the page number
2833 lda #6 ; 6 "pages" per graphics page
2834 mul ; now we have proper number of "pages" for the offset
2835 addb GRPRAM ; add start of graphics memory
2836 exg a,b ; put MSB into A, 0 into B.
2837 L9751 rts
2838 L9752 jmp LB44A ; raise illegal function call
2839 ; GET command
2840 GET clrb ; GET flag
2841 bra L975A ; go on to the main body
2842 PUT ldb #1 ; PUT flag
2843 L975A stb VD8 ; save GET/PUT flag
2844 jsr RVEC22 ; do the RAM hook dance (so Disk Basic can do its thing)
2845 L975F cmpa #'@ ; @ before coordinates?
2846 bne L9765 ; brif not
2847 jsr GETNCH ; eat the @
2848 L9765 jsr L938F ; evaluate start/end coordinates
2849 jsr SYNCOMMA ; make sure we have a comma
2850 jsr L98CC ; get pointer to array
2851 tfr X,D ; save descriptor pointer
2852 ldu ,x ; get offset to next descriptor
2853 leau -2,u ; move back to array name
2854 leau d,u ; point to end of array
2855 stu VD1 ; save end of data
2856 leax 2,x ; point to number of dimensions
2857 ldb ,x ; get dimension count
2858 aslb ; two bytes per dimension size
2859 abx ; now X points to start of data
2860 stx VCF ; save start of array data
2861 lda VALTYP ; is it numeric
2862 bne L9752 ; brif not
2863 clr VD4 ; set default graphic action to PSET
2864 jsr GETCCH ; get input character
2865 beq L97B7 ; brif no action flag
2866 com VD4 ; flag action enabled
2867 jsr SYNCOMMA ; make sure there's a comma
2868 tst VD8 ; PUT?
2869 bne L979A ; brif so
2870 ldb #'G ; check for full graphics option
2871 jsr LB26F
2872 bra L97CA ; handle the rest of the process
2873 L979A ldb #5 ; 5 legal actions for PUT
2874 ldx #L9839 ; point to action table
2875 L979F ldu ,x++ ; get "clear bit" action routine
2876 ldy ,x++ ; get "set bit" action routine
2877 cmpa ,x+ ; does token match?
2878 beq L97AE ; brif so
2879 decb ; checked all?
2880 bne L979F ; brif not
2881 jmp LB277 ; raise error
2882 L97AE sty VD5 ; save set bit action address
2883 stu VD9 ; save clear bit action address
2884 jsr GETNCH ; munch the acton token
2885 bra L97CA ; handle rest of process
2886 L97B7 ldb #0xf8 ; mask for bottom three bits
2887 lda PMODE ; get graphics mode
2888 rora ; odd number mode?
2889 bcc L97C0 ; brif even
2890 ldb #0xfc ; bottom 2 bits mask
2891 L97C0 tfr b,a ; save mask
2892 andb HORBEG+1 ; round down the start address
2893 stb HORBEG+1
2894 anda HOREND+1 ; round down end address
2895 sta HOREND+1
2896 L97CA jsr L971D ; get horizontal size
2897 bcc L97D3 ; brif end > start
2898 ldx HOREND ; switch end in for start
2899 stx HORBEG
2900 L97D3 std HOREND ; save size
2901 jsr L9710 ; calculate vertical size
2902 bcc L97DE ; brif end > start
2903 ldx VEREND ; swap in vertical end for the start
2904 stx VERBEG
2905 L97DE std VEREND ; save vertical size
2906 lda PMODE ; get graphics mode
2907 rora ; even?
2908 ldd HOREND ; get difference
2909 bcc L97EB ; brif even (2 colour)
2910 addd HOREND ; add in size (double it)
2911 std HOREND ; save adjusted end size
2912 L97EB jsr L9420 ; normalize differences
2913 ldd HOREND ; get end coord
2914 ldx VEREND ; get end size
2915 leax 1,x ; make vertical size inclusive
2916 stx VEREND ; save it back
2917 tst VD4 ; got "G" or GET action
2918 bne L9852 ; brif given
2919 lsra ; we're going for whole bytes here
2920 rorb
2921 lsra
2922 rorb
2923 lsra
2924 rorb
2925 addd #1 ; make it inclusive
2926 std HOREND ; save new coordinate
2927 jsr L9298 ; convert to screen address
2928 L9808 ldb HOREND+1 ; get horizontal size
2929 pshs x ; save screen position
2930 L980C tst VD8 ; get/put flag
2931 beq L9831 ; brif get
2932 bsr L9823 ; bump array data pointer
2933 lda ,u ; copy data from array to screen
2934 sta ,x+
2935 L9816 decb ; are we done the row?
2936 bne L980C ; brif not
2937 puls x ; get screen address
2938 jsr L92E9 ; move to next row
2939 dec VEREND+1 ; done?
2940 bne L9808 ; brif not
2941 L9822 rts
2942 L9823 ldu VCF ; get array data location
2943 leau 1,u ; bump it
2944 stu VCF ; save new array data location
2945 cmpu VD1 ; did we hit the end of the array?
2946 bne L9822 ; brif not
2947 L982E jmp LB44A ; raise function call error
2948 L9831 lda ,x+ ; get data from screen
2949 bsr L9823 ; bump array data pointer
2950 sta ,u ; put data in array
2951 bra L9816 ; do the loopy thing
2952 ; PUT actions
2953 L9839 fdb L9894,L989B ; PSET
2954 fcb 0xbd
2955 fdb L989B,L9894 ; PRESET
2956 fcb 0xbe
2957 fdb L98B1,L989B ; OR
2958 fcb 0xb1
2959 fdb L9894,L98B1 ; AND
2960 fcb 0xb0
2961 fdb L98A1,L98A1 ; NOT
2962 fcb 0xa8
2963 L9852 addd #1 ; add to horiz difference
2964 std HOREND ; save it
2965 lda VD8 ; PUT?
2966 bne L9864 ; brif so
2967 ldu VD1 ; get end of array
2968 L985D sta ,-u ; zero out a byte
2969 cmpu VCF ; done?
2970 bhi L985D ; brif not
2971 L9864 jsr L9298 ; get screen address
2972 ldb PMODE ; get graphics mode
2973 rorb ; even?
2974 bcc L986E ; brif so
2975 anda #0xaa ; use as pixel mask for 4 colour mode
2976 L986E ldb #1 ; set bit probe
2977 ldy VCF ; point to start of array data
2978 L9873 pshs x,a ; save screen address
2979 ldu HOREND ; get horizontal size
2980 L9877 pshs u,a ; save horizontal size and pixel mask
2981 lsrb ; move bit probe right
2982 bcc L9884 ; brif we didn't fall off a byte
2983 rorb ; shift carry back in on the left
2984 leay 1,y ; move ahead a byte in the array
2985 cmpy VD1 ; end of array data?
2986 beq L982E ; raise error if so
2987 L9884 tst VD8 ; PUT?
2988 beq L98A7 ; brif not
2989 bitb ,y ; test bit in array
2990 beq L9890 ; brif not set
2991 jmp [VD5] ; do action routine for bit set
2992 L9890 jmp [VD9] ; do action routine for bit clear
2993 L9894 coma ; invert mask
2994 anda ,x ; read screen data and reset the desired bit
2995 sta ,x ; save on screen
2996 bra L98B1
2997 L989B ora ,x ; merge pixel mask with screen data (turn on bit)
2998 sta ,x ; save on screen
2999 bra L98B1
3000 L98A1 eora ,x ; invert the pixel in the screen data
3001 sta ,x ; save on screen
3002 bra L98B1
3003 L98A7 bita ,x ; is the bit set?
3004 beq L98B1 ; brif not - do nothing
3005 tfr b,a ; get bit probe
3006 ora ,y ; turn on proper bit in data
3007 sta ,y
3008 L98B1 puls a,u ; get back array address
3009 jsr L92ED ; move screen address to the right
3010 leau -1,u ; account for consumed pixel
3011 cmpu ZERO ; done yet?
3012 bne L9877 ; brif not
3013 ldx 1,s ; get start of row back
3014 lda HORBYT ; get number of bytes per row
3015 leax a,x ; move ahead one line
3016 puls a ; get back screen pixel mask
3017 leas 2,s ; lose the screen pointer
3018 dec VEREND+1 ; done all rows?
3019 bne L9873 ; brif not
3020 rts
3021 L98CC jsr LB357 ; evaluate a variable
3022 ldb ,-x ; get variable name
3023 lda ,-x
3024 tfr d,u ; save it
3025 ldx ARYTAB ; get start of arrays
3026 L98D7 cmpx ARYEND ; end of arrays?
3027 lbeq LB44A ; brif not found
3028 cmpu ,x ; correct variable?
3029 beq L98E8 ; brif so
3030 ldd 2,x ; get array size
3031 leax d,x ; move to next array
3032 bra L98D7 ; check this array
3033 L98E8 leax 2,x ; move pointer to the array header
3034 rts ; obviously this rts is not needed
3035 L98EB rts
3036 ; PAINT command
3037 PAINT cmpa #'@ ; do we have @ before coords?
3038 bne L98F2 ; brif not
3039 jsr GETNCH ; eat the @
3040 L98F2 jsr L93B2 ; evaluate coordinates
3041 jsr L931D ; normalize coordinates
3042 lda #1 ; PSET flag (use working colour)
3043 sta SETFLG
3044 jsr L9581 ; parse colour and set working colour, etc.
3045 ldd WCOLOR ; get working colour and all pixels byte
3046 pshs d ; save them
3047 jsr GETCCH ; is there anything else?
3048 beq L990A ; brif not
3049 jsr L9581 ; evaluate border colour
3050 L990A lda ALLCOL ; get border colour all pixel byte
3051 sta VD8 ; save border colour pixel byte
3052 puls d ; get back working colour details
3053 std WCOLOR
3054 clra ; store a "stop" frame on the stack so PAINT knows when it's finished unwinding
3055 pshs u,x,b,a
3056 jsr L9522 ; set up starting coordinates
3057 jsr L928F ; point to pixel mask routine
3058 stu VD9 ; save pixel mask routine
3059 jsr L99DF ; paint from current horizontal coordinate to zero (left)
3060 beq L9931 ; brif hit border immediately
3061 jsr L99CB ; paint from current horizontal coordinate upward (right)
3062 lda #1 ; set direction to "down"
3063 sta VD7
3064 jsr L99BA ; save "down" frame
3065 neg VD7 ; set direction to "up"
3066 jsr L99BA ; save "up" frame
3067 L9931 sts TMPSTK ; save stack pointer
3068 L9934 tst CHGFLG ; did the paint change anything?
3069 bne L993B ; brif so
3070 lds TMPSTK ; get back stack pointer
3071 L993B puls a,b,x,u ; get frame from stack
3072 clr CHGFLG ; mark nothing changed
3073 sts TMPSTK ; save stack pointer
3074 leax 1,x ; move start coordinate right
3075 stx HORBEG ; save new coordinate
3076 stu VD1 ; save length of line
3077 sta VD7 ; save up/down flag
3078 beq L98EB ; did we hit the "stop" frame?
3079 bmi L9954 ; brif negative going (up)?
3080 incb ; bump vertical coordinate
3081 cmpb VD6 ; at end?
3082 bls L9958 ; brif not
3083 clrb ; set vertical to 0 (wrap around)
3084 L9954 tstb ; did we wrap?
3085 beq L9934 ; do another block if so
3086 decb ; move up a row
3087 L9958 stb VERBEG+1 ; save vertical coordinate
3088 jsr L99DF ; paint from horizontal to 0
3089 beq L996E ; brif we hit the border immediately
3090 cmpd #3 ; less than 3 pixels?
3091 blo L9969 ; brif so
3092 leax -2,x ; move two pixels left
3093 bsr L99A1 ; save paint block on the stack
3094 L9969 jsr L99CB ; continue painting to the right
3095 L996C bsr L99BA ; save paint data frame
3096 L996E coma ; complement length of line just painted and add to length of line
3097 comb
3098 L9970 addd VD1 ; save difference between this line and parent line
3099 std VD1
3100 ble L998C ; brif parent line is shorter
3101 jsr L9506 ; bump horizontal coordinate
3102 jsr L9A12 ; see if we bounced into the border
3103 bne L9983 ; brif not border
3104 ldd #-1 ; move left
3105 bra L9970 ; keep looking
3106 L9983 jsr L9514 ; move horizontally left
3107 bsr L99C6 ; save horizontal coordinate
3108 bsr L99E8 ; paint right
3109 bra L996C ; save paint block and do more
3110 L998C jsr L9506 ; bump horizontal coordinate
3111 leax d,x ; point to right end of parent line
3112 stx HORBEG ; set as curent coordinate
3113 coma ; get amount we extend past parent line
3114 comb
3115 subd #1
3116 ble L999E ; brif doesn't extend
3117 tfr d,x ; save length of line
3118 bsr L99A1 ; save paint frame
3119 L999E jmp L9934
3120 L99A1 std VCB ; save number of pixels painted
3121 puls y ; get return address
3122 ldd HORBEG ; get horizontal coordinate
3123 pshs x,b,a ; save horizontal coordinate and pointer
3124 lda VD7 ; get up/down flag
3125 nega ; reverse it
3126 L99AC ldb VERBEG+1 ; get vertical coordainte
3127 pshs b,a ; save vertical coord and up/down flag
3128 pshs y ; put return address back
3129 ldb #2 ; make sure we haven't overflowed memory
3130 jsr LAC33
3131 ldd VCB ; get line length back
3132 rts
3133 L99BA std VCB ; save length of painted line
3134 puls y ; get return address
3135 ldd HOREND ; get start coord
3136 pshs x,b,a ; save horizontal start and length
3137 lda VD7 ; get up/down flag
3138 bra L99AC ; finish up with the stack
3139 L99C6 ldx HORBEG ; save current horizontal coord and save it
3140 stx HOREND
3141 rts
3142 L99CB std VCD ; save number of pixels painted
3143 ldy HOREND ; get last horizontal start
3144 bsr L99C6 ; save current coordinate
3145 sty HORBEG ; save coordinate
3146 bsr L99E8 ; paint a line
3147 ldx VCD ; get number painted
3148 leax d,x ; add to the number painted going the other way
3149 addd #1 ; now D is length of line
3150 rts
3151 L99DF jsr L99C6 ; put starting coordinate in end
3152 ldy #L9514 ; decrement horizontal coordinate address
3153 bra L99EE ; go paint line
3154 L99E8 ldy #L9506 ; increment horizontal coordinate address
3155 jsr ,y ; bump coordinate
3156 L99EE ldu ZERO ; initialize pixel count
3157 ldx HORBEG ; get starting coordinate
3158 L99F2 bmi L9A0B ; brif out of range for hoizontal coordinate
3159 cmpx VD3 ; at end?
3160 bhi L9A0B ; brif right of max
3161 pshs u,y ; save counter and inc/dec routine pointer
3162 bsr L9A12 ; at border?
3163 beq L9A09 ; brif so
3164 jsr L9377 ; set pixel to paint colour
3165 puls y,u ; restore counter and inc/dec/pointer
3166 leau 1,u ; bump number of painted pixels
3167 jsr ,y ; inc/dec screen address
3168 bra L99F2 ; go do another pixel
3169 L9A09 puls y,u ; get back counter and inc/dec routine
3170 L9A0B tfr u,d ; save count in D
3171 tfr d,x ; and in X
3172 subd ZERO ; set flags on D (smaller/faster than cmpd ZERO)
3173 rts
3174 L9A12 jsr [VD9] ; get the screen address
3175 tfr a,b ; save pixel mask
3176 andb VD8 ; set pixel to border colour
3177 pshs b,a ; save mask and border
3178 anda ,x ; mask current pixel into A
3179 cmpa 1,s ; does it match border? Z=1 if so
3180 puls a,b,pc ; restore mask, border pixel, and return
3181 ; PLAY command
3182 ; This is here mixed in with the graphics package because it shares some machinery with DRAW.
3183 PLAY ldx ZERO ; default values for note length, etc.
3184 ldb #1
3185 pshs x,b ; save default values
3186 jsr LB156 ; evaluate argument
3187 clrb ; enable DA and sound output
3188 jsr LA9A2
3189 jsr LA976
3190 L9A32 jsr LB654 ; fetch PLAY string details
3191 bra L9A39 ; go evaluate the string
3192 L9A37 puls b,x ; get back play string details
3193 L9A39 stb VD8 ; save length of string
3194 beq L9A37 ; brif end of string
3195 stx VD9 ; save start of string
3196 lbeq LA974 ; brif NULL string - disable sound and return
3197 L9A43 tst VD8 ; have anything left?
3198 beq L9A37 ; brif not
3199 jsr L9B98 ; get command character
3200 cmpa #'; ; command separator?
3201 beq L9A43 ; brif so - ignore it
3202 cmpa #'' ; '?
3203 beq L9A43 ; brif so - ignore it
3204 cmpa #'X ; execuate sub string?
3205 lbeq L9C0A ; brif so - handle it
3206 bsr L9A5C ; handle other commands
3207 bra L9A43 ; look for more stuff
3208 L9A5C cmpa #'O ; octave?
3209 bne L9A6D ; brif not
3210 ldb OCTAVE ; get current octave
3211 incb ; 1-base it
3212 bsr L9AC0 ; get value if present
3213 decb ; zero-base it
3214 cmpb #4 ; valid octave?
3215 bhi L9ACD ; raise error if not
3216 stb OCTAVE ; save new octave
3217 rts
3218 L9A6D cmpa #'V ; volume?
3219 bne L9A8B ; brif not
3220 ldb VOLHI ; get current high volume limit
3221 lsrb ; shift 2 bits right (DA is 6 bits in high bits)
3222 lsrb
3223 subb #31 ; subtract out mid value offset
3224 bsr L9AC0 ; read argument
3225 cmpb #31 ; maximum range is 31
3226 bhi L9ACD ; brif out of range
3227 aslb ; adjust back in range
3228 aslb
3229 pshs b ; save new volume
3230 ldd #0x7e7e ; midrange value for both high and low
3231 adda ,s ; add new volume to high limit
3232 subb ,s+ ; subtract volume from low limit
3233 std VOLHI ; save new volume limits (sets high and low amplitudes)
3234 rts
3235 L9A8B cmpa #'L ; note length?
3236 bne L9AB2 ; brif not
3237 ldb NOTELN ; get current length
3238 bsr L9AC0 ; read parameter
3239 tstb ; resulting length 0?
3240 beq L9ACD ; brif so - problem
3241 stb NOTELN ; save new length
3242 clr DOTVAL ; reset note timer scale factor
3243 L9A9A bsr L9A9F ; check for dot
3244 bcc L9A9A ; brif there was one
3245 rts
3246 L9A9F tst VD8 ; check length
3247 beq L9AAD ; brif zero
3248 jsr L9B98 ; get command character
3249 cmpa #'. ; dot?
3250 beq L9AAF ; brif so
3251 jsr L9BE2 ; move input back and bump length
3252 L9AAD coma ; set C to indicate nothing found
3253 rts
3254 L9AAF inc DOTVAL ; bump number of dots
3255 rts
3256 L9AB2 cmpa #'T ; tempo?
3257 bne L9AC3 ; brif not
3258 ldb TEMPO ; get current tempo
3259 bsr L9AC0 ; parse tempo argument
3260 tstb ; 0?
3261 beq L9ACD ; brif so - invalid
3262 stb TEMPO ; save new tempo
3263 rts
3264 L9AC0 jmp L9BAC ; evaluate various operators
3265 L9AC3 cmpa #'P ; pause?
3266 bne L9AEB ; brif not
3267 jsr L9CCB ; evaluate parameter
3268 tstb ; is the pause number 0?
3269 bne L9AD0 ; brif not
3270 L9ACD jmp LB44A ; raise FC error
3271 L9AD0 lda DOTVAL ; save current volume and note scale
3272 ldx VOLHI
3273 pshs x,a
3274 lda #0x7e ; drop DA to mid range
3275 sta VOLHI
3276 sta VOLLOW
3277 clr DOTVAL
3278 bsr L9AE7 ; go play a "silence"
3279 puls a,x ; restore volume and note scale
3280 sta DOTVAL
3281 stx VOLHI
3282 rts
3283 L9AE7 clr ,-s ; set not number 0
3284 bra L9B2B ; go play it
3285 L9AEB cmpa #'N ; N for "note"?
3286 bne L9AF2 ; brif not - it's optional
3287 jsr L9B98 ; skip the "N"
3288 L9AF2 cmpa #'A ; is it a valid note?
3289 blo L9AFA ; brif not
3290 cmpa #'G ; is it above the note range?
3291 bls L9AFF ; brif not - valid note
3292 L9AFA jsr L9BBE ; evaluate a number
3293 bra L9B22 ; process note value
3294 L9AFF suba #'A ; normalize note number to 0
3295 ldx #L9C5B ; point to note number lookup table
3296 ldb a,x ; get not number
3297 tst VD8 ; any command characters left?
3298 beq L9B22 ; brif not
3299 jsr L9B98 ; get character
3300 cmpa #'# ; sharp?
3301 beq L9B15 ; brif so
3302 cmpa #'+ ; also sharp?
3303 bne L9B18 ; brif not
3304 L9B15 incb ; add one half tone
3305 bra L9B22
3306 L9B18 cmpa #'- ; flat?
3307 bne L9B1F ; brif not
3308 decb ; subtract one half tone
3309 bra L9B22
3310 L9B1F jsr L9BE2 ; back up command pointer
3311 L9B22 decb ; adjust note number (zero base it)
3312 cmpb #11 ; is it valid?
3313 bhi L9ACD ; raise error if not
3314 pshs b ; save note value
3315 ldb NOTELN ; get note length
3316 L9B2B lda TEMPO ; get tempo value
3317 mul ; calculate note duration
3318 std VD5 ; save duration
3319 leau 1,s ; point to where the stack goes after we're done
3320 lda OCTAVE ; get current octave
3321 cmpa #1 ; 0 or 1?
3322 bhi L9B64 ; brif not
3323 ldx #L9C62 ; point to delay table
3324 ldb #2*12 ; 24 bytes per octave
3325 mul ; now we have the base address
3326 abx ; now X points to the octave base
3327 puls b ; get back note value
3328 aslb ; two bytes per delay
3329 abx ; now we're pointing to the delay
3330 leay ,x ; save pointer to note value
3331 bsr L9B8C ; calculate note timer value
3332 std PLYTMR ; set timer for note playing (IRQ will count this down)
3333 L9B49 bsr L9B57 ; set to mid range and delay
3334 lda VOLHI ; get high value
3335 bsr L9B5A ; set to high value and delay
3336 bsr L9B57 ; set to mid range and delay
3337 lda VOLLOW ; get low value
3338 bsr L9B5A ; set to low value and delay
3339 bra L9B49 ; do it again (IRQ will break the loop)
3340 L9B57 lda #0x7e ; mid value for DA with RS232 marking
3341 nop ; a delay to fine tune frequencies
3342 L9B5A sta PIA1 ; set DA
3343 ldx ,y ; get delay value
3344 L9B5F leax -1,x ; count down
3345 bne L9B5F ; brif not done yet
3346 rts
3347 L9B64 ldx #L9C92-2*12 ; point to delay table for octaves 2+
3348 ldb #12 ; 12 bytes per octave
3349 mul ; now we have the offset to the desired octave
3350 abx ; now we point to the start of the octave
3351 puls b ; get back note value
3352 abx ; now we point to the delay value
3353 bsr L9B8C ; calculate timer value
3354 std PLYTMR ; set play timer (IRQ counts this down)
3355 L9B72 bsr L9B80 ; send mid value and delay
3356 lda VOLHI ; get high value
3357 bsr L9B83 ; send high value and delay
3358 bsr L9B80 ; send low value and delay
3359 lda VOLLOW ; get low value
3360 bsr L9B83 ; send low value and delay
3361 bra L9B72 ; do it again (IRQ will break the loop)
3362 L9B80 lda #0x7e ; mid range value with RS232 marking
3363 nop ; fine tuning delay
3364 L9B83 sta PIA1 ; set DA
3365 lda ,x ; get delay value
3366 L9B88 deca ; count down
3367 bne L9B88 ; brif not done
3368 rts
3369 L9B8C ldb #0xff ; base timer value
3370 lda DOTVAL ; get number of dots
3371 beq L9B97 ; use default value if 0
3372 adda #2 ; add in constant timer factor
3373 mul ; multiply scale by base
3374 lsra ; divide by two - each increment will increase note timer by 128
3375 rorb
3376 L9B97 rts
3377 L9B98 pshs x ; save register
3378 L9B9A tst VD8 ; do we have anything left?
3379 beq L9BEB ; brif not - raise error
3380 ldx VD9 ; get parsing address
3381 lda ,x+ ; get character
3382 stx VD9 ; save pointer
3383 dec VD8 ; account for character consumed
3384 cmpa #0x20 ; space?
3385 beq L9B9A ; brif so - skip it
3386 puls x,pc ; restore register and return
3387 L9BAC bsr L9B98 ; get character
3388 cmpa #'+ ; add one?
3389 beq L9BEE ; brif so
3390 cmpa #'- ; subtract one?
3391 beq L9BF2 ; brif so
3392 cmpa #'> ; double?
3393 beq L9BFC ; brif so
3394 cmpa #'< ; halve?
3395 beq L9BF7 ; brif so
3396 L9BBE cmpa #'= ; variable equate?
3397 beq L9C01 ; brif so
3398 jsr L90AA ; clear carry if numeric
3399 bcs L9BEB ; brif not numeric
3400 clrb ; initialize value to 0
3401 L9BC8 suba #'0 ; remove ASCII bias
3402 sta VD7 ; save digit
3403 lda #10 ; make room for digit
3404 mul
3405 tsta ; did we overflow 8 bits?
3406 bne L9BEB ; brif so
3407 addb VD7 ; add in digit
3408 bcs L9BEB ; brif that overflowed
3409 tst VD8 ; more digits?
3410 beq L9BF1 ; brif not
3411 jsr L9B98 ; get character
3412 jsr L90AA ; clear carry if numeric
3413 bcc L9BC8 ; brif another digit
3414 L9BE2 inc VD8 ; unaccount for character just read
3415 ldx VD9 ; move pointer back
3416 leax -1,x
3417 stx VD9
3418 rts
3419 L9BEB jmp LB44A ; raise FC error
3420 L9BEE incb ; bump param
3421 beq L9BEB ; brif overflow
3422 L9BF1 rts
3423 L9BF2 tstb ; already zero?
3424 beq L9BEB ; brif so - underflow
3425 decb ; decrease parameter
3426 rts
3427 L9BF7 tstb ; already at 0?
3428 beq L9BEB ; brif so - raise error
3429 lsrb ; halve it
3430 rts
3431 L9BFC tstb ; will it overflow?
3432 bmi L9BEB ; brif so
3433 aslb ; double it
3434 rts
3435 L9C01 pshs u,y ; save registers
3436 bsr L9C1B ; interpret command string as a variable
3437 jsr LB70E ; convert it to an 8 bit number
3438 puls y,u,pc ; restore registers and return
3439 L9C0A jsr L9C1B ; evaluate expression in command string
3440 ldb #2 ; room for 4 bytes?
3441 jsr LAC33
3442 ldb VD8 ; get the command length and pointer
3443 ldx VD9
3444 pshs x,b ; save them
3445 jmp L9A32 ; go process the sub string
3446 L9C1B ldx VD9 ; get command pointer
3447 pshs x ; save it
3448 jsr L9B98 ; get input character
3449 jsr LB3A2 ; set carry if not alpha
3450 bcs L9BEB ; brif not a variable reference
3451 L9C27 jsr L9B98 ; get command character
3452 cmpa #'; ; semicolon?
3453 bne L9C27 ; keep scanning if not
3454 puls x ; get back start of variable string
3455 ldu CHARAD ; get current interpreter input pointer
3456 pshs u ; save it
3457 stx CHARAD ; point interpreter at command string
3458 jsr LB284 ; evaluate expression as string
3459 puls x ; restore interpeter input pointer
3460 stx CHARAD
3461 rts
3462 ; The bit of Extended Basic's IRQ routine that handles PLAY. Note that everything after
3463 ; clr PLYTMR+1 could be replaced with a simple lds 8,s followed by rts.
3464 L9C3E clra ; make sure DP is set to 0
3465 tfr a,dp
3466 ldd PLYTMR ; is PLAY running?
3467 lbeq LA9BB ; brif not - transfer control on the Color Basic's routine
3468 subd VD5 ; subtract out the interval
3469 std PLYTMR ; save new timer value
3470 bhi L9C5A ; brif it isn't <= 0
3471 clr PLYTMR ; disable the timer
3472 clr PLYTMR+1
3473 puls a ; get saved CC
3474 lds 7,s ; set stack to saved U value
3475 anda #0x7f ; clear E flag (to return minimal state)
3476 pshs a ; set fake "FIRQ" stack frame
3477 L9C5A rti
3478 L9C5B fcb 10,12,1,3,5,6,8 ; table of half tone numbers for notes A-G
3479 L9C62 fdb 0x01a8,0x0190,0x017a,0x0164 ; delays for octave 1
3480 fdb 0x0150,0x013d,0x012b,0x011a
3481 fdb 0x010a,0x00fb,0x00ed,0x00df
3482 fdb 0x00d3,0x00c7,0x00bb,0x00b1 ; delays for octave 2
3483 fdb 0x00a6,0x009d,0x0094,0x008b
3484 fdb 0x0083,0x007c,0x0075,0x006e
3485 L9C92 fcb 0xa6,0x9c,0x93,0x8b ; delays for octave 3
3486 fcb 0x83,0x7b,0x74,0x6d
3487 fcb 0x67,0x61,0x5b,0x56
3488 fcb 0x51,0x4c,0x47,0x43 ; delays for octave 4
3489 fcb 0x3f,0x3b,0x37,0x34
3490 fcb 0x31,0x2e,0x2b,0x28
3491 fcb 0x26,0x23,0x21,0x1f ; delays for octave 5
3492 fcb 0x1d,0x1b,0x19,0x18
3493 fcb 0x16,0x14,0x13,0x12
3494 ; DRAW command
3495 DRAW ldx ZERO ; create an empty "DRAW" frame
3496 ldb #1
3497 pshs x,b
3498 stb SETFLG ; set to "PSET" mode
3499 stx VD5 ; clear update and draw flag
3500 jsr L959A ; set active colour byte
3501 jsr LB156 ; evaluate command string
3502 L9CC6 jsr LB654 ; fetch command string details
3503 bra L9CD3 ; interpret the command string
3504 L9CCB jsr L9B98 ; fetch command character
3505 jmp L9BBE ; evaluate a number
3506 L9CD1 puls b,x ; get previously saved command string
3507 L9CD3 stb VD8 ; save length counter
3508 beq L9CD1 ; brif end of string
3509 stx VD9 ; save pointer
3510 lbeq L9DC7 ; brif overall end of command
3511 L9CDD tst VD8 ; are we at the end of the string?
3512 beq L9CD1 ; brif so - return to previous string
3513 jsr L9B98 ; get command character
3514 cmpa #'; ; semicolon?
3515 beq L9CDD ; brif so - ignore it
3516 cmpa #'' ; '?
3517 beq L9CDD ; brif so - ignore that too
3518 cmpa #'N ; update position toggle?
3519 bne L9CF4 ; brif not
3520 com VD5 ; toggle update position flag
3521 bra L9CDD ; get on for another command
3522 L9CF4 cmpa #'B ; blank flag?
3523 bne L9CFC ; brif not
3524 com VD6 ; toggle blank flag
3525 bra L9CDD ; get on for another command
3526 L9CFC cmpa #'X ; substring?
3527 lbeq L9D98 ; brif so - execute command
3528 cmpa #'M ; move draw position?
3529 lbeq L9E32 ; brif so
3530 pshs a ; save command character
3531 ldb #1 ; default value if no number follows
3532 tst VD8 ; is there something there?
3533 beq L9D21 ; brif not
3534 jsr L9B98 ; get character
3535 jsr LB3A2 ; set C if not alpha
3536 pshs cc ; save alpha state
3537 jsr L9BE2 ; move back pointer
3538 puls cc ; get back alpha flag
3539 bcc L9D21 ; brif it's alpha
3540 bsr L9CCB ; evaluate a number
3541 L9D21 puls a ; get command back
3542 cmpa #'C ; color change?
3543 beq L9D4F ; brif so
3544 cmpa #'A ; angle?
3545 beq L9D59 ; brif so
3546 cmpa #'S ; scale?
3547 beq L9D61 ; brif so
3548 cmpa #'U ; up?
3549 beq L9D8F ; brif so
3550 cmpa #'D ; down?
3551 beq L9D8C ; brif so
3552 cmpa #'L ; left?
3553 beq L9D87 ; brif so
3554 cmpa #'R ; right?
3555 beq L9D82 ; brif so
3556 suba #'E ; normalize the half cardinals to 0
3557 beq L9D72 ; brif E (45°)
3558 deca ; F (135°?)
3559 beq L9D6D ; brif so
3560 deca ; G (225°?)
3561 beq L9D7B ; brif so
3562 deca ; H (315°?)
3563 beq L9D69 ; brif so
3564 L9D4C jmp LB44A ; raise FC error
3565 L9D4F jsr L955D ; adjust colour for PMODE
3566 stb FORCOL ; save new foreground colour
3567 jsr L959A ; set up working colour and all pixels byte
3568 L9D57 bra L9CDD ; go process another command
3569 L9D59 cmpb #4 ; only 3 angles are valid
3570 bhs L9D4C ; brif not valid
3571 stb ANGLE ; save new angle
3572 bra L9D57 ; go process another command
3573 L9D61 cmpb #63 ; only 64 scale values are possible
3574 bhs L9D4C ; brif out of range
3575 stb SCALE ; save new scale factor
3576 bra L9D57 ; go process another command
3577 L9D69 clra ; make horizontal negative
3578 bsr L9DC4
3579 skip1
3580 L9D6D clra ; keep horizontal distance positive
3581 tfr d,x ; make horizontal distance and vertical distance the same
3582 bra L9DCB ; go do the draw thing
3583 L9D72 clra ; zero extend horizontal distance
3584 tfr d,x ; set it as vertical
3585 bsr L9DC4 ; negate horizontal distance
3586 exg d,x ; swap directions (vertical is now negative)
3587 bra L9DCB ; go do the draw thing
3588 L9D7B clra ; zero extend horizontal distance
3589 tfr d,x ; copy horizontal to vertical
3590 bsr L9DC4 ; negate horizontal
3591 bra L9DCB ; go do the drawing thing
3592 L9D82 clra ; zero extend horizontal distance
3593 L9DB3 ldx ZERO ; no vertical distance
3594 bra L9DCB ; go do the drawing things
3595 L9D87 clra ; zero extend horizontal
3596 bsr L9DC4 ; negate horizontal
3597 bra L9DB3 ; zero out vertical and do the drawing thing
3598 L9D8C clra ; zero extend distance
3599 bra L9D92 ; make the distance vertical and zero out horizontal
3600 L9D8F clra ; zero extend distance
3601 bsr L9DC4 ; negate distance
3602 L9D92 ldx ZERO ; zero out vertical distance
3603 exg x,d ; swap vertical and horizontal
3604 bra L9DCB ; go do the drawing thing
3605 L9D98 jsr L9C1B ; evaluate substring expression
3606 ldb #2 ; is there enough room for the state?
3607 jsr LAC33
3608 ldb VD8 ; save current command string state
3609 ldx VD9
3610 pshs x,b
3611 jmp L9CC6 ; go evaluate the sub string
3612 L9DA9 ldb SCALE ; get scale factor
3613 beq L9DC8 ; brif zero - default to full size
3614 clra ; zero extend
3615 exg d,x ; put distance somewhere useful
3616 sta ,-s ; save MS of distance
3617 bpl L9DB6 ; brif positive distance
3618 bsr L9DC3 ; negate the distance
3619 L9DB6 jsr L9FB5 ; multiply D and X
3620 tfr u,d ; save ms bytes in D
3621 lsra ; divide by 2
3622 rorb
3623 L9DBD lsra ; ...divide by 4
3624 rorb
3625 tst ,s+ ; negative distance?
3626 bpl L9DC7 ; brif it was positive
3627 L9DC3 nega ; negate D
3628 L9DC4 negb
3629 sbca #0
3630 L9DC7 rts
3631 L9DC8 tfr x,d ; copy unchanged sitance to D
3632 rts
3633 L9DCB pshs b,a ; save horizontal distance
3634 bsr L9DA9 ; apply scale factor to vertical
3635 puls x ; get horizontal distance
3636 pshs b,a ; save scaled vertical
3637 bsr L9DA9 ; apply scale to horizontal
3638 puls x ; get back vertical distance
3639 ldy ANGLE ; get draw angle and scale
3640 pshs y ; save them
3641 L9DDC tst ,s ; is there an angle?
3642 beq L9DE8 ; brif no angle
3643 exg x,d ; swap distances
3644 bsr L9DC3 ; negate D
3645 dec ,s ; account for one tick around the rotation
3646 bra L9DDC ; see if we're there yet
3647 L9DE8 puls y ; get angle and scale back
3648 ldu ZERO ; default end position (horizontal) is 0
3649 addd HORDEF ; add default horizontal to horizontal distance
3650 bmi L9DF2 ; brif we went negative
3651 tfr d,u ; save calculated end coordindate
3652 L9DF2 tfr x,d ; get vertical distance somewhere useful
3653 ldx ZERO ; default vertical end is 0
3654 addd VERDEF ; add distance to default vertical start
3655 bmi L9DFC ; brif negative - use 0
3656 tfr d,x ; save calculated end coordinate
3657 L9DFC cmpu #256 ; is horizontal in range?
3658 blo L9E05 ; brif su
3659 ldu #255 ; maximize it
3660 L9E05 cmpx #192 ; is vertical in range?
3661 blo L9E0D ; brif so
3662 ldx #191 ; maximize it
3663 L9E0D ldd HORDEF ; set starting coordinates for the line
3664 std HORBEG
3665 ldd VERDEF
3666 std VERBEG
3667 stx VEREND ; set end coordinates
3668 stu HOREND
3669 tst VD5 ; are we updating position?
3670 bne L9E21 ; brif not
3671 stx VERDEF ; update default coordinates
3672 stu HORDEF
3673 L9E21 jsr L9420 ; normalize coordindates
3674 tst VD6 ; are we drawing something?
3675 bne L9E2B ; brif not
3676 jsr L94A1 ; draw the line
3677 L9E2B clr VD5 ; reset draw and update flags
3678 clr VD6
3679 jmp L9CDD ; do another command
3680 L9E32 jsr L9B98 ; get a command character
3681 pshs a ; save it
3682 jsr L9E5E ; evaluate horizontal distance
3683 pshs b,a ; save it
3684 jsr L9B98 ; get character
3685 cmpa #', ; comma between coordinates?
3686 lbne L9D4C ; brif not - raise error
3687 jsr L9E5B ; evaluate vertical distance
3688 tfr d,x ; save vertical distance
3689 puls u ; get horizontal distance
3690 puls a ; get back first command character
3691 cmpa #'+ ; was it + at start?
3692 beq L9E56 ; brif +; treat values as positive
3693 cmpa #'- ; was it -?
3694 bne L9DFC ; brif not - treat it as absolute
3695 L9E56 tfr u,d ; put horizontal distance somewhere useful
3696 jmp L9DCB ; move draw position (relative)
3697 L9E5B jsr L9B98 ; get input character
3698 L9E5E cmpa #'+ ; leading +?
3699 beq L9E69 ; brif so
3700 cmpa #'- ; leading -?
3701 beq L9E6A ; brif so - negative
3702 jsr L9BE2 ; move pointer back one
3703 L9E69 clra ; 0 for +, nonzero for -
3704 L9E6A pshs a ; save sign flag
3705 jsr L9CCB ; evaluate number
3706 puls a ; get sign flag
3707 tsta ; negative?
3708 beq L9E78 ; brif not
3709 clra ; zero extend and negate
3710 negb
3711 sbca #0
3712 L9E78 rts
3713 ; Table of sines and cosines for CIRCLE
3714 L9E79 fdb 0x0000,0x0001 ; subarc 0
3715 fdb 0xfec5,0x1919 ; subarc 1
3716 fdb 0xfb16,0x31f2 ; subarc 2
3717 fdb 0xf4fb,0x4a51 ; subarc 3
3718 fdb 0xec84,0x61f9 ; subarc 4
3719 fdb 0xe1c7,0x78ae ; subarc 5
3720 fdb 0xd4dc,0x8e3b ; subarc 6
3721 fdb 0xc5e5,0xa269 ; subarc 7
3722 fdb 0xb506,0xb506 ; subarc 8
3723 ; CIRCLE command
3724 ; The circle is drawn as a 64 sided polygon (64 LINE commands essentially)
3725 CIRCLE cmpa #'@ ; is there an @ before coordinates?
3726 bne L9EA3 ; brif not
3727 jsr GETNCH ; eat the @
3728 L9EA3 jsr L9522 ; get max coordinates for screen
3729 jsr L93B2 ; parse coordinates for circle centre
3730 jsr L931D ; normalize the start coordinates
3731 ldx ,u ; get horizontal coordinate
3732 stx VCB ; save it
3733 ldx 2,u ; get vertical coordinate
3734 stx VCD ; saveit
3735 jsr SYNCOMMA ; make sure we have a comma
3736 jsr LB73D ; evaluate radius expression
3737 ldu #VCF ; point to temp storage
3738 stx ,u ; save radius
3739 jsr L9320 ; normalize radius
3740 lda #1 ; default to PSET
3741 sta SETFLG
3742 jsr L9581 ; evaluate the colour expression
3743 ldx #0x100 ; height/width default value
3744 jsr GETCCH ; is there a ratio?
3745 beq L9EDF ; brif not
3746 jsr SYNCOMMA ; make sure we have a comma
3747 jsr LB141 ; evaluate the ratio
3748 lda FP0EXP ; multiply ratio by 256
3749 adda #8
3750 sta FP0EXP
3751 jsr LB740 ; evaluate ratio to X (fraction part in LSB)
3752 L9EDF lda PMODE ; get graphics mode
3753 bita #2 ; is it even?
3754 beq L9EE9 ; brif so
3755 tfr x,d ; double the ratio
3756 leax d,x
3757 L9EE9 stx VD1 ; save height/width ratio
3758 ldb #1 ; set the SET flag to PSET
3759 stb SETFLG
3760 stb VD8 ; set first time flag (set to 0 after arc drawn)
3761 jsr L9FE2 ; evaluate circle starting point (octant, subarc)
3762 pshs b,a ; save startpoint
3763 jsr L9FE2 ; evaluate circle end point (octant, subarc)
3764 std VD9 ; save endp oint
3765 puls a,b
3766 L9EFD pshs b,a ; save current circle position
3767 ldx HOREND ; move end coordinates to start coordinates
3768 stx HORBEG
3769 ldx VEREND
3770 stx VERBEG
3771 ldu #L9E79+2 ; point to sine/cosine table
3772 anda #1 ; even octant?
3773 beq L9F11 ; brif so
3774 negb ; convert 0-7 to 8-1 for odd octants
3775 addb #8
3776 L9F11 aslb ; four bytes per table entry
3777 aslb
3778 leau b,u ; point to correct table entry
3779 pshs u ; save sine/cosine table entry pointer
3780 jsr L9FA7 ; calculate horizontal offset
3781 puls u ; get back table entry pointer
3782 leau -2,u ; move to cosine entry
3783 pshs x ; save horizontal offset
3784 jsr L9FA7 ; calculate vertical offset
3785 puls y ; put horizontal in Y
3786 lda ,s ; get octant number
3787 anda #3 ; is it 0 or 4?
3788 beq L9F31 ; brif so
3789 cmpa #3 ; is it 3 or 7?
3790 beq L9F31 ; brif so
3791 exg x,y ; swap horizontal and vertical
3792 L9F31 stx HOREND ; save horizontal offset
3793 tfr y,x ; put vertical offset in X
3794 ldd VD1 ; get height/width ratio
3795 jsr L9FB5 ; multiply vertical by h/w ratio
3796 tfr y,d ; save the product to D
3797 tsta ; did it overflow?
3798 lbne LB44A ; brif so
3799 stb VEREND ; save vertical coordinate MSB
3800 tfr u,d ; get LSW of product
3801 sta VEREND+1 ; save LSB of integer part (we have 8 bits of fraction in the ratio)
3802 lda ,s ; get octant
3803 cmpa #2 ; is it 0 or 1?
3804 blo L9F5B ; brif so
3805 cmpa #6 ; is it 6 or 7?
3806 bhs L9F5B ; brif so
3807 ldd VCB ; get horizontal centre
3808 subd HOREND ; subtract horizontal displacement
3809 bcc L9F68 ; brif we didn't overflow the screen
3810 clra ; zero out coordinate if we overflowed the screen
3811 clrb
3812 bra L9F68
3813 L9F5B ldd VCB ; get horizontal coordinate of the centre
3814 addd HOREND ; add displacement
3815 bcs L9F66 ; brif overlod
3816 cmpd VD3 ; larger than max horizontal coord?
3817 blo L9F68 ; brif not
3818 L9F66 ldd VD3 ; maximize the coordinate
3819 L9F68 std HOREND ; save horizontal ending coordainte
3820 lda ,s ; get octant
3821 cmpa #4 ; is it 0-3?
3822 blo L9F7A ; brif so
3823 ldd VCD ; get vertical coordinate of centre
3824 subd VEREND ; subtract displacement
3825 bcc L9F87 ; brif we didn't overflow the screen
3826 clra ; minimize to top of screen
3827 clrb
3828 bra L9F87
3829 L9F7A ldd VCD ; get vertical centre coordinate
3830 addd VEREND ; add displacement
3831 bcs L9F85 ; brif we overflowed the screen
3832 cmpd VD5 ; did we go past max coordinate?
3833 blo L9F87 ; brif not
3834 L9F85 ldd VD5 ; maximize the coordinate
3835 L9F87 std VEREND ; save end coordinate
3836 tst VD8 ; check first time flag
3837 bne L9F8F ; do not draw if first time through (it was setting start coord)
3838 bsr L9FDF ; draw the line
3839 L9F8F puls a,b ; get arc number and sub arc
3840 lsr VD8 ; get first time flag value (and clear it!)
3841 bcs L9F9A ; do not check for end point after drawing for first coordinate
3842 cmpd VD9 ; at end point?
3843 beq L9FA6 ; brif drawing finished
3844 L9F9A incb ; bump arc counter
3845 cmpb #8 ; done 8 arcs?
3846 bne L9FA3 ; brif not
3847 inca ; bump octant
3848 clrb ; reset subarc number
3849 anda #7 ; make sure octant number stays in 0-7 range
3850 L9FA3 jmp L9EFD ; go do another arc
3851 L9FA6 rts
3852 L9FA7 ldx VCF ; get radius
3853 ldd ,u ; get sine/cosine table entry
3854 beq L9FB4 ; brif 0 - offset = radius
3855 subd #1 ; adjust values to correct range
3856 bsr L9FB5 ; multiply radius by sine/cosine
3857 tfr y,x ; resturn result in X
3858 L9FB4 rts
3859 L9FB5 pshs u,y,x,b,a ; save registers and reserve temp space
3860 clr 4,s ; reset overflow byte (YH)
3861 lda 3,s ; calcuate B*XL
3862 mul
3863 std 6,s ; put in "U"
3864 ldd 1,s ; calculate B*XH
3865 mul
3866 addb 6,s ; accumluate with previous product
3867 adca #0
3868 std 5,s ; save in YL,UH
3869 ldb ,s ; calculate A*XL
3870 lda 3,s
3871 mul
3872 addd 5,s ; accumulate with previous partical product
3873 std 5,s ; save in YL,UH
3874 bcc L9FD4 ; brif no carry
3875 inc 4,s ; bump YH for carry
3876 L9FD4 lda ,s ; calculate A*XH
3877 ldb 2,s
3878 mul
3879 addd 4,s ; accumulate with previous partial product
3880 std 4,s ; save in Y (we can't have a carry here)
3881 puls a,b,x,y,u,pc ; restore multiplicands and return results
3882 L9FDF jmp L94A1 ; go draw a line
3883 L9FE2 clrb ; default arc number (0)
3884 jsr GETCCH ; is there something there for a value?
3885 beq L9FF8 ; brif not
3886 jsr SYNCOMMA ; evaluate , + expression
3887 jsr LB141
3888 lda FP0EXP ; multiply by 64
3889 adda #6
3890 sta FP0EXP
3891 jsr LB70E ; get integer value of circle fraction
3892 andb #0x3f ; max value of 63
3893 L9FF8 tfr b,a ; save arc value in A to calculate octant
3894 andb #7 ; calculate subarc
3895 lsra ; calculate octant
3896 lsra
3897 lsra
3898 rts
3899 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3900 ; COLOR BASIC ROM area
3901 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3902 ; This is the official set of ROM entry points. It is unfortunate that the generic input ("console in") routine is not exposed
3903 ; here. It is also unfortunate that no open and close file routines are exposed. This and other oversignts led to a lot of
3904 ; software either having to re-invent the wheel or calling directly into the ROM instead of via these official entry points.
3905 POLCAT fdb KEYIN ; indirect jump, get a keystroke
3906 CHROUT fdb PUTCHR ; indirect jump, output character
3907 CSRDON fdb CASON ; indirect jump, turn cassette on and start reading
3908 BLKIN fdb GETBLK ; indirect jump, read a block from tape
3909 BLKOUT fdb SNDBLK ; indirect jump, write a block to tape
3910 JOYIN fdb GETJOY ; indirect jump, read joystick axes
3911 WRTLDR fdb WRLDR ; indirect jump, turn cassette on and write a leader
3912 ; Initialization code.
3913 LA00E lds #LINBUF+LBUFMX+1 ; put the stack in the line input buffer which is a safe place for now
3914 lda #0x37 ; enable the cartidge interrupt (to detect autostarting cartridges)
3915 sta PIA1+3
3916 lda RSTFLG ; get warm start flag
3917 cmpa #0x55 ; is it valid?
3918 bne BACDST ; brif not - cold start
3919 ldx RSTVEC ; get warm start routine pointer
3920 lda ,x ; get first byte of the routine
3921 cmpa #0x12 ; is it NOP?
3922 bne BACDST ; brif not - the routine is invalid so do a cold start
3923 jmp ,x ; transfer control to the warm start routine
3924 ; RESET/power on comes here
3925 RESVEC leay LA00E,pcr ; point to warm start check code
3926 LA02A lda #0x3a ; restore MMU block in 0x4000-0x5fff block
3927 sta MMUREG+2
3928 ldx #PIA1 ; point to PIA1
3929 ldd #0xff34 ; set up for initializing PIAs
3930 clr 1,x ; set PIA1 DA to direction mode
3931 clr 3,x ; set PIA1 DB to direction mode
3932 deca
3933 sta ,x ; set PIA1 DA bits 7-1 as output, 0 as input
3934 lda #0xf8 ; set PIA1 DB bits 7-3 as output, 2-0 as input
3935 sta 2,x
3936 stb 1,x ; set PIA1 DA to data mode
3937 stb 3,x ; set PIA1 DB to data mode
3938 clr 2,x ; set VDG to alpha-numeric
3939 lda #2 ; set RS232 to marking
3940 sta ,x
3941 lda #0xff
3942 ldx #PIA0 ; point to PIA0
3943 clr 1,x ; set PIA0 DA to direction mode
3944 clr 3,x ; set PIA0 DB to direction mode
3945 clr ,x ; set PIA0 DA to input
3946 sta 2,x ; set PIA0 DB to output
3947 stb 1,x ; set PIA0 DA to direction mode
3948 stb 3,x ; set PIA0 DB to direction mode
3949 jmp LA072 ; continue initializing
3950 LA05E jsr L8C2E ; map ROM pack
3951 jmp 0xc000 ; transfer control to ROM pack
3952 ; Left over initialization code from Color Basic 1.2 follows
3953 bitb 2,x ; check RAMSZ input
3954 beq LA072 ; brif set for 4K RAMs
3955 clr -2,x ; set strobe low
3956 bitb 2,x ; check input
3957 beq LA070 ; brif set for 64K rams
3958 leau -2,u ; adjust pointer to set SAM for 16K RAMs
3959 LA070 sta -3,u ; program SAM for either 16K or 64K RAMs
3960 LA072 jmp ,y ; transfer control to startup routine
3961 ; Cold start jumps here
3962 BACDST ldx #VIDRAM+1 ; point past the top of the first 1K of memory (for double predec below)
3963 LA077 clr ,--x ; clear a byte (last will actually try clearing LSB of RESET vector in ROM)
3964 leax 1,x ; move forward one byte (will set Z if we're done)
3965 bne LA077 ; brif not donw yet
3966 jsr LA928 ; clear the screen
3967 clr ,x+ ; put the constant zero that lives before the program
3968 stx TXTTAB ; set beginning of program storage
3969 LA084 ldx #0x7fff ; set to of available RAM to just below the "ROM" area
3970 bra LA093
3971 nop
3972 nop
3973 nop
3974 nop
3975 nop
3976 nop
3977 nop
3978 nop
3979 nop
3980 nop
3981 LA093 stx TOPRAM ; save top of memory (one below actual top because we need a byte for VAL() to work)
3982 stx MEMSIZ ; save top of string space
3983 stx STRTAB ; set bottom of allocated string space
3984 leax -200,x ; allocate 200 bytes of string space
3985 stx FRETOP ; set top of actually free memory
3986 tfr x,s ; put the stack there
3987 ldx #LA10D ; point to variable initializer
3988 ldu #CMPMID ; point to variables to initialize (first batch)
3989 ldb #28 ; 28 bytes in first batch
3990 jsr LA59A ; copy bytes to variables
3991 ldu #IRQVEC ; point to variables to initialize (second batch)
3992 ldb #30 ; 30 bytes this time
3993 jsr LA59A ; copy bytes to variables
3994 ldx -12,x ; get SN error address
3995 stx 3,u ; set ECB's command handlers to error
3996 stx 8,u
3997 ldx #RVEC0 ; point to RAM vectors
3998 ldd #0x394b ; write 75 RTS opcodes (25 RAM vectors)
3999 LA0C0 sta ,x+ ; put an RTS
4000 decb ; done?
4001 bne LA0C0 ; brif not
4002 sta LINHDR-1 ; make temporary line header data for line encoding have a nonzero next line pointer
4003 jsr LAD19 ; do a "NEW"
4004 jmp L8002 ; transfer control to ECB's initialization routine
4005 LA0CE pshs b,x ; save registers
4006 tst HRWIDTH ; is it VDG mode?
4007 lbne ALINK24 ; brif not
4008 LA0D6 jsr LA199 ; do a "cursor"
4009 jsr KEYIN ; read a key
4010 beq LA0D6 ; brif no key
4011 LA0DE jmp LA1B9 ; return to mainline
4012 fcb 0x72 ; left-over from code replacement above
4013 LA0E2 lda #0x55 ; warm start valid flag
4014 sta RSTFLG ; mark warm start valid
4015 bra LA0F3 ; go to direct mode
4016 ; Warm start entry point
4017 BAWMST nop ; valid routine marker
4018 clr DEVNUM ; reset output/input to screen
4019 jsr LAD33 ; do a partial NEW
4020 andcc #0xaf ; start interrupts
4021 jsr CLS ; clear the screen
4022 LA0F3 jmp LAC73 ; go to direct mode
4023 ; FIRQ service routine - this handles starting autostart cartridges
4024 BFRQSV tst PIA1+3 ; is it the cartridge interrupt?
4025 bmi LA0FC ; brif so
4026 rti
4027 LA0FC jsr L8C28 ; map cartridge
4028 jsr LA7D1 ; delay for another while
4029 leay <LA108,pcr ; point to cartridge starter
4030 jmp LA02A ; go initialize everything clean for the cartridge
4031 LA108 clr RSTFLG ; force a cold start a cartridge reset
4032 jmp ROMPAK ; transfer control to the cartridge
4033 ; Variable initializers (first batch)
4034 LA10D fcb 18 ; mid band partition of the 1200/2400 Hz period
4035 fcb 24 ; upper limit of 1200 Hz period
4036 fcb 10 ; upper limit of 2400 Hz period
4037 fdb 128 ; number of 0x55s for cassette leader
4038 fcb 11 ; cursor blink delay
4039 fdb 88 ; 600 baud delay constant
4040 fdb 1 ; printer carriage return delay constant
4041 fcb 16 ; printer tab field width
4042 fcb 112 ; last printer tab zone
4043 fcb 132 ; printer carriage width
4044 fcb 0 ; printer carriage position
4045 fdb LB44A ; default execution address for EXEC
4046 inc CHARAD+1 ;* character fetching routines (DP portion) - we first do a two
4047 bne LA123 ;* two stage increment of CHARAD then load the value into A
4048 inc CHARAD ;* before transferring control to the bottom half routine in ROM
4049 LA123 lda >0 ; NOTE: the 0 is a placeholder, extended addressing is required
4050 jmp BROMHK
4051 ; Variable initializers (second batch)
4052 jmp BIRQSV ; IRQ handler
4053 jmp BFRQSV ; FIRQ handler
4054 jmp LB44A ; default USR() address
4055 fcb 0x80,0x4f,0xc7,0x52,0x59 ; random seed
4056 fcb 0xff ; capslock flag - default to upper case
4057 fdb DEBDEL ; keyboard debounce delay (why is it a variable?)
4058 jmp LB277 ; exponentiation handler vector
4059 fcb 53 ; (command interpretation table) 53 commands
4060 fdb LAA66 ; (command interpretation table) reserved words list (commands)
4061 fdb LAB67 ; (command interpretation table) jump table (commands)
4062 fcb 20 ; (command interpretation table) 20 functions
4063 fdb LAB1A ; (command interpretation table) reserved words list (functions)
4064 fdb LAA29 ; (command interpretation table) jump table (functions)
4065 ; This is the signon message.
4066 LA147 fcc 'COLOR BASIC 1.2'
4067 fcb 0x0d
4068 fcc '(C) 1982 TANDY'
4069 fcb 0
4070 ; This is the "invalid colour" CLS easter egg text. Basically 11 wasted bytes
4071 LA166 fcc 'MICROSOFT'
4072 fcb 0x0d,0
4073 ; Read a character from current device and mask off bit 7 (keep it as 7 bit ASCII)
4074 LA171 bsr LA176 ; get character
4075 anda #0x7f ; mask off high bit
4076 rts
4077 ; Generic read routine. Reads a character from the device specified by DEVNUM. If no input was available,
4078 ; CINBFL will bet nonzero (on EOF). If input was available, CINBFL will be zero. Note that this routine
4079 ; has undefined results when called on an output only device. All registers except CC and A are preserved.
4080 LA176 jsr RVEC4 ; do RAM hook
4081 clr CINBFL ; flag data available
4082 tst DEVNUM ; is it keyboard?
4083 beq LA1B1 ; brif so - blink cursor and wait for key press
4084 tst CINCTR ; is there anything in cassette input buffer?
4085 bne LA186 ; brif so
4086 com CINBFL ; flag EOF
4087 rts
4088 ; Read character from cassette file
4089 LA186 pshs u,y,x,b ; preserve registers
4090 ldx CINPTR ; get input buffer pointer
4091 lda ,x+ ; get character from buffer
4092 pshs a ; save it for return
4093 stx CINPTR ; save new input buffer pointer
4094 dec CINCTR ; count character just consumed
4095 bne LA197 ; brif buffer is not empty yet
4096 jsr LA635 ; go read another block, if any, to refill the buffer
4097 LA197 puls a,b,x,y,u,pc ; restore registers and return the character
4098 ; Blink the cursor. This might be better timed via an interrupt or something.
4099 LA199 dec BLKCNT ; is it time to blink the cursor?
4100 bne LA1AB ; brif not
4101 ldb #11 ; reset blink timer
4102 stb BLKCNT
4103 ldx CURPOS ; get cursor position
4104 lda ,x ; get character at the cursor
4105 adda #0x10 ; move to next color
4106 ora #0x8f ; make sure it's a grahpics block with all elements lit
4107 sta ,x ; put new cursor block on screen
4108 LA1AB ldx #DEBDEL ; we'll use the debounce delay for the cursor blink timer (10ms)
4109 LA1AE jmp LA7D3 ; go count X down
4110 ; Blink cursor while waiting for a key press
4111 LA1B1 pshs x,b ; save registers
4112 LA1B3 bsr LA199 ; go do a cursor iteration
4113 bsr KEYIN ; go read a key
4114 beq LA1B3 ; brif no key pressed
4115 LA1B9 ldb #0x60 ; VDG screen space character
4116 stb [CURPOS] ; blank cursor out
4117 puls b,x,pc ; restore registers and return
4118 ; This is the actual keyboard polling routine. Returns 0 if no new key is down. Compared to the 1.0 and 1.1
4119 ; ROMs, this routine is quite a lot more compact and robust.
4120 LA1C1 jmp KEYIN ; transfer control to actual keyboard scan
4121 rts ;* this actually removes a check to see if any keys are actually down
4122 rts ;* which is unfortunate because it makes programs run slower.
4123 rts
4124 rts
4125 rts
4126 rts
4127 rts
4128 KEYIN pshs u,x,b ; save registers
4129 ldu #PIA0 ; point to keyboard PIA
4130 ldx #KEYBUF ; point to state table
4131 clra ; clear carry, set column to 0xff (no strobe)
4132 deca ; (note: deca does not affect C)
4133 pshs x,a ; save column counter and make a couple of holes for temporaries
4134 sta 2,u ; set strobe to no columns
4135 LA1D9 rol 2,u ; move to next column (C is 0 initially, 1 after)
4136 bcc LA220 ; brif we shifted out a 0 - we've done 8 columns
4137 inc 0,s ; bump column counter (first bump goes to 0)
4138 bsr LA23A ; read row data
4139 sta 1,s ; save key data (for debounce check and later saving)
4140 eora ,x ; now bits set if key state changed
4141 anda ,x ; now bits are only set if a key has been pressed
4142 ldb 1,s ; get new key data
4143 stb ,x+ ; save in state table
4144 tsta ; was a key down?
4145 beq LA1D9 ; brif not - do another (nothing above cleared C)
4146 ldb 2,u ; get strobe data
4147 stb 2,s ; save it for debounce check
4148 ldb #0xf8 ; set up so B is 0 after first add
4149 LA1F4 addb #8 ; add 8 for each row
4150 lsra ; did we hit the right row?
4151 bcc LA1F4 ; brif not
4152 addb 0,s ; add in column number
4153 beq LA245 ; brif @
4154 cmpb #26 ; letter?
4155 bhi LA247 ; brif not
4156 orb #0x40 ; bias into letter range
4157 bsr LA22E ; check for SHIFT
4158 ora CASFLG ; merge in capslock state
4159 bne LA20C ; brif either capslock or SHIFT - keep upper case
4160 orb #0x20 ; move to lower case
4161 LA20C stb 0,s ; save ASCII value
4162 ldx DEBVAL ; get debounce delay
4163 bsr LA1AE ; do the 10ms debounce delay
4164 ldb #0xff ; set strobe to none - only joystick buttons register now
4165 bsr LA238 ; read keyboard
4166 inca ; A now 0 if no buttons down
4167 bne LA220 ; brif button down - return nothing since we have interference
4168 LA21A ldb 2,s ; get column strobe data
4169 bsr LA238 ; read row data
4170 cmpa 1,s ; does it match original read?
4171 LA220 puls a,x ; clean up stack and get return value
4172 bne LA22B ; brif failed debounce or a joystick button down
4173 cmpa #0x12 ; is it SHIFT-0?
4174 bne LA22C ; brif not
4175 com CASFLG ; swap capslock state
4176 LA22B clra ; set no key down
4177 LA22C puls b,x,u,pc ; restore registers and return
4178 LA22E lda #0x7f ; column strobe for SHIFT
4179 sta 2,u ; set column
4180 lda ,u ; get row data
4181 coma ; set if key down
4182 anda #0x40 ; only keep SHIFT state
4183 rts
4184 LA238 stb 2,u ; save strobe data
4185 LA23A lda ,u ; get row data
4186 ora #0x80 ; mask off comparator so it doesn't interfere
4187 tst 2,u ; are we on column 7?
4188 bmi LA244 ; brif not
4189 ora #0xc0 ; also mask off SHIFT
4190 LA244 rts
4191 LA245 ldb #51 ; scan code for @
4192 LA247 ldx #CONTAB-0x36 ; point to code table
4193 cmpb #33 ; arrows, space, zero?
4194 blo LA264 ; brif so
4195 ldx #CONTAB-0x54 ; adjust to other half of table
4196 cmpb #48 ; ENTER, CLEAR, BREAK, @?
4197 bhs LA264 ; brif so
4198 bsr LA22E ; read shift state
4199 cmpb #43 ; is it a number, colon, semicolon?
4200 bls LA25D ; brif so
4201 eora #0x40 ; invert shift state for others
4202 LA25D tsta ; shift down?
4203 bne LA20C ; brif not - return result
4204 addb #0x10 ; add in offset to shifted character
4205 bra LA20C ; go return result
4206 LA264 lslb ; two entries per key
4207 bsr LA22E ; check SHIFT state
4208 beq LA26A ; brif not shift
4209 incb ; point to shifted entry
4210 LA26A ldb b,x ; get actual key code
4211 bra LA20C ; go return result
4212 CONTAB fcb 0x5e,0x5f ; <UP> (^, _)
4213 fcb 0x0a,0x5b ; <DOWN> (LF, [)
4214 fcb 0x08,0x15 ; <LEFT> (BS, ^U)
4215 fcb 0x09,0x5d ; <RIGHT> (TAB, ])
4216 fcb 0x20,0x20 ; <SPACE>
4217 fcb 0x30,0x12 ; <0> (0, ^R)
4218 fcb 0x0d,0x0d ; <ENTER> (CR, CR)
4219 fcb 0x0c,0x5c ; <CLEAR> (FF, \)
4220 fcb 0x03,0x03 ; <BREAK> (^C, ^C)
4221 fcb 0x40,0x13 ; <@> (@, ^S)
4222 ; Generic output routine.
4223 ; Output character in A to the device specified by DEVNUM. All registers are preserved except CC.
4224 ; Sending output to a device that does not support output is undefined.
4225 PUTCHR jsr RVEC3 ; call RAM hook
4226 pshs b ; save B
4227 ldb DEVNUM ; get desired device number
4228 incb ; set flags (Z for -1, etc.)
4229 puls b ; restore B
4230 bmi LA2BF ; brif < -1 (line printer)
4231 bne LA30A ; brif > -1 (screen)
4232 ; Write character to tape file
4233 pshs x,b,a ; save registers
4234 ldb FILSTA ; get file status
4235 decb ; input file?
4236 beq LA2A6 ; brif so
4237 ldb CINCTR ; get character count
4238 incb ; account for this character
4239 bne LA29E ; brif buffer not full
4240 bsr LA2A8 ; write previously full block to tape
4241 LA29E ldx CINPTR ; get output buffer pointer
4242 sta ,x+ ; put character in output
4243 stx CINPTR ; save new buffer pointer
4244 inc CINCTR ; account for this character
4245 LA2A6 puls a,b,x,pc ; restore registers and return
4246 ; Write a block of data to tape.
4247 LA2A8 ldb #1 ; data block type
4248 LA2AA stb BLKTYP ; set block type
4249 ldx #CASBUF ; point to output buffer
4250 stx CBUFAD ; set buffer pointer
4251 ldb CINCTR ; get number of bytes in the block
4252 stb BLKLEN ; set length to write
4253 pshs u,y,a ; save registers
4254 jsr LA7E5 ; write a block to tape
4255 puls a,y,u ; restore registers
4256 jmp LA650 ; reset buffer pointers
4257 ; Send byte to line printer
4258 LA2BF pshs x,b,a,cc ; save registers and interrupt status
4259 orcc #0x50 ; disable interrupts
4260 LA2C3 ldb PIA1+2 ; get RS232 status
4261 lsrb ; get status to C
4262 bcs LA2C3 ; brif busy - loop until not busy
4263 bsr LA2FB ; set output to marking
4264 clrb ; transmit one start bit
4265 bsr LA2FD
4266 ldb #8 ; counter for 8 bits
4267 LA2D0 pshs b ; save bit count
4268 clrb ; zero output bits
4269 lsra ; bet output bit to C
4270 rolb ; get output bit to correct bit for output byte
4271 lslb
4272 bsr LA2FD ; transmit bit
4273 puls b ; get back bit counter
4274 decb ; are we done yet?
4275 bne LA2D0 ; brif not
4276 bsr LA2FB ; send stop bit (marking)
4277 puls cc,a ; restore interrupt status and output character
4278 cmpa #0x0d ; carriage return?
4279 beq LA2ED ; brif so
4280 inc LPTPOS ; bump output position
4281 ldb LPTPOS ; get new position
4282 cmpb LPTWID ; end of line?
4283 blo LA2F3 ; brif not
4284 LA2ED clr LPTPOS ; reset position to start of line
4285 bsr LA305 ; do carriage return delay
4286 bsr LA305
4287 LA2F3 ldb PIA1+2 ; get RS232 status
4288 lsrb ; get status to C
4289 bcs LA2F3 ; brif still busy, keep waiting
4290 puls b,x,pc ; restore registers and return
4291 LA2FB ldb #2 ; set output to high (marking)
4292 LA2FD stb PIA1 ; set RS232 output
4293 bsr LA302 ; do baud delay (first iteration) then fall through for second
4294 LA302 ldx LPTBTD ; get buard rate delay constant
4295 skip2
4296 LA305 ldx LPTLND ; get carriage return delay constant
4297 jmp LA7D3 ; count X down
4298 ; Output character to screen
4299 LA30A pshs x,b,a ; save registers
4300 ldx CURPOS ; get cursor pointer
4301 LA30E cmpa #0x08 ; backspace?
4302 bne LA31D ; brif not
4303 cmpx #VIDRAM ; at top of screen?
4304 beq LA35D ; brif so - it's a no-op
4305 lda #0x60 ; VDG space character
4306 sta ,-x ; put a space at previous location and move pointer back
4307 bra LA344 ; save new cursor position and return
4308 LA31D cmpa #0x0d ; carriage return?
4309 bne LA32F ; brif not
4310 ldx CURPOS ; get cursor pointer (why? we already have it)
4311 LA323 lda #0x60 ; VDG space character
4312 sta ,x+ ; put output space
4313 tfr x,d ; see if we at a multiple of 32 now
4314 bitb #0x1f
4315 bne LA323 ; brif not
4316 bra LA344 ; go check for scrolling
4317 LA32F cmpa #0x20 ; control character?
4318 blo LA35D ; brif so
4319 tsta ; is it graphics block?
4320 bmi LA342 ; brif so
4321 cmpa #0x40 ; number or special?
4322 blo LA340 ; brif so (flip "case" bit)
4323 cmpa #0x60 ; upper case alpha?
4324 blo LA342 ; brif so - keep it unmodified
4325 anda #0xdf ; clear bit 5 (inverse video)
4326 LA340 eora #0x40 ; flip inverse video bit
4327 LA342 sta ,x+ ; output character
4328 LA344 stx CURPOS ; save new cursor position
4329 cmpx #VIDRAM+511 ; end of screen?
4330 bls LA35D ; brif not
4331 ldx #VIDRAM ; point to start of screen
4332 LA34E ldd 32,x ; get two characters from next row
4333 std ,x++ ; put them on this row
4334 cmpx #VIDRAM+0x1e0 ; at start of last row on screen?
4335 blo LA34E ; brif not
4336 ldb #0x60 ; VDG space
4337 jsr LA92D ; blank out last line (borrow CLS's loop)
4338 LA35D puls a,b,x,pc ; restore registers and return
4339 ; Set up device parameters for output
4340 LA35F jsr RVEC2 ; do the RAM hook dance
4341 pshs x,b,a ; save registers
4342 clr PRTDEV ; flag device as a screen
4343 lda DEVNUM ; get devicenumber
4344 beq LA373 ; brif screen
4345 inca ; is it tape?
4346 beq LA384 ; brif so
4347 ldx LPTCFW ; get tab width and last tab stop for printer
4348 ldd LPTWID ; get line width and current position for printer
4349 bra LA37C ; set parameters
4350 LA373 ldb CURPOS+1 ; get LSB of cursor position
4351 andb #0x1f ; now we have the offset into the line
4352 ldx #0x1010 ; 16 character tab, position 16 is last tab stop
4353 lda #32 ; screen is 32 characters wide
4354 LA37C stx DEVCFW ; save tab width and last tab stop for active device
4355 stb DEVPOS ; save line position for current device
4356 sta DEVWID ; save line width for current device
4357 puls a,b,x,pc ; restore registers and return
4358 LA384 com PRTDEV ; flag device as non-display
4359 ldx #0x0100 ; tab width is 1, last tab field is 0
4360 clra ; line width is 0
4361 clrb ; character position on line is 0
4362 bra LA37C ; go set parameters
4363 ; This is the line input routine used for reading lines for Basic, both in immediate mode and for
4364 ; INPUT and LINE INPUT. Exit with C set if terminated by BREAK and C clear if terminated by ENTER.
4365 ; The actualy entry point is LA390. Note that this routine echoes to *all* devices.
4366 LA38D jsr LA928 ; clear screen (CLEAR key handling)
4367 LA390 jsr RVEC12 ; do the RAM hook dance
4368 clr IKEYIM ; reset cached input character from BREAK check
4369 ldx #LINBUF+1 ; point to line input buffer (input pointer)
4370 ldb #1 ; Number of characters in line (we start at 1 so BS handling is easier)
4371 LA39A jsr LA171 ; get an input character, only keep low 7 bits
4372 tst CINBFL ; is it EOF?
4373 bne LA3CC ; brif EOF
4374 tst DEVNUM ; is it keyboard input?
4375 bne LA3C8 ; brif not - don't do line editing
4376 cmpa #0x0c ; form feed (CLEAR)?
4377 beq LA38D ; brif so - clear screen and reset
4378 cmpa #0x08 ; backspace?
4379 bne LA3B4 ; brif not
4380 decb ; move back one character
4381 beq LA390 ; brif we were at the start of the line - reset and start again
4382 leax -1,x ; move input pointer back
4383 bra LA3E8 ; echo the backspace and continue
4384 LA3B4 cmpa #0x15 ; SHIFT-LEFT (kill line)?
4385 bne LA3C2 ; brif not
4386 LA3B8 decb ; at start of line?
4387 beq LA390 ; brif so - reset and restart
4388 lda #0x08 ; echo a backspace
4389 jsr PUTCHR
4390 bra LA3B8 ; see if we've erased everything yet
4391 LA3C2 cmpa #0x03 ; BREAK?
4392 orcc #1 ; set C if it is (only need Z for the next test
4393 LA3C6 beq LA3CD ; brif BREAK - exit
4394 LA3C8 cmpa #0x0d ; ENTER (CR)
4395 bne LA3D9 ; brif not
4396 LA3CC clra ; clear carry (it might not be clear on EOF)
4397 LA3CD pshs cc ; save ENTER/BREAK flag
4398 jsr LB958 ; echo a carriage return
4399 clr ,x ; make sure we have a NUL at the end of the buffer
4400 ldx #LINBUF ; point to input buffer
4401 puls cc,pc ; restore ENTER/BREAK flag and return
4402 LA3D9 cmpa #0x20 ; control character?
4403 blo LA39A ; brif so - skip it
4404 cmpa #'z+1 ; above z?
4405 bhs LA39A ; brif so - ignore it
4406 cmpb #LBUFMX ; is the buffer full?
4407 bhs LA39A ; brif so - ignore extra characters
4408 sta ,x+ ; put character in the buffer
4409 incb ; bump character count
4410 LA3E8 jsr PUTCHR ; echo character
4411 bra LA39A ; go handle next input character
4412 ; Check if DEVNUM Is valid for reading. Raise FM error if open but not for reading. NO error if not open.
4413 LA3ED jsr RVEC5 ; do the RAM hook dance
4414 lda DEVNUM ; get device number
4415 beq LA415 ; brif keyboard - always valid
4416 inca ; is it tape?
4417 bne LA403 ; brif not
4418 lda FILSTA ; get tape file status
4419 bne LA400 ; brif file is open
4420 LA3FB ldb #22*2 ; raise NO error
4421 jmp LAC46
4422 LA400 deca ; is it in input mode?
4423 beq LA415 ; brif so
4424 LA403 jmp LA616 ; raise FM error
4425 ; Check if DEVNUM is valid for writing. Raise FM error if open but not for writing. NO error if not open.
4426 LA406 jsr RVEC6 ; do the RAM hook dance
4427 lda DEVNUM ; get device number
4428 inca ; is it tape?
4429 bne LA415 ; brif not
4430 lda FILSTA ; get file status
4431 beq LA3FB ; brif not open
4432 deca ; is it open for reading?
4433 beq LA403 ; brif so - bad mode
4434 LA415 rts
4435 ; CLOSE command
4436 CLOSE beq LA426 ; brif no file specified - close all files
4437 jsr LA5A5 ; parse device number
4438 LA41B bsr LA42D ; close specified file
4439 jsr GETCCH ; is there more?
4440 beq LA44B ; brif not
4441 jsr LA5A2 ; check for comma and parse another device number
4442 bra LA41B ; go close this one
4443 ; Close all files handler.
4444 LA426 jsr RVEC7 ; Yup. The RAM hook dance.
4445 LA429 lda #-1 ; start with tape file
4446 sta DEVNUM
4447 ; Close file specified in DEVNUM. Note that this never fails.
4448 LA42D jsr RVEC8 ; You know it. RAM hook.
4449 lda DEVNUM ; get device we're closing
4450 clr DEVNUM ; reset to screen/keyboard
4451 inca ; is it tape?
4452 bne LA44B ; brif not
4453 lda FILSTA ; get file status
4454 cmpa #2 ; is it output?
4455 bne LA449 ; brif not
4456 lda CINCTR ; is there anything waiting to be written?
4457 beq LA444 ; brif not
4458 jsr LA2A8 ; write final block of data
4459 LA444 ldb #0xff ; write EOF block
4460 jsr LA2AA
4461 LA449 clr FILSTA ; mark tape file closed
4462 LA44B rts
4463 ; CSAVE command
4464 CSAVE jsr LA578 ; parse filename
4465 jsr GETCCH ; see what we have after the file name
4466 beq LA469 ; brif none
4467 jsr SYNCOMMA ; make sure there's a comma
4468 ldb #'A ; make sure there's an A after
4469 jsr LB26F
4470 bne LA44B ; brif not end of line
4471 clra ; file type 0 (basic program)
4472 jsr LA65C ; write out header block
4473 lda #-1 ; set output to tape
4474 sta DEVNUM
4475 clra ; set Z so we list the whole program
4476 jmp LIST ; go list the program to tape
4477 LA469 clra ; file type 0 (basic program)
4478 ldx ZERO ; set to binary file mode
4479 jsr LA65F ; write header block
4480 clr FILSTA ; close files
4481 inc BLKTYP ; set block type to data
4482 jsr WRLDR ; write out a leader
4483 ldx TXTTAB ; point to start of program
4484 LA478 stx CBUFAD ; set buffer location
4485 lda #255 ; block size to 255 bytes (max size)
4486 sta BLKLEN
4487 ldd VARTAB ; get end of program
4488 subd CBUFAD ; how much is left?
4489 beq LA491 ; brif we have nothing left
4490 cmpd #255 ; do we have a full block worth?
4491 bhs LA48C ; brif so
4492 stb BLKLEN ; save actual remainder as block length
4493 LA48C jsr SNDBLK ; write a block out
4494 bra LA478 ; go do another block
4495 LA491 neg BLKTYP ; set block type to 0xff (EOF)
4496 clr BLKLEN ; no data in EOF block
4497 jmp LA7E7 ; write EOF, stop tape, and return
4498 ; CLOAD and CLOADM commands
4499 CLOAD clr FILSTA ; close tape file
4500 cmpa #'M ; is it ClOADM?
4501 beq LA4FE ; brif so
4502 leas 2,s ; clean up stack
4503 jsr LA5C5 ; parse file name
4504 jsr LA648 ; go find the file
4505 tst CASBUF+10 ; is it binary?
4506 beq LA4C8 ; brif so
4507 lda CASBUF+9 ; is it ASCII?
4508 beq LA4CD ; brif not
4509 jsr LAD19 ; clear out existing program
4510 lda #-1 ; set up for reading from tape
4511 sta DEVNUM
4512 inc FILSTA ; set tape file to input
4513 jsr LA635 ; go read first block
4514 jmp LAC7C ; go to immediate mode to read in the program
4515 ; This is the EOF handler for immediate mode. It's rather assinine for this to be located here. It is
4516 ; probably an artifact of a substantially different code layout prior to compacting the ROM to fit in
4517 ; 8K.
4518 LA4BF jsr RVEC13 ; do the RAM hook dance
4519 jsr LA42D ; close file
4520 jmp LAC73 ; go back to immediate mode
4521 LA4C8 lda CASBUF+8 ; get file type
4522 beq LA4D0 ; brif basic program
4523 LA4CD jmp LA616 ; raise FM error
4524 LA4D0 jsr LAD19 ; erase existing program
4525 jsr CASON ; start reading tape
4526 ldx TXTTAB ; get start of program storage
4527 LA4D8 stx CBUFAD ; set load address for block
4528 ldd CBUFAD ; get start of block
4529 inca ; bump by 256
4530 jsr LAC37 ; check if there's room for a maximum sized block of 255
4531 jsr GETBLK ; go read a block
4532 bne LA4F8 ; brif there was an error during reading
4533 lda BLKTYP ; get type of block read
4534 beq LA4F8 ; brif header block - IO error
4535 bpl LA4D8 ; brif data block - read another
4536 stx VARTAB ; save new end of program
4537 bsr LA53B ; stop tape
4538 ldx #LABED-1 ; point to "OK" prompt
4539 jsr STRINOUT ; show prompt
4540 jmp LACE9 ; reset various things and return
4541 LA4F8 jsr LAD19 ; clear out partial program load
4542 LA4FB jmp LA619 ; raise IO error
4543 ; This is the CLOADM command
4544 LA4FE jsr GETNCH ; eat the "M"
4545 bsr LA578 ; parse file name
4546 jsr LA648 ; go find the file
4547 LA505 ldx ZERO ; default offset is 0
4548 jsr GETCCH ; see if there's something after the file name
4549 beq LA511 ; brif no offset
4550 jsr SYNCOMMA ; make sure there's a comma
4551 jsr LB73D ; evaluate offset to X
4552 LA511 lda CASBUF+8 ; get file mode
4553 cmpa #2 ; M/L program?
4554 bne LA4CD ; brif not - FM error
4555 ldd CASBUF+11 ; get load address
4556 leau D,x ; add in offset
4557 stu EXECJP ; set EXEC default address
4558 tst CASBUF+10 ; is it binary?
4559 bne LA4CD ; brif not
4560 ldd CASBUF+13 ; get load address
4561 leax d,x ; add in offset
4562 stx CBUFAD ; set buffer address for loading
4563 jsr CASON ; start up tape
4564 LA52E jsr GETBLK ; read a block
4565 bne LA4FB ; brif error reading
4566 stx CBUFAD ; save new load address
4567 tst BLKTYP ; set flags on block type
4568 beq LA4FB ; brif another header - IO error
4569 bpl LA52E ; brif it was data - read more
4570 LA53B jmp LA7E9 ; turn off tape and return
4571 ; The EXEC command
4572 EXEC beq LA545 ; brif no argument - use default address
4573 jsr LB73D ; evaluate EXEC address to X
4574 stx EXECJP ; set new default EXEC address
4575 LA545 jmp [EXECJP] ; transfer control to execution address
4576 ; Break check for LIST so it doesn't interrupt ASCII saves. Why is this here instead of with the rest of the break
4577 ; check logic or packaged up with LIST?
4578 LA549 jsr RVEC11 ; do the RAM hook dance
4579 lda DEVNUM ; get device number
4580 inca ; is it tape?
4581 beq LA5A1 ; brif so - don't do break check
4582 jmp LADEB ; do the actual break check
4583 ; Evaluate an expression and make sure it is within the limits of the screen and sets the cursor position.
4584 ; This really should be located with the PRINT command.
4585 LA554 jsr LB3E4 ; evaluate a positive expression to D
4586 subd #511 ; is it within bounds?
4587 lbhi LB44A ; brif not - error out
4588 addd #VIDRAM+511 ; adjust to be within the screen (and undo the SUBD above)
4589 std CURPOS ; set cursor position
4590 rts
4591 ; INKEY$ function
4592 INKEY lda IKEYIM ; was a key down during break check?
4593 bne LA56B ; brif so
4594 jsr KEYIN ; poll the keyboard
4595 LA56B clr IKEYIM ; reset the break check cache
4596 sta FPA0+3 ; store result for later return
4597 lbne LB68F ; brif a key was down - return it as a string
4598 sta STRDES ; set string length to 0 (no key down)
4599 jmp LB69B ; return the NULL string
4600 ; Parse a filename
4601 LA578 ldx #CFNBUF ; point to file name buffer
4602 clr ,x+ ; zero out file name length
4603 lda #0x20 ; space character to initialize file name
4604 LA57F sta ,x+ ; put a space in the buffer
4605 cmpx #CASBUF ; at end of file name?
4606 bne LA57F ; brif not
4607 jsr GETCCH ; get input character
4608 beq LA5A1 ; brif no name present
4609 jsr LB156 ; evaluate the file name expression
4610 jsr LB654 ; point to start of the file name
4611 ldu #CFNBUF ; point to file name buffer
4612 stb ,u+ ; save string length
4613 beq LA5A1 ; brif empty - we're done
4614 skip2
4615 LA598 ldb #8 ; copy 8 bytes
4616 ; Move B bytes from (X) to (U)
4617 LA59A lda ,x+ ; copy a byte
4618 sta ,u+
4619 decb ; done yet?
4620 bne LA59A ; brif not
4621 LA5A1 rts
4622 ; Parse a device number and check validity
4623 LA5A2 jsr SYNCOMMA ; check for comma and SN error if not
4624 LA5A5 cmpa #'# ; do we have a #?
4625 bne LA5AB ; brif not (it's optional)
4626 jsr GETNCH ; munch the #
4627 LA5AB jsr LB141 ; evaluate the expression
4628 LA5AE jsr INTCNV ; convert it to an integer in D
4629 rolb ; move sign of B into C
4630 adca #0 ; add sign of B to A
4631 bne LA61F ; brif A doesn't match the sign of B
4632 rorb ; restore B (ADCA will have set C if B was negative)
4633 stb DEVNUM ; set device number
4634 jsr RVEC1 ; do the RAM hook dance
4635 beq LA5C4 ; brif device number set to screen/keyboard (valid)
4636 bpl LA61F ; brif not negative (not valid)
4637 cmpb #-2 ; is it printer or tape?
4638 blt LA61F ; brif not (not valid)
4639 LA5C4 rts
4640 ; Read file name from the line and do an error if anything follows it
4641 LA5C5 bsr LA578 ; parse file name
4642 LA5C7 jsr GETCCH ; set flags on current character
4643 LA5C9 beq LA5C4 ; brif nothing there - it's good
4644 jmp LB277 ; raise SN error
4645 ; EOF function
4646 EOF jsr RVEC14 ; do the RAM hook dance
4647 lda DEVNUM ; get device number
4648 pshs a ; save it (so we can restore it later)
4649 bsr LA5AE ; check the device number (which is in FPA0)
4650 jsr LA3ED ; check validity for reading
4651 LA5DA clrb ; not EOF = 0 (FALSE)
4652 lda DEVNUM ; get device number
4653 beq LA5E4 ; brif keyboard - never EOF
4654 tst CINCTR ; is there anything in the input buffer?
4655 bne LA5E4 ; brif so - not EOF
4656 comb ; set EOF flag to -1 (true)
4657 LA5E4 puls a ; get back original device
4658 sta DEVNUM ; restore it
4659 LA5E8 sex ; sign extend result to 16 bits
4660 jmp GIVABF ; go return the result
4661 ; SKIPF command
4662 SKIPF bsr LA5C5 ; parse file name
4663 bsr LA648 ; look for the file
4664 jsr LA6D1 ; read the file
4665 bne LA619 ; brif error reading file
4666 rts
4667 ; OPEN command
4668 OPEN jsr RVEC0 ; do the RAM hook dance
4669 jsr LB156 ; get file status (input/output)
4670 jsr LB6A4 ; get first character of status string
4671 pshs b ; save status
4672 bsr LA5A2 ; parse a comma then the device number
4673 jsr SYNCOMMA ; make sure there's a comma
4674 bsr LA5C5 ; parse the file name
4675 lda DEVNUM ; get device number of the file
4676 clr DEVNUM ; reset actual device to the screen
4677 puls b ; get back status
4678 cmpb #'I ; INPUT?
4679 beq LA624 ; brif so - open a file for INPUT
4680 cmpb #'O ; OUTPUT?
4681 beq LA658 ; brif so - open a file for OUTPUT
4682 LA616 ldb #21*2 ; raise FM error
4683 skip2
4684 LA619 ldb #20*2 ; raise I/O error
4685 skip2
4686 LA61C ldb #18*2 ; raise AO error
4687 skip2
4688 LA61F ldb #19*2 ; raise DN error
4689 jmp LAC46
4690 LA624 inca ; are we opening the tape?
4691 bmi LA616 ; brif printer - FM error; printer can't be opened for READ
4692 bne LA657 ; brif screen - screen is always open
4693 bsr LA648 ; read header block
4694 lda CASBUF+9 ; clear A if binary or machine language file
4695 anda CASBUF+10
4696 beq LA616 ; bad file mode if not data file
4697 inc FILSTA ; open file for input
4698 LA635 jsr LA701 ; start tape, read block
4699 bne LA619 ; brif error during read
4700 tst BLKTYP ; check block type
4701 beq LA619 ; brif header block - something's wrong
4702 bmi LA657 ; brif EOF
4703 lda BLKLEN ; get length of block
4704 beq LA635 ; brif empty block - read another
4705 LA644 sta CINCTR ; set buffer count
4706 bra LA652 ; reset buffer pointer
4707 LA648 tst FILSTA ; is the file open?
4708 bne LA61C ; brif so - AO error
4709 bsr LA681 ; search for file
4710 bne LA619 ; brif error on read
4711 LA650 clr CINCTR ; mark buffer empty
4712 LA652 ldx #CASBUF ; set buffer pointer to start of buffer
4713 stx CINPTR
4714 LA657 rts
4715 LA658 inca ; check for tape device
4716 bne LA657 ; brif not tape (nothing doing - it's always open)
4717 inca ; make file type 1
4718 LA65C ldx #0xffff ; ASCII and data mode
4719 LA65F tst FILSTA ; is file open?
4720 bne LA61C ; brif so - raise error
4721 ldu #CASBUF ; point to tape buffer
4722 stu CBUFAD ; set address of block to write
4723 sta 8,u ; set file type
4724 stx 9,u ; set ASCII flag and mode
4725 ldx #CFNBUF+1 ; point to file name
4726 jsr LA598 ; move file name to the tape buffer
4727 clr BLKTYP ; set for header block
4728 lda #15 ; 15 bytes in a header block
4729 sta BLKLEN ; set block length
4730 jsr LA7E5 ; write the block
4731 lda #2 ; set file type to output
4732 sta FILSTA
4733 bra LA650 ; reset file pointers
4734 ; Search for correct cassette file name
4735 LA681 ldx #CASBUF ; point to cassette buffer
4736 stx CBUFAD ; set location to read blocks to
4737 LA686 lda CURLIN ; are we in immediate mode?
4738 inca
4739 bne LA696 ; brif not
4740 jsr LA928 ; clear screen
4741 ldx CURPOS ; get start of screen (set after clear)
4742 ldb #'S ; for "searching"
4743 stb ,x++ ; put it on the screen
4744 stx CURPOS ; save cursor position to be one past the search indicator
4745 LA696 bsr LA701 ; read a block
4746 orb BLKTYP ; merge error flag with block type
4747 bne LA6D0 ; brif error or not header
4748 ldx #CASBUF ; point to block just read
4749 ldu #CFNBUF+1 ; point to the desired name
4750 ldb #8 ; compare 8 characters
4751 clr ,-s ; set flag to "match"
4752 LA6A6 lda ,x+ ; get character from just read block
4753 ldy CURLIN ; immediate mode?
4754 leay 1,y
4755 bne LA6B4 ; brif not
4756 clr DEVNUM ; set output to screen
4757 jsr PUTCHR ; display character
4758 LA6B4 suba ,u+ ; subtract from desired file name (nonzero if no match)
4759 ora ,s ; merge with match flag
4760 sta ,s ; save new match flag (will be nonzero if any character differs)
4761 decb ; done all characters?
4762 bne LA6A6 ; brif not - do another
4763 lda ,s+ ; get match flag (and set flags)
4764 beq LA6CB ; brif we have a match
4765 tst -9,u ; did we actually have a file name or will any file do?
4766 beq LA6CB ; brif any file will do
4767 bsr LA6D1 ; go read past the file
4768 bne LA6D0 ; return on error
4769 bra LA686 ; keep looking
4770 LA6CB lda #'F ; for "found"
4771 bsr LA6F8 ; put "F" on screen
4772 clra ; set Z to indicat eno errors
4773 LA6D0 rts
4774 LA6D1 tst CASBUF+10 ; check type of file
4775 bne LA6DF ; brif "blocked" file
4776 jsr CASON ; turn on tape
4777 LA6D9 bsr GETBLK ; read a block
4778 bsr LA6E5 ; error or EOF?
4779 bra LA6D9 ; read another block
4780 LA6DF bsr LA701 ; read a single block
4781 bsr LA6E5 ; error or EOF?
4782 bra LA6DF ; read another block
4783 LA6E5 bne LA6ED ; got error reading block
4784 lda BLKTYP ; check block type
4785 nega ; A is 0 now if EOF
4786 bmi LA700 ; brif not end of file
4787 deca ; clear error indicator
4788 LA6ED sta CSRERR ; set error flag
4789 leas 2,s ; don't return to original caller
4790 bra LA705 ; turn off motor and return
4791 LA6F3 lda VIDRAM ; get first char on screen
4792 eora #0x40 ; flip case
4793 LA6F8 ldb CURLIN ; immediate mode?
4794 incb
4795 bne LA700 ; brif not
4796 sta VIDRAM ; save flipped case character
4797 LA700 rts
4798 ; Read a single block from tape (for a "blocked" file)
4799 LA701 bsr CASON ; start tape going
4800 bsr GETBLK ; read block
4801 LA705 jsr LA7E9 ; stop tape
4802 ldb CSRERR ; get error status
4803 rts
4804 ; Read a block from tape - this does the heavy lifting
4805 GETBLK orcc #0x50 ; disable interrupts (timing is important)
4806 bsr LA6F3 ; reverse video of upper left character in direct mode
4807 ldx CBUFAD ; point to destination buffer
4808 clra ; reset read byte
4809 LA712 bsr LA755 ; read a bit
4810 rora ; move bit into accumulator
4811 cmpa #0x3c ; have we synched on the start of the block data yet?
4812 bne LA712 ; brif not
4813 bsr LA749 ; read block type
4814 sta BLKTYP
4815 bsr LA749 ; get block size
4816 sta BLKLEN
4817 adda BLKTYP ; accumulate checksum
4818 sta CCKSUM ; save current checksum
4819 lda BLKLEN ; get back count
4820 sta CSRERR ; initialize counter; we use this since it will be ovewritten later anyway
4821 beq LA73B ; brif empty block
4822 LA72B bsr LA749 ; read a byte
4823 sta ,x ; save in buffer
4824 cmpa ,x+ ; make sure it wrote
4825 bne LA744 ; brif error if it didn't match
4826 adda CCKSUM ; accumulate checksum
4827 sta CCKSUM
4828 dec CSRERR ; read all bytes?
4829 bne LA72B ; brif not
4830 LA73B bsr LA749 ; read checksum from tape
4831 suba CCKSUM ; does it match?
4832 beq LA746 ; brif so
4833 lda #1 ; checksum error flag
4834 skip2
4835 LA744 lda #2 ; non-RAM error flag
4836 LA746 sta CSRERR ; save error status
4837 rts
4838 LA749 lda #8 ; read 8 bits
4839 sta CPULWD ; initialize counter
4840 LA74D bsr LA755 ; read a bit
4841 rora ; put it into accumulator
4842 dec CPULWD ; got all 8 bits?
4843 bne LA74D ; brif not
4844 rts
4845 LA755 bsr LA75D ; get time between transitions
4846 ldb CPERTM ; get timer
4847 decb
4848 cmpb CMPMID ; set C if timer is below the transition point - high or 1; clear otherwise
4849 rts
4850 LA75D clr CPERTM ; reset timer
4851 tst CBTPHA ; check which phase we synched on
4852 bne LA773 ; brif HI-LO synch
4853 LA763 bsr LA76C ; read input
4854 bcs LA763 ; brif still high
4855 LA767 bsr LA76C ; read input
4856 bcc LA767 ; brif still low
4857 rts
4858 LA76C inc CPERTM ; bump timer
4859 ldb PIA1 ; get input bit to C
4860 rorb
4861 rts
4862 LA773 bsr LA76C ; read input
4863 bcc LA773 ; brif still low
4864 LA777 bsr LA76C ; read output
4865 bcs LA777 ; brif still high
4866 rts
4867 ; Start tape and look for sync bytes
4868 CASON orcc #0x50 ; disable interrupts
4869 bsr LA7CA ; turn on tape
4870 clr CPULWD ; reset timer
4871 LA782 bsr LA763 ; wait for low-high transition
4872 LA784 bsr LA7AD ; wait for it to go low again
4873 bhi LA797 ; brif in range for 1200 Hz
4874 LA788 bsr LA7A7 ; wait for it to go high again
4875 blo LA79B ; brif in range for 2400 Hz
4876 dec CPULWD ; decrement counter (synched on low-high)
4877 lda CPULWD ; get counter
4878 cmpa #-96 ; have we seen 96 1-0-1-0 patterns (48 0x55s)?
4879 LA792 bne LA782 ; brif not - wait some more
4880 sta CBTPHA ; save phase we synched on
4881 rts
4882 LA797 bsr LA7A7 ; wait for it to go high again
4883 bhi LA784 ; brif another 1200 Hz, 2 in a row, try again
4884 LA79B bsr LA7AD ; wait for it to go low again
4885 blo LA788 ; brif another 2400 Hz; go try again for high
4886 inc CPULWD ; bump counter
4887 lda CPULWD ; get counter
4888 suba #96 ; set 0 if we've seen enought 0-1-0-1 patterns (0xaa)
4889 bra LA792 ; set phase and return or keep waiting
4890 LA7A7 clr CPERTM ; reset period timer
4891 bsr LA767 ; wait for high
4892 bra LA7B1 ; set flags on result
4893 LA7AD clr CPERTM ; reset period timer
4894 bsr LA777 ; wait for low
4895 LA7B1 ldb CPERTM ; get period count
4896 cmpb CMP0 ; is it too long for 1200Hz?
4897 bhi LA7BA ; brif so - reset counts
4898 cmpb CMP1 ; set C if 2400Hz, clear C if 1200 Hz
4899 rts
4900 LA7BA clr CPULWD ; reset sync counter (too slow or drop out)
4901 rts
4902 ; MOTOR command
4903 MOTOR tfr a,b ; save ON/OFF
4904 jsr GETNCH ; eat the ON/OFF token
4905 cmpb #0xaa ; OFF?
4906 beq LA7E9 ; brif so - turn off tape
4907 cmpb #0x88 ; ON?
4908 jsr LA5C9 ; SN error if no match
4909 ; Turn on tape
4910 LA7CA lda PIA1+1 ; get motor control value
4911 ora #8 ; turn on bit 3 (starts motor)
4912 bsr LA7F0 ; put it back (dumb but it saves a byte)
4913 LA7D1 ldx ZERO ; maximum delay timer
4914 LA7D3 leax -1,x ; count down
4915 bne LA7D3 ; brif not at 0 yet
4916 rts
4917 ; Write a synch leader to tape
4918 WRLDR orcc #0x50 ; disable interrupts
4919 bsr LA7CA ; turn on tape
4920 ldx SYNCLN ; get count of 0x55s to write
4921 LA7DE bsr LA828 ; write a 0x55
4922 leax -1,x ; done?
4923 bne LA7DE ; brif not
4924 rts
4925 ; Write sync bytes and a block, then stop tape
4926 LA7E5 bsr WRLDR ; write sync
4927 LA7E7 bsr SNDBLK ; write block
4928 ; Turn off tape
4929 LA7E9 andcc #0xaf ; enable interrupts
4930 lda PIA1+1 ; get control register
4931 anda #0xf7 ; disable motor bit
4932 LA7F0 sta PIA1+1 ; set motor enable bit
4933 rts
4934 ; Write a block to tape.
4935 SNDBLK orcc #0x50 ; disable interrupts
4936 ldb BLKLEN ; get block size
4937 stb CSRERR ; initialize character counter
4938 lda BLKLEN ; initialize checksum
4939 beq LA805 ; brif empty block
4940 ldx CBUFAD ; point to tape buffer
4941 LA800 adda ,x+ ; accumulate checksum
4942 decb ; end of block data?
4943 bne LA800 ; brif not
4944 LA805 adda BLKTYP ; accumulate block type into checksum
4945 sta CCKSUM ; save calculated checksum
4946 ldx CBUFAD ; point to buffer
4947 bsr LA828 ; send a 0x55
4948 lda #0x3c ; and then a 0x3c
4949 bsr LA82A
4950 lda BLKTYP ; send block type
4951 bsr LA82A
4952 lda BLKLEN ; send block size
4953 bsr LA82A
4954 tsta ; empty block?
4955 beq LA824 ; brif so
4956 LA81C lda ,x+ ; send character from block data
4957 bsr LA82A
4958 dec CSRERR ; are we done yet?
4959 bne LA81C ; brif not
4960 LA824 lda CCKSUM ; send checksum
4961 bsr LA82A
4962 LA828 lda #0x55 ; send a 0x55
4963 LA82A pshs a ; save output byte
4964 ldb #1 ; initialize bit probe
4965 LA82E lda CLSTSN ; get ending value of last cycle
4966 sta PIA1 ; set DA
4967 ldy #LA85C ; point to sine wave table
4968 bitb ,s ; is bit set?
4969 bne LA848 ; brif so - do high frequency
4970 LA83B lda ,y+ ; get next sample (use all for low frequency)
4971 cmpy #LA85C+36 ; end of table?
4972 beq LA855 ; brif so
4973 sta PIA1 ; set output sample
4974 bra LA83B ; do another sample
4975 LA848 lda ,y++ ; get next sample (use every other for high frequency)
4976 cmpy #LA85C+36 ; end of table?
4977 beq LA855 ; brif so
4978 sta PIA1 ; send output sample
4979 bra LA848 ; do another sample
4980 LA855 sta CLSTSN ; save last sample that *would* have been sent
4981 lslb ; shift mask to next bit
4982 bcc LA82E ; brif not done all 8 bits
4983 puls a,pc ; get back original character and return
4984 ; This is the sample table for the tape sine wave
4985 LA85C fcb 0x82,0x92,0xaa,0xba,0xca,0xda
4986 fcb 0xea,0xf2,0xfa,0xfa,0xfa,0xf2
4987 fcb 0xea,0xda,0xca,0xba,0xaa,0x92
4988 fcb 0x7a,0x6a,0x52,0x42,0x32,0x22
4989 fcb 0x12,0x0a,0x02,0x02,0x02,0x0a
4990 fcb 0x12,0x22,0x32,0x42,0x52,0x6a
4991 ; SET command
4992 SET bsr LA8C1 ; get absolute screen position of graphics block
4993 pshs x ; save character location
4994 jsr LB738 ; evaluate comma then expression in B
4995 puls x ; get back character pointer
4996 cmpb #8 ; valid colour?
4997 bhi LA8D5 ; brif not
4998 decb ; normalize colours
4999 bmi LA895 ; brif colour 0 (use current colour)
5000 lda #0x10 ; 16 patterns per colour
5001 mul
5002 bra LA89D ; go save the colour
5003 LA895 ldb ,x ; get current value
5004 bpl LA89C ; brif not grahpic
5005 andb #0x70 ; keep only the colour
5006 skip1
5007 LA89C clrb ; reset block to all black
5008 LA89D pshs b ; save colour
5009 bsr LA90D ; force a )
5010 lda ,x ; get current screen value
5011 bmi LA8A6 ; brif graphic block already
5012 clra ; force all pixels off
5013 LA8A6 anda #0x0f ; keep only pixel data
5014 ora GRBLOK ; set the desired pixel
5015 ora ,s+ ; merge with desired colour
5016 LA8AC ora #0x80 ; force it to be a graphic block
5017 sta ,x ; put new block on screen
5018 rts
5019 ; RESET command
5020 RESET bsr LA8C1 ; get address of desired block
5021 bsr LA90D ; force a )
5022 clra ; zero block (no pixels)
5023 ldb ,x ; is it graphics?
5024 bpl LA8AC ; brif not - just blank the block
5025 com GRBLOK ; invert pixel data
5026 andb GRBLOK ; turn off the desired pixel
5027 stb ,x ; put new pixel data on screen
5028 rts
5029 ; Parse SET/RESET/POINT coordinates except for closing )
5030 LA8C1 jsr LB26A ; make sure it starts with (
5031 LA8C4 jsr RVEC21 ; do the RAM hook dance
5032 jsr EVALEXPB ; get first coordinate
5033 cmpb #63 ; valid horizontal coordinate
5034 bhi LA8D5 ; brif out of range
5035 pshs b ; save horizontal coordinate
5036 jsr LB738 ; look for , followed by vertical coordinate
5037 cmpb #31 ; in range for vertical?
5038 LA8D5 bhi LA948 ; brif not
5039 pshs b ; save vertical coordinate
5040 lsrb ; divide by two (two blocks per row)
5041 lda #32 ; 32 bytes per row
5042 mul ; now we have the offset into video RAM
5043 ldx #VIDRAM ; point to start of screen
5044 leax d,x ; now X points to the correct character row
5045 ldb 1,s ; get horizontal coordinate
5046 lsrb ; divide by two (two per character cell)
5047 abx ; now we're pointing to the correct character cell
5048 puls a,b ; get back coordinates (vertical in A)
5049 anda #1 ; keep only row offset of vertical
5050 rorb ; get column offset of horizontal to C
5051 rola ; now we have "row * 2 + col" in A
5052 ldb #0x10 ; make a bit mask (one bit left of first pixel)
5053 LA8EE lsrb ; move mask right
5054 deca ; at the right pixel?
5055 bpl LA8EE ; brif not
5056 stb GRBLOK ; save graphics block mask
5057 rts
5058 ; POINT function
5059 POINT bsr LA8C4 ; evaluate coordinates
5060 ldb #0xff ; default colour value is -1 (not graphics)
5061 lda ,x ; get character
5062 bpl LA90A ; brif not graphics
5063 anda GRBLOK ; is desired pixel set?
5064 beq LA909 ; brif not - return 0 for "black"
5065 ldb ,x ; get graphics data
5066 lsrb ; shift right 4 to get colour in low bits
5067 lsrb
5068 lsrb
5069 lsrb
5070 andb #7 ; lose the graphics block bias
5071 LA909 incb ; shift colours into 1 to 8 range
5072 LA90A jsr LA5E8 ; convert B to floating point
5073 LA90D jmp LB267 ; make sure we have a ) and return
5074 ; CLS command
5075 CLS jsr RVEC22 ; do the RAM hook dance
5076 LA913 beq LA928 ; brif no colour - just do a basic screen clear
5077 jsr EVALEXPB ; evaluate colour number
5078 cmpb #8 ; valid colour?
5079 bhi LA937 ; brif not - do the easter egg
5080 tstb ; color 0?
5081 beq LA925 ; brif so
5082 decb ; normalize to 0 based colour numbers
5083 lda #0x10 ; 16 blocks per colour
5084 mul ; now we have the base code for that colour
5085 orb #0x0f ; set all pixels
5086 LA925 orb #0x80 ; make it a graphics block
5087 skip2
5088 LA928 ldb #0x60 ; VDG screen space character
5089 ldx #VIDRAM ; point to start of screen
5090 LA92D stx CURPOS ; set cursor position
5091 LA92F stb ,x+ ; blank a character
5092 cmpx #VIDRAM+511 ; end of screen?
5093 bls LA92F ; brif not
5094 rts
5095 LA937 bsr LA928 ; clear te screen
5096 ldx #LA166-1 ; point to the easter egg
5097 jmp STRINOUT ; go display it
5098 ; Evaluate an expression to B, prefixed by a comma, and do FC error if 0
5099 LA93F jsr SYNCOMMA ; force a comma
5100 LA942 jsr EVALEXPB ; evaluate expression to B
5101 tstb ; is it 0?
5102 bne LA984 ; brif not - return
5103 LA948 jmp LB44A ; raise FC error
5104 ; SOUND command
5105 SOUND bsr LA942 ; evaluate frequency
5106 stb SNDTON ; save it
5107 bsr LA93F ; evaluate duration (after a comma)
5108 LA951 lda #4 ; constant factor for duration (each increment is 1/15 of a second)
5109 mul
5110 std SNDDUR ; save length of sound (IRQ will count it down)
5111 lda PIA0+3 ; enable 60 Hz interrupt
5112 ora #1
5113 sta PIA0+3
5114 clr ARYDIS ; clear array disable flag for some reason
5115 bsr LA9A2 ; connect DAC to MUX output
5116 bsr LA976 ; turn on sound
5117 LA964 bsr LA985 ; store mid range output value and delay
5118 lda #0xfe ; store high value and delay
5119 bsr LA987
5120 bsr LA985 ; store mid range value and delay
5121 lda #2 ; store low value and delay
5122 bsr LA987
5123 ldx SNDDUR ; has timer expired?
5124 bne LA964 ; brif not, do another wave
5125 ; Disable sound output
5126 LA974 clra ; bit 3 to 0 will disable output
5127 skip2
5128 ; Enable sound output
5129 LA976 lda #8 ; bit 3 set to enable output
5130 sta ,-s ; save desired value
5131 lda PIA1+3 ; get control register value
5132 anda #0xf7 ; reset value
5133 ora ,s+ ; set to desired value
5134 sta PIA1+3 ; set new sound output status
5135 LA984 rts
5136 LA985 lda #0x7e ; mid range value for DAC
5137 LA987 sta PIA1 ; set DAC output value
5138 lda SNDTON ; get frequency
5139 LA98C inca ; increment it (gives shorter count with higher values, so higher frequencies work)
5140 bne LA98C ; brif not done yet
5141 rts
5142 ; AUDIO command
5143 AUDIO tfr a,b ; save ON/OFF token
5144 jsr GETNCH ; munch the ON/OFF token
5145 cmpb #0xaa ; OFF?
5146 beq LA974 ; brif so
5147 subb #0x88 ; ON?
5148 jsr LA5C9 ; do SN error if not
5149 incb ; now B is 1 - cassette sound source
5150 bsr LA9A2 ; set MUX input to tape
5151 bra LA976 ; enable sound
5152 ; Set MUX source to value in B
5153 LA9A2 ldu #PIA0+1 ; point to PIA0 control register A
5154 bsr LA9A7 ; program bit 0 then fall through for bit 1
5155 LA9A7 lda ,u ; get control register value
5156 anda #0xf7 ; reset mux control bit
5157 asrb ; shift desired value to C
5158 bcc LA9B0 ; brif this bit is clear
5159 ora #8 ; set the bit
5160 LA9B0 sta ,u++ ; set register value and move to next register
5161 rts
5162 ; IRQ service routine
5163 BIRQSV lda PIA0+3 ; check for VSYNC interrupt
5164 bpl LA9C5 ; brif not - return. BUG: should clear HSYNC interrupt status first
5165 lda PIA0+2 ; clear VSYNC interrupt status
5166 LA9BB ldx >SNDDUR ; are we counting down for SOUND? (force extended in case DP is modified)
5167 beq LA9C5 ; brif not
5168 leax -1,x ; count down one tick
5169 stx >SNDDUR ; save new count (forced extended in case DP is modified)
5170 LA9C5 rti
5171 ; JOYSTK function
5172 JOYSTK jsr LB70E ; evaluate which joystick axis is desired
5173 cmpb #3 ; valid axis?
5174 lbhi LB44A ; brif not
5175 tstb ; want axis 0?
5176 bne LA9D4 ; brif not
5177 bsr GETJOY ; read axis data if axis 0
5178 LA9D4 ldx #POTVAL ; point to axis values
5179 ldb FPA0+3 ; get desired axis
5180 ldb b,x ; get axis value
5181 jmp LB4F3 ; return value
5182 ; Read all four joystick axes. Note that this routine will try 10 times to get a value that matches
5183 ; the value obtained during the *previous call to this routine*. Thus, if the axis value has changed,
5184 ; this routine will do the read *ten times* before just returning the last value. This is assininely
5185 ; slow and probably a bug since it seems more logical to look for two matching reads in a row. Note
5186 ; also that this routine should be using PSHS and PULS but it doesn't.
5187 GETJOY bsr LA974 ; turn off sound
5188 ldx #POTVAL+4 ; point to the end of the axis data (we'll work backwards)
5189 ldb #3 ; start with axis 3
5190 LA9E5 lda #10 ; 10 tries to see if we match *the last call* to this routine
5191 std ,--s ; save retry counter and axis number
5192 bsr LA9A2 ; set MUX for the correct axis
5193 LA9EB ldd #0x4080 ; set initial trial value to mid range and the next difference to add/subtract to half
5194 LA9EE sta ,-s ; store the add/subtract value
5195 orb #2 ; keep rs232 output marking
5196 stb PIA1 ; set DAC output to the trial value
5197 eorb #2 ; remove RS232 output value
5198 lda PIA0 ; read the comparator
5199 bmi LA9FF ; brif comparator output is high (DAC is lower than the axis value)
5200 subb ,s ; subtract next bit value (split the difference toward 0)
5201 skip2
5202 LA9FF addb ,s ; add next bit value (split the different toward infinity)
5203 lda ,s+ ; get bit value back
5204 lsra ; cut in half
5205 cmpa #1 ; have we done that last value for the DAC?
5206 bne LA9EE ; brif not
5207 lsrb ; normalize the axis value
5208 lsrb
5209 cmpb -1,x ; does it match the read from the last call to this routine?
5210 beq LAA12 ; brif so
5211 dec ,s ; are we out of retries?
5212 bne LA9EB ; brif not - try again
5213 LAA12 stb ,-x ; save new value and move pointer back
5214 ldd ,s++ ; get axis counter and clean up retry counter
5215 decb ; move to next axis
5216 bpl LA9E5 ; brif still more axes to do
5217 rts
5218 ; This is the "bottom half" of the character fetching routines.
5219 BROMHK cmpa #'9+1 ; is it >= colon?
5220 bhs LAA28 ; brif so Z set if colon, C clear.
5221 cmpa #0x20 ; space?
5222 bne LAA24 ; brif not
5223 jmp GETNCH ; move on to another character if space
5224 LAA24 suba #'0 ; normalize ascii digit to 0-9; we already handled above digit 9
5225 suba #-'0 ; this will cause a carry for any value that was already positive
5226 LAA28 rts
5227 ; Jump table for functions
5228 LAA29 fdb SGN ; SGN 0x80
5229 fdb INT ; INT 0x81
5230 fdb ABS ; ABS 0x82
5231 fdb USRJMP ; USR 0x83
5232 fdb RND ; RND 0x84
5233 fdb SIN ; SIN 0x85
5234 fdb PEEK ; PEEK 0x86
5235 fdb LEN ; LEN 0x87
5236 fdb STR ; STR$ 0x88
5237 fdb VAL ; VAL 0x89
5238 fdb ASC ; ASC 0x8a
5239 fdb CHR ; CHR$ 0x8b
5240 fdb EOF ; EOF 0x8c
5241 fdb JOYSTK ; JOYSTK 0x8d
5242 fdb LEFT ; LEFT$ 0x8e
5243 fdb RIGHT ; RIGHT$ 0x8f
5244 fdb MID ; MID$ 0x90
5245 fdb POINT ; POINT 0x91
5246 fdb INKEY ; INKEY$ 0x92
5247 fdb MEM ; MEM 0x93
5248 ; Operator precedence and jump table (binary ops except relational)
5249 LAA51 fcb 0x79 ; +
5250 fdb LB9C5
5251 fcb 0x79 ; -
5252 fdb LB9BC
5253 fcb 0x7b ; *
5254 fdb LBACC
5255 fcb 0x7b ; /
5256 fdb LBB91
5257 fcb 0x7f ; ^ (exponentiation)
5258 fdb EXPJMP
5259 fcb 0x50 ; AND
5260 fdb LB2D5
5261 fcb 0x46 ; OR
5262 fdb LB2D4
5263 ; Reserved words table for commands
5264 LAA66 fcs 'FOR' ; 0x80
5265 fcs 'GO' ; 0x81
5266 fcs 'REM' ; 0x82
5267 fcs "'" ; 0x83
5268 fcs 'ELSE' ; 0x84
5269 fcs 'IF' ; 0x85
5270 fcs 'DATA' ; 0x86
5271 fcs 'PRINT' ; 0x87
5272 fcs 'ON' ; 0x88
5273 fcs 'INPUT' ; 0x89
5274 fcs 'END' ; 0x8a
5275 fcs 'NEXT' ; 0x8b
5276 fcs 'DIM' ; 0x8c
5277 fcs 'READ' ; 0x8d
5278 fcs 'RUN' ; 0x8e
5279 fcs 'RESTORE' ; 0x8f
5280 fcs 'RETURN' ; 0x90
5281 fcs 'STOP' ; 0x91
5282 fcs 'POKE' ; 0x92
5283 fcs 'CONT' ; 0x93
5284 fcs 'LIST' ; 0x94
5285 fcs 'CLEAR' ; 0x95
5286 fcs 'NEW' ; 0x96
5287 fcs 'CLOAD' ; 0x97
5288 fcs 'CSAVE' ; 0x98
5289 fcs 'OPEN' ; 0x99
5290 fcs 'CLOSE' ; 0x9a
5291 fcs 'LLIST' ; 0x9b
5292 fcs 'SET' ; 0x9c
5293 fcs 'RESET' ; 0x9d
5294 fcs 'CLS' ; 0x9e
5295 fcs 'MOTOR' ; 0x9f
5296 fcs 'SOUND' ; 0xa0
5297 fcs 'AUDIO' ; 0xa1
5298 fcs 'EXEC' ; 0xa2
5299 fcs 'SKIPF' ; 0xa3
5300 fcs 'TAB(' ; 0xa4
5301 fcs 'TO' ; 0xa5
5302 fcs 'SUB' ; 0xa6
5303 fcs 'THEN' ; 0xa7
5304 fcs 'NOT' ; 0xa8
5305 fcs 'STEP' ; 0xa9
5306 fcs 'OFF' ; 0xaa
5307 fcs '+' ; 0xab
5308 fcs '-' ; 0xac
5309 fcs '*' ; 0xad
5310 fcs '/' ; 0xae
5311 fcs '^' ; 0xaf
5312 fcs 'AND' ; 0xb0
5313 fcs 'OR' ; 0xb1
5314 fcs '>' ; 0xb2
5315 fcs '=' ; 0xb3
5316 fcs '<' ; 0xb4
5317 ; Reserved word list for functions
5318 LAB1A fcs 'SGN' ; 0x80
5319 fcs 'INT' ; 0x81
5320 fcs 'ABS' ; 0x82
5321 fcs 'USR' ; 0x83
5322 fcs 'RND' ; 0x84
5323 fcs 'SIN' ; 0x85
5324 fcs 'PEEK' ; 0x86
5325 fcs 'LEN' ; 0x87
5326 fcs 'STR$' ; 0x88
5327 fcs 'VAL' ; 0x89
5328 fcs 'ASC' ; 0x8a
5329 fcs 'CHR$' ; 0x8b
5330 fcs 'EOF' ; 0x8c
5331 fcs 'JOYSTK' ; 0x8d
5332 fcs 'LEFT$' ; 0x8e
5333 fcs 'RIGHT$' ; 0x8f
5334 fcs 'MID$' ; 0x90
5335 fcs 'POINT' ; 0x91
5336 fcs 'INKEY$' ; 0x92
5337 fcs 'MEM' ; 0x93
5338 ; Jump table for commands
5339 LAB67 fdb FOR ; 0x80 FOR
5340 fdb GO ; 0x81 GO
5341 fdb REM ; 0x82 REM
5342 fdb REM ; 0x83 '
5343 fdb REM ; 0x84 ELSE
5344 fdb IFTOK ; 0x85 IF
5345 fdb DATA ; 0x86 DATA
5346 fdb PRINT ; 0x87 PRINT
5347 fdb ON ; 0x88 ON
5348 fdb INPUT ; 0x89 INPUT
5349 fdb ENDTOK ; 0x8a END
5350 fdb NEXT ; 0x8b NEXT
5351 fdb DIM ; 0x8c DIM
5352 fdb READ ; 0x8d READ
5353 fdb RUN ; 0x8e RUN
5354 fdb RESTOR ; 0x8f RESTORE
5355 fdb RETURN ; 0x90 RETURN
5356 fdb STOP ; 0x91 STOP
5357 fdb POKE ; 0x92 POKE
5358 fdb CONT ; 0x93 CONT
5359 fdb LIST ; 0x94 LIST
5360 fdb CLEAR ; 0x95 CLEAR
5361 fdb NEW ; 0x96 NEW
5362 fdb CLOAD ; 0x97 CLOAD
5363 fdb CSAVE ; 0x98 CSAVE
5364 fdb OPEN ; 0x99 OPEN
5365 fdb CLOSE ; 0x9a CLOSE
5366 fdb LLIST ; 0x9b LLIST
5367 fdb SET ; 0x9c SET
5368 fdb RESET ; 0x9d RESET
5369 fdb CLS ; 0x9e CLS
5370 fdb MOTOR ; 0x9f MOTOR
5371 fdb SOUND ; 0xa0 SOUND
5372 fdb AUDIO ; 0xa1 AUDIO
5373 fdb EXEC ; 0xa2 EXEC
5374 fdb SKIPF ; 0xa3 SKIPF
5375 ; Error message table
5376 LABAF fcc 'NF' ; 0 NEXT without FOR
5377 fcc 'SN' ; 1 Syntax error
5378 fcc 'RG' ; 2 RETURN without GOSUB
5379 fcc 'OD' ; 3 Out of data
5380 fcc 'FC' ; 4 Illegal function call
5381 fcc 'OV' ; 5 Overflow
5382 fcc 'OM' ; 6 Out of memory
5383 fcc 'UL' ; 7 Undefined line number
5384 fcc 'BS' ; 8 Bad subscript
5385 fcc 'DD' ; 9 Redimensioned array
5386 fcc '/0' ; 10 Division by 0
5387 fcc 'ID' ; 11 Illegal direct statement
5388 fcc 'TM' ; 12 Type mismatch
5389 fcc 'OS' ; 13 Out of string space
5390 fcc 'LS' ; 14 String too long
5391 fcc 'ST' ; 15 String formula too complex
5392 fcc 'CN' ; 16 Can't continue
5393 fcc 'FD' ; 17 Bad file data
5394 fcc 'AO' ; 18 File already open
5395 fcc 'DN' ; 19 Device number error
5396 fcc 'IO' ; 20 Input/output error
5397 fcc 'FM' ; 21 Bad file mode
5398 fcc 'NO' ; 22 File not open
5399 fcc 'IE' ; 23 Input past end of file
5400 fcc 'DS' ; 24 Direct statement in file
5401 LABE1 fcn ' ERROR'
5402 LABE8 fcn ' IN '
5403 LABED fcb 0x0d
5404 LABEE fcc 'OK'
5405 fcb 0x0d,0x00
5406 LABF2 fcb 0x0d
5407 fcn 'BREAK'
5408 ; Search stack for a FOR/NEXT stack frame. Stop search when something that isn't a FOR/NEXT
5409 ; stack frame is found. Enter with the index variable descriptor pointer in VARDES, or NULL
5410 ; for the first match.
5411 ;
5412 ; NOTE: this routine can be reworked to avoid needed two temporaries by taking advantage of the
5413 ; 6809's registers. This requires some minor tweaks where the routine is called. Further, the
5414 ; use of B is completely pointless and, even if B is going to be used, why is it reloaded on
5415 ; every loop?
5416 LABF9 leax 4,s ; skip past our caller and the main command loop return address
5417 LABFB ldb #18 ; each FOR/NEXT frame is 18 bytes
5418 stx TEMPTR ; save current search pointer
5419 lda ,x ; get first byte of this frame
5420 suba #0x80 ; set to 0 if FOR/NEXT
5421 bne LAC1A ; brif not FOR/NEXT (we hit the end of the stack for a GOSUB frame)
5422 ldx 1,x ; get index variable descriptor
5423 stx TMPTR1 ; save it
5424 ldx VARDES ; get desired index descriptor
5425 beq LAC16 ; brif NULL - we found something
5426 cmpx TMPTR1 ; does this one match?
5427 beq LAC1A ; brif so
5428 ldx TEMPTR ; get back frame pointer
5429 abx ; move to next entry
5430 bra LABFB ; check next block of data
5431 LAC16 ldx TMPTR1 ; get index variable of this frame
5432 stx VARDES ; set it as the one found
5433 LAC1A ldx TEMPTR ; get matching frame pointer
5434 tsta ; set Z if FOR/NEXT
5435 rts
5436 ; This is a block copy routine which copies from top to bottom. It's not clear that the use of
5437 ; this routine actually saves any ROM space compared to just implementing the copies directly
5438 ; once all the marshalling to set up the parameter variables is taken into account.
5439 LAC1E bsr LAC37 ; check to see if stack collides with D
5440 LAC20 ldu V41 ; point to destination
5441 leau 1,u ; offset for pre-dec
5442 ldx V43 ; point to source
5443 leax 1,x ; offset for pre-dec
5444 LAC28 lda ,-x ; get source byte
5445 pshu a ; store at destination (sta ,-u would be less weird)
5446 cmpx V47 ; at the bottom of the copy?
5447 bne LAC28 ; brif not
5448 stu V45 ; save final destination address
5449 LAC32 rts
5450 ; Check for 2*B (0 <= B <= 127) bytes for free memory
5451 LAC33 clra ; zero extend
5452 aslb ; times 2 (loses bit 7 of B)
5453 addd ARYEND ; add to top of used memory
5454 LAC37 addd #STKBUF ; add a fudge factor for interpreter operation
5455 bcs LAC44 ; brif >65535!
5456 sts BOTSTK ; get current stack pointer
5457 cmpd BOTSTK ; is our new address above that?
5458 blo LAC32 ; brif not - no error
5459 LAC44 ldb #6*2 ; raise OM error
5460 ; The error servicing routine
5461 LAC46 jsr RVEC16 ; do the RAM hook dance (ON ERROR reserved hook)
5462 LAC49 jsr RVEC17 ; do the RAM hook dance again
5463 jsr LA7E9 ; turn off tape
5464 jsr LA974 ; disable sound
5465 jsr LAD33 ; reset stack, etc.
5466 clr DEVNUM ; reset output to screen
5467 jsr LB95C ; do a newline
5468 jsr LB9AF ; send a ?
5469 ldx #LABAF ; point to error table
5470 LAC60 abx ; offset to correct message
5471 bsr LACA0 ; send a char from X
5472 bsr LACA0 ; send another char from X
5473 LAC65 ldx #LABE1-1 ; point to "ERROR" message
5474 LAC68 jsr STRINOUT ; print ERROR message (or BREAK)
5475 lda CURLIN ; are we in immediate mode?
5476 inca
5477 beq LAC73 ; brif not - go to immediate mode
5478 jsr LBDC5 ; print "IN ****"
5479 ; This is the immediate mode loop
5480 LAC73 jsr LB95C ; do a newline if needed
5481 LAC76 ldx #LABEE-1 ; point to prompt (without leading CR)
5482 jsr STRINOUT ; show prompt
5483 LAC7C jsr LA390 ; read an input line
5484 ldu #0xffff ; flag immediate mode
5485 stu CURLIN
5486 bcs LAC7C ; brif we ended on BREAK - just go for another line
5487 tst CINBFL ; EOF?
5488 lbne LA4BF ; brif so
5489 stx CHARAD ; save start of input line as input pointer
5490 jsr GETNCH ; get character from input line
5491 beq LAC7C ; brif no input
5492 bcs LACA5 ; brif numeric - adding or removing a line number
5493 ldb #2*24 ; code for "direct statement in file"
5494 tst DEVNUM ; keyboard input?
5495 bne LAC46 ; brif not - complain about direct statement
5496 jsr LB821 ; go tokenize the input line
5497 LAC9D jmp LADC0 ; go execute the newly tokenized line
5498 LACA0 lda ,x+ ; get character and advance pointer
5499 jmp LB9B1 ; output it
5500 LACA5 jsr LAF67 ; convert line number to binary
5501 LACA8 ldx BINVAL ; get converted number
5502 stx LINHDR ; put it before the line we just read
5503 jsr LB821 ; tokenize the input line
5504 stb TMPLOC ; save line length
5505 bsr LAD01 ; find where the line should be in the program
5506 bcs LACC8 ; brif the line number isn't already present
5507 ldd V47 ; get address where the line is in the program
5508 subd ,x ; get the difference between here and the end of the line (negative)
5509 addd VARTAB ; subtract line length from the end of the program
5510 std VARTAB ; save new end of program address
5511 ldu ,x ; get start of next line
5512 LACC0 pulu a ; get source byte (lda ,u+ would be less weird)
5513 sta ,x+ ; move it down
5514 cmpx VARTAB ; have we moved everything yet?
5515 bne LACC0 ; brif not
5516 LACC8 lda LINBUF ; see if there is actually a line to input
5517 beq LACE9 ; brif not - we just needed to remove the line
5518 ldd VARTAB ; get current end of program
5519 std V43 ; set as source pointer
5520 addb TMPLOC ; add in the length of the new line
5521 adca #0
5522 std V41 ; save destination pointer
5523 jsr LAC1E ; make sure there's enough room and then make a hole for the new line
5524 ldu #LINHDR-2 ; point to the line (well, 4 bytes before it, incl line number and fake next line pointer)
5525 LACDD pulu a ; get byte from new line (lda ,u+ would be less weird)
5526 sta ,x+ ; stow it
5527 cmpx V45 ; at the end of the hole we just made?
5528 bne LACDD ; brif not
5529 ldx V41 ; get save new top of program address
5530 stx VARTAB
5531 LACE9 bsr LAD21 ; reset variables, etc.
5532 bsr LACEF ; adjust next line pointers
5533 bra LAC7C ; go read another input line
5534 ; Recompute next line pointers
5535 LACEF ldx TXTTAB ; point to start of program
5536 LACF1 ldd ,x ; get address of next line
5537 beq LAD16 ; brif end of program
5538 leau 4,x ; move past pointer and line number
5539 LACF7 lda ,u+ ; are we at the end of the line?
5540 bne LACF7 ; brif not
5541 stu ,x ; save new next line pointer
5542 ldx ,x ; point to next line
5543 bra LACF1 ; process the next line
5544 ; Find a line in the program
5545 LAD01 ldd BINVAL ; get desired line number
5546 ldx TXTTAB ; point to start of program
5547 LAD05 ldu ,x ; get address of next line
5548 beq LAD12 ; brif end of program
5549 cmpd 2,x ; do we have a match?
5550 bls LAD14 ; brif our search number is <= the number here
5551 ldx ,x ; move to next line
5552 bra LAD05 ; check another line
5553 LAD12 orcc #1 ; set C for not found
5554 LAD14 stx V47 ; save address of matching line *or* line just after where it would have been
5555 LAD16 rts
5556 ; NEW command
5557 ; This routine has multiple entry points used for various "levels" of NEW
5558 NEW bne LAD14 ; brif there was input given; should be LAD16!
5559 LAD19 ldx TXTTAB ; point to start of program
5560 clr ,x+ ; blank out program (with NULL next line pointer)
5561 clr ,x+
5562 stx VARTAB ; save end of program
5563 LAD21 ldx TXTTAB ; get start of program
5564 jsr LAEBB ; put input pointer there
5565 LAD26 ldx MEMSIZ ; reset string space
5566 stx STRTAB
5567 jsr RESTOR ; reset DATA pointer
5568 ldx VARTAB ; clear out scalars and arrays
5569 stx ARYTAB
5570 stx ARYEND
5571 LAD33 ldx #STRSTK ; reset the string stack
5572 stx TEMPPT
5573 ldx ,s ; get return address (we're going to reset the stack)
5574 lds FRETOP ; reset the stack to top of memory
5575 clr ,-s ; put stopper so FOR/NEXT search will actually stop here
5576 LAD3F clr OLDPTR ; reset "CONT" state
5577 clr OLDPTR+1
5578 LAD43 clr ARYDIS ; un-disable arrays
5579 jmp ,x ; return to original caller
5580 ; FOR command
5581 FOR lda #0x80 ; disable array parsing
5582 sta ARYDIS
5583 jsr LET ; assign start value to index
5584 jsr LABF9 ; search stack for matching FOR/NEXT frame
5585 leas 2,s ; lose return address
5586 bne LAD59 ; brif variable not already being used
5587 ldx TEMPTR ; get address of matched data
5588 leas b,x ; move stack pointer to the end of it (B is set to 18 in the stack search)
5589 LAD59 ldb #9 ; is there room for 18 bytes in memory?
5590 jsr LAC33
5591 jsr LAEE8 ; get address of the end of this statement in X
5592 ldd CURLIN ; get line number
5593 pshs x,b,a ; save next line address and current line number
5594 ldb #0xa5 ; make sure we have TO
5595 jsr LB26F
5596 jsr LB143 ; make sure we have a numeric index
5597 jsr LB141 ; evaluate terminal condition value
5598 ldb FP0SGN ; pack FPA0 in place
5599 orb #0x7f
5600 andb FPA0
5601 stb FPA0
5602 ldy #LAD7F ; where to come back to
5603 jmp LB1EA ; stash terminal condition on the stack
5604 LAD7F ldx #LBAC5 ; point to FP 1.0 (default step)
5605 jsr LBC14 ; unpack it to FPA0
5606 jsr GETCCH ; get character after the terminal
5607 cmpa #0xa9 ; is it STEP?
5608 bne LAD90 ; brif not
5609 jsr GETNCH ; eat STEP
5610 jsr LB141 ; evaluate step condition
5611 LAD90 jsr LBC6D ; get "status" of FPA0
5612 jsr LB1E6 ; stash FPA0 on the stack (for step value)
5613 ldd VARDES ; get variable descriptor pointer
5614 pshs d ; put that on the stack too
5615 lda #0x80 ; flag the frame as a FOR/NEXT frame
5616 pshs a
5617 ; Main command interpretation loop
5618 LAD9E jsr RVEC20 ; do the RAM hook dance
5619 andcc #0xaf ; make sure interrupts are running
5620 bsr LADEB ; check for BREAK/pause
5621 ldx CHARAD ; get input pointer
5622 stx TINPTR ; save input pointer for start of line
5623 lda ,x+ ; get current input character
5624 beq LADB4 ; brif end of line - move to another line
5625 cmpa #': ; end of statement?
5626 beq LADC0 ; brif so - keep processing
5627 LADB1 jmp LB277 ; raise a syntax error
5628 LADB4 lda ,x++ ; get MSB of next line pointer and skip past pointer
5629 sta ENDFLG
5630 beq LAE15 ; brif MSB of next line address is 0 (do END)
5631 ldd ,x+ ; get line number but only advance one
5632 std CURLIN ; set current line number
5633 stx CHARAD ; set input pointer to one before line text
5634 LADC0 jsr GETNCH ; move past statement separator or to first character in line
5635 bsr LADC6 ; process a command
5636 LADC4 bra LAD9E ; handle next statement or line
5637 LADC6 beq LAE40 ; return if end of statement
5638 tsta ; is it a token?
5639 lbpl LET ; brif not - do a LET
5640 cmpa #0xa3 ; above SKIPF?
5641 bhi LADDC ; brif so
5642 ldx COMVEC+3 ; point to jump table
5643 LADD4 lsla ; two bytes per entry (loses the token bias)
5644 tfr a,b ; put it in B for unsigned ABX
5645 abx
5646 jsr GETNCH ; move past token
5647 jmp [,x] ; transfer control to the handler (which will return to the main loop)
5648 LADDC cmpa #0xb4 ; is it a non-executable token?
5649 bls LADB1 ; brif so
5650 jmp [COMVEC+13] ; transfer control to ECB command handler
5651 ; RESTORE command
5652 RESTOR ldx TXTTAB ; point to beginning of the program
5653 leax -1,x ; move back one (to compensate for "GETNCH")
5654 LADE8 stx DATPTR ; save as new data pointer
5655 rts
5656 ; BREAK check
5657 LADEB jsr LA1C1 ; read keyboard
5658 beq LADFA ; brif no key down
5659 LADF0 cmpa #3 ; BREAK?
5660 beq STOP ; brif so - do a STOP
5661 LADF4 cmpa #0x13 ; pause (SHIFT-@)?
5662 beq LADFB ; brif so
5663 sta IKEYIM ; cache key for later INKEY$ so break check doesn't break INKEY$
5664 LADFA rts
5665 LADFB jsr KEYIN ; read keyboard
5666 beq LADFB ; brif no key down
5667 bra LADF0 ; process pressed key in case BREAK or SHIFT-@ again
5668 ; END command
5669 ENDTOK jsr LA426 ; close files
5670 jsr GETCCH ; re-get input character
5671 bra LAE0B
5672 ; STOP command
5673 STOP orcc #1 ; flag "STOP"
5674 LAE0B bne LAE40 ; brif not end of statement
5675 ldx CHARAD ; save current input pointer
5676 stx TINPTR
5677 LAE11 ror ENDFLG ; save END/STOP flag (C)
5678 leas 2,s ; lose return address
5679 LAE15 ldx CURLIN ; get current input line (end of program comes here)
5680 cmpx #0xffff ; immediate mode?
5681 beq LAE22 ; brif so
5682 stx OLDTXT ; save line where we stopped executing
5683 ldx TINPTR ; get input pointer
5684 stx OLDPTR ; save location where we stopped executing
5685 LAE22 clr DEVNUM ; reset to screen/keyboard
5686 ldx #LABF2-1 ; point to BREAK message
5687 tst ENDFLG ; are we doing "BREAK"?
5688 lbpl LAC73 ; brif not
5689 jmp LAC68 ; go do the BREAK message and return to main loop
5690 ; CONT command
5691 CONT bne LAE40 ; brif not end of statement
5692 ldb #2*16 ; code for can't continue
5693 ldx OLDPTR ; get saved execution pointer
5694 lbeq LAC46 ; brif no saved pointer - raise CN error
5695 stx CHARAD ; reset input pointer
5696 ldx OLDTXT ; reset current line number
5697 stx CURLIN
5698 LAE40 rts
5699 ; CLEAR command
5700 CLEAR beq LAE6F ; brif no argument
5701 jsr LB3E6 ; evaluate string space size
5702 pshs d ; save it
5703 ldx MEMSIZ ; get memory size (top of memory)
5704 jsr GETCCH ; is there anything after the string space size?
5705 beq LAE5A ; brif not
5706 jsr SYNCOMMA ; force a comma
5707 jsr LB73D ; get top of memory value in X
5708 leax -1,x ; move back one (top of cleared space)
5709 cmpx TOPRAM ; is it within the memory available?
5710 bhi LAE72 ; brif higher than top of memory - OM error
5711 LAE5A tfr x,d ; so we can do math for checking memory usage
5712 subd ,s++ ; subtract out string space value
5713 bcs LAE72 ; brif less than 0
5714 tfr d,u ; U is bottom of cleared space
5715 subd #STKBUF ; also account for slop space
5716 bcs LAE72 ; brif less than 0
5717 subd VARTAB ; is there still room for the program?
5718 blo LAE72 ; brif not
5719 stu FRETOP ; set top of free memory
5720 stx MEMSIZ ; set size of usable memory
5721 LAE6F jmp LAD26 ; erase variables, etc.
5722 LAE72 jmp LAC44 ; raise OM error
5723 ; RUN command
5724 RUN jsr RVEC18 ; do the RAM hook dance
5725 jsr LA426 ; close any open files
5726 jsr GETCCH ; is there a line number
5727 lbeq LAD21 ; brif no line number - start from beginning
5728 jsr LAD26 ; clear variables, etc.
5729 bra LAE9F ; "GOTO" the line number
5730 ; GO command (GOTO and GOSUB)
5731 GO tfr a,b ; save TO/SUB
5732 LAE88 jsr GETNCH ; eat the TO/SUB token
5733 cmpb #0xa5 ; TO?
5734 beq LAEA4 ; brif GOTO
5735 cmpb #0xa6 ; SUB?
5736 bne LAED7 ; brif not
5737 ldb #3 ; room for 6 bytes?
5738 jsr LAC33
5739 ldu CHARAD ; get input pointer
5740 ldx CURLIN ; get line number
5741 lda #0xa6 ; flag for GOSUB frame
5742 pshs u,x,a ; set stack frame
5743 LAE9F bsr LAEA4 ; do "GOTO"
5744 jmp LAD9E ; go back to main loop
5745 ; Actual GOTO is here
5746 LAEA4 jsr GETCCH ; get current input
5747 jsr LAF67 ; convert number to binary
5748 bsr LAEEB ; move input pointer to end of statement
5749 leax 1,x ; point to start of next line
5750 ldd BINVAL ; get desired line number
5751 cmpd CURLIN ; is it beyond here?
5752 bhi LAEB6 ; brif so
5753 ldx TXTTAB ; start search at beginning of program
5754 LAEB6 jsr LAD05 ; find line number
5755 bcs LAED2 ; brif not found
5756 LAEBB leax -1,x ; move to just before start of line
5757 stx CHARAD ; reset input pointer
5758 LAEBF rts
5759 ; RETURN command
5760 RETURN bne LAEBF ; exit if argument given
5761 lda #0xff ; set VARDES to an illegal value so we ignore FOR frames
5762 sta VARDES
5763 jsr LABF9 ; look for a GOSUB frame
5764 tfr x,s ; reset stack
5765 cmpa #0xa6-0x80 ; is it a GOSUB frame?
5766 beq LAEDA ; brif so
5767 ldb #2*2 ; code for RETURN without GOSUB
5768 skip2
5769 LAED2 ldb #7*2 ; code for undefined line number
5770 jmp LAC46 ; raise error
5771 LAED7 jmp LB277 ; raise syntax error
5772 LAEDA puls a,x,u ; get back saved line number and input pointer
5773 stx CURLIN ; reset line number
5774 stu CHARAD ; reset input pointer
5775 ; DATA command
5776 DATA bsr LAEE8 ; move input pointer to end of statement
5777 skip2
5778 ; REM command (also ELSE)
5779 REM bsr LAEEB ; move input pointer to end of line
5780 stx CHARAD ; save new input pointer
5781 LAEE7 rts
5782 ; Return end of statement (LAEE8) or line (AEEB) in X
5783 LAEE8 ldb #': ; colon is statement terminator
5784 skip1lda
5785 LAEEB clrb ; make main terminator NUL
5786 stb CHARAC ; save terminator
5787 clrb ; end of line - always terminates
5788 ldx CHARAD ; get input pointer
5789 LAEF1 tfr b,a ; save secondary terminator
5790 ldb CHARAC ; get main terminator
5791 sta CHARAC ; save secondary
5792 LAEF7 lda ,x ; get input character
5793 beq LAEE7 ; brif end of line
5794 pshs b ; save terminator
5795 cmpa ,s+ ; does it match?
5796 beq LAEE7 ; brif so - bail
5797 leax 1,x ; move pointer ahead
5798 cmpa #'" ; start of string?
5799 beq LAEF1 ; brif so
5800 inca ; functon token?
5801 bne LAF0C ; brif not
5802 leax 1,x ; skip second part of function token
5803 LAF0C cmpa #0x85+1 ; IF?
5804 bne LAEF7 ; brif not
5805 inc IFCTR ; bump "IF" count
5806 bra LAEF7 ; get check another input character
5807 ; IF command
5808 IFTOK jsr LB141 ; evaluate condition
5809 jsr GETCCH ; find out what's after the conditin
5810 cmpa #0x81 ; GO?
5811 beq LAF22 ; treat same as THEN
5812 ldb #0xa7 ; make sure we have a THEN
5813 jsr LB26F
5814 LAF22 lda FP0EXP ; get true/false (false is 0)
5815 bne LAF39 ; brif condition true
5816 clr IFCTR ; reset IF counter
5817 LAF28 bsr DATA ; skip over statement
5818 tsta ; end of line?
5819 beq LAEE7 ; brif so
5820 jsr GETNCH ; get start of this statement
5821 cmpa #0x84 ; ELSE?
5822 bne LAF28 ; brif not
5823 dec IFCTR ; is it a matching ELSE?
5824 bpl LAF28 ; brif not - keep looking
5825 jsr GETNCH ; eat the ELSE
5826 LAF39 jsr GETCCH ; get current input
5827 lbcs LAEA4 ; brif numeric - to a GOTO
5828 jmp LADC6 ; let main loop interpret the next command
5829 ; ON command
5830 ON jsr EVALEXPB ; evaluate index expression
5831 LAF45 ldb #0x81 ; make sure we have "GO"
5832 jsr LB26F
5833 pshs a ; save TO/SUB
5834 cmpa #0xa6 ; SUB?
5835 beq LAF54 ; brif so
5836 cmpa #0xa5 ; TO?
5837 LAF52 bne LAED7 ; brif not
5838 LAF54 dec FPA0+3 ; are we at the right index?
5839 bne LAF5D ; brif not
5840 puls b ; get TO/SUB token
5841 jmp LAE88 ; go do GOTO or GOSUB
5842 LAF5D jsr GETNCH ; munch a character
5843 bsr LAF67 ; parse line number
5844 cmpa #', ; is there another line following?
5845 beq LAF54 ; brif so - see if we're there yet
5846 puls b,pc ; clean up TO/SUB token and return - we fell through
5847 ; Parse a line number
5848 LAF67 ldx ZERO ; initialize line number accumulator to 0
5849 stx BINVAL
5850 LAF6B bcc LAFCE ; brif not numeric
5851 suba #'0 ; adjust to actual value of digit
5852 sta CHARAC ; save digit
5853 ldd BINVAL ; get accumulated number
5854 cmpa #24 ; will this overflow?
5855 bhi LAF52 ; brif so - raise syntax error
5856 aslb ; times 2
5857 rola
5858 aslb ; times 4
5859 rola
5860 addd BINVAL ; times 5
5861 aslb ; times 10
5862 rola
5863 addb CHARAC ; add in digit
5864 adca #0
5865 std BINVAL ; save new accumulated number
5866 jsr GETNCH ; fetch next character
5867 bra LAF6B ; process next digit
5868 ; LET command (the LET keyword requires Extended Basic)
5869 LET jsr LB357 ; evaluate destination variable
5870 stx VARDES ; save descriptor pointer
5871 ldb #0xb3 ; make sure we have =
5872 jsr LB26F
5873 lda VALTYP ; get destination variable type
5874 pshs a ; save it for later
5875 jsr LB156 ; evaluate the expression to assign
5876 puls a ; get back original variable type
5877 rora ; put type in C
5878 jsr LB148 ; make sure the current result matches the type
5879 lbeq LBC33 ; bri fnumeric - copy FPA0 to variable
5880 LAFA4 ldx FPA0+2 ; point to descriptor of replacement string
5881 ldd FRETOP ; get bottom of string space
5882 cmpd 2,x ; is the string already in string space?
5883 bhs LAFBE ; brif so
5884 cmpx VARTAB ; is the descriptor in variable space?
5885 blo LAFBE ; brif not
5886 LAFB1 ldb ,x ; get length of string
5887 jsr LB50D ; allocate space for this string
5888 ldx V4D ; get descriptor pointer back
5889 jsr LB643 ; copy string into string space
5890 ldx #STRDES ; point to temporary string descriptor
5891 LAFBE stx V4D ; save descriptor pointer
5892 jsr LB675 ; remove string from string stack if appropriate
5893 ldu V4D ; get back replacement descriptor
5894 ldx VARDES ; get target descriptor
5895 pulu a,b,y ; get string length (A) and data pointer (Y)
5896 sta ,x ; save new length
5897 sty 2,x ; save new pointer
5898 LAFCE rts
5899 ; READ and INPUT commands.
5900 LAFCF fcc '?REDO' ; The ?REDO message
5901 fcb 0x0d,0x00
5902 LAFD6 ldb #2*17 ; bad file data code
5903 tst DEVNUM ; are we reading from the keyboard?
5904 beq LAFDF ; brif so
5905 LAFDC jmp LAC46 ; raise the error
5906 LAFDF lda INPFLG ; are we doing INPUT?
5907 beq LAFEA ; brif so
5908 ldx DATTXT ; get line number where the DATA statement happened
5909 stx CURLIN ; set current line number to that so can report the correct location
5910 jmp LB277 ; raise a syntax error on bad data
5911 LAFEA ldx #LAFCF-1 ; show the ?REDO if we're doing INPUT
5912 jsr STRINOUT
5913 ldx TINPTR ;* reset input pointer to start of statement (this will cause the
5914 stx CHARAD ;* INPUT statement to be re-executed
5915 rts
5916 INPUT ldb #11*2 ; code for illegal direct statement
5917 ldx CURLIN ; are we in immediate mode?
5918 leax 1,x
5919 beq LAFDC ; brif so - raise ID error
5920 bsr LB002 ; go do the INPUT thing
5921 clr DEVNUM ; reset device to screen/keyboard
5922 rts
5923 LB002 cmpa #'# ; is there a device number?
5924 bne LB00F ; brif not
5925 jsr LA5A5 ; parse device number
5926 jsr LA3ED ; make sure it's valid for input
5927 jsr SYNCOMMA ; make sure we have a comma after the device number
5928 LB00F cmpa #'" ; is there a prompt string?
5929 bne LB01E ; brif not
5930 jsr LB244 ; parse the prompt string
5931 ldb #'; ; make sure we have a semicolon after the prompt
5932 jsr LB26F
5933 jsr LB99F ; print the prompt
5934 LB01E ldx #LINBUF ; point to line input buffer
5935 clr ,x ; NUL first byte to indicate no data
5936 tst DEVNUM ; is it keyboard input?
5937 bne LB049 ; brif not
5938 bsr LB02F ; read a line from the keyboard
5939 ldb #', ; put a comma at the start of the buffer
5940 stb ,x
5941 bra LB049 ; go process some input
5942 LB02F jsr LB9AF ; send a ?
5943 jsr LB9AC ; send a space
5944 LB035 jsr LA390 ; read input from the keyboard
5945 bcc LB03F ; brif not BREAK
5946 leas 4,s ; clean up stack
5947 LB03C jmp LAE11 ; go process BREAK
5948 LB03F ldb #2*23 ; input past end of file error code
5949 tst CINBFL ; was it EOF?
5950 bne LAFDC ; brif so - raise the error
5951 rts
5952 READ ldx DATPTR ; fetch current DATA pointer
5953 skip1lda ; set A to nonzero (for READ)
5954 LB049 clra ; set A to zero (for INPUT)
5955 sta INPFLG ; record whether we're doing READ or INPUT
5956 stx DATTMP ; save current input location
5957 LB04E jsr LB357 ; evaluate a variable (destination of data)
5958 stx VARDES ; save descriptor
5959 ldx CHARAD ; save interpreter input pointer
5960 stx BINVAL
5961 ldx DATTMP ; get data pointer
5962 lda ,x ; is there anything to read?
5963 bne LB069 ; brif so
5964 lda INPFLG ; is it INPUT?
5965 bne LB0B9 ; brif not
5966 jsr RVEC10 ; do the RAM hook dance
5967 jsr LB9AF ; send a ? (so subsequent lines get ??)
5968 bsr LB02F ; go read an input line
5969 LB069 stx CHARAD ; save data pointer
5970 jsr GETNCH ; fetch next data character
5971 ldb VALTYP ; do we want a number?
5972 beq LB098 ; brif so
5973 ldx CHARAD ; get input pointer
5974 sta CHARAC ; save initial character as the delimiter
5975 cmpa #'" ; do we have a string delimiter?
5976 beq LB08B ; brif so - use " as both delimiters
5977 leax -1,x ; back up input if we don't have a delimiter
5978 clra ; set delimiter to NUL (end of line)
5979 sta CHARAC
5980 jsr LA35F ; set up print parameters
5981 tst PRTDEV ; is it a file type device?
5982 bne LB08B ; brif so - use two NULs
5983 lda #': ; use colon as one delimiter
5984 sta CHARAC
5985 lda #', ; and use comma as the other
5986 LB08B sta ENDCHR ; save second terminator
5987 jsr LB51E ; parse out the string
5988 jsr LB249 ; move input pointer past the string
5989 jsr LAFA4 ; assign the string to the variable
5990 bra LB09E ; go see if there's more to read
5991 LB098 jsr LBD12 ; parse a numeric string
5992 jsr LBC33 ; assign the numbe to the variable
5993 LB09E jsr GETCCH ; get current input character
5994 beq LB0A8 ; brif end of line
5995 cmpa #', ; check for comma
5996 lbne LAFD6 ; brif not - we have bad data
5997 LB0A8 ldx CHARAD ; get current data pointer
5998 stx DATTMP ; save the data pointer
5999 ldx BINVAL ; restore the interpreter input pointer
6000 stx CHARAD
6001 jsr GETCCH ; get current input from program
6002 beq LB0D5 ; brif end of statement
6003 jsr SYNCOMMA ; make sure there's a comma between variables
6004 bra LB04E ; go read another item
6005 LB0B9 stx CHARAD ; reset input pointer
6006 jsr LAEE8 ; search for end of statement
6007 leax 1,x ; move past end of statement
6008 tsta ; was it end of line?
6009 bne LB0CD ; brif not
6010 ldb #2*3 ; code for out of data
6011 ldu ,x++ ; get pointer to next line
6012 beq LB10A ; brif end of program - raise OD error
6013 ldd ,x++ ; get line number
6014 std DATTXT ; record it for raising errors in DATA statements
6015 LB0CD lda ,x ; do we have a DATA statement?
6016 cmpa #0x86
6017 bne LB0B9 ; brif not - keep scanning
6018 bra LB069 ; go process the input
6019 LB0D5 ldx DATTMP ; get data pointer
6020 ldb INPFLG ; were we doing READ?
6021 lbne LADE8 ; brif so - save DATA pointer
6022 lda ,x ; is there something after the input in the input buffer?
6023 beq LB0E7 ; brif not - we consumed everything
6024 ldx #LB0E8-1 ; print the ?EXTRA IGNORED message
6025 jmp STRINOUT
6026 LB0E7 rts
6027 LB0E8 fcc '?EXTRA IGNORED'
6028 fcb 0x0d,0x00
6029 ; NEXT command
6030 NEXT bne LB0FE ; brif argument given
6031 ldx ZERO ; set to NULL descriptor pointer
6032 bra LB101 ; go process "any index will do"
6033 LB0FE jsr LB357 ; evaluate the variable
6034 LB101 stx VARDES ; save the index we're looking for
6035 jsr LABF9 ; search the stack for the matching frame
6036 beq LB10C ; brif we found a matching frame
6037 ldb #0 ; code for NEXT without FOR
6038 LB10A bra LB153 ; raise the error
6039 LB10C tfr x,s ; reset the stack to the start of the stack frame
6040 leax 3,x ; point to the STEP value
6041 jsr LBC14 ; copy the value to FPA0
6042 lda 8,s ; get step direction
6043 sta FP0SGN ; save as sign of FPA0
6044 ldx VARDES ; point to index variable
6045 jsr LB9C2 ; add (X) to FPA0 (steps the index)
6046 jsr LBC33 ; save new value to the index
6047 leax 9,s ; point to terminal condition
6048 jsr LBC96 ; compare the new index value with the terminal
6049 subb 8,s ; set B=0 if we hit the terminal (or passed it with nonzero step)
6050 beq LB134 ; brif loop complete
6051 ldx 14,s ; restore line number and input pointer to start of loop
6052 stx CURLIN
6053 ldx 16,s
6054 stx CHARAD
6055 LB131 jmp LAD9E ; return to interpretation loop
6056 LB134 leas 18,s ; remove the frame from the stack
6057 jsr GETCCH ; get character after the index
6058 cmpa #', ; do we have more indexes?
6059 bne LB131 ; brif not
6060 jsr GETNCH ; munch the comma
6061 bsr LB0FE ; go process another value
6062 ; NOTE: despite the BSR on the preceding line, execution of the NEXT command will not fall
6063 ; through this point, nor will the stack grow without bound. The BSR is required to make sure
6064 ; the stack is aligned properly for the stack search for the subsequent index variable.
6065 ;
6066 ; The following is the expression evaluation system. It has various entry points including for type
6067 ; checking. This really consists of two co-routines, one for evaluating operators and one for individual
6068 ; terms. However, it does some rather confusing stack operations so it's a bit difficult to follow
6069 ; just how some of this works.
6070 ;
6071 ; Evaluate numeric expression
6072 LB141 bsr LB156 ; evaluate an expression
6073 ; TM error if string
6074 LB143 andcc #0xfe ; clear C to indicate we want a number
6075 skip2keepc
6076 ; TM error if numeric
6077 LB146 orcc #1 ; set C to indicate we want a string
6078 ; TM error if: C = 1 and number, OR C = 0 and string
6079 LB148 tst VALTYP ; set flags on the current value to (doesn't change C)
6080 bcs LB14F ; brif we want a string
6081 bpl LB0E7 ; brif we have a number (we want a number)
6082 skip2
6083 LB14F bmi LB0E7 ; brif we have a string (we want a string)
6084 LB151 ldb #12*2 ; code for TM error
6085 LB153 jmp LAC46 ; raise the error
6086 ; The general expression evaluation entry point
6087 LB156 bsr LB1C6 ; back up input pointer to compensate for GETNCH below
6088 LB158 clra ; set operator precedence to 0 (no previous operator)
6089 skip2
6090 LB15A pshs b ; save relational operator flags
6091 pshs a ; save previous operator precedence
6092 ldb #1 ; make sure we aren't overflowing the stack
6093 jsr LAC33
6094 jsr LB223 ; go evaluate the first term
6095 LB166 clr TRELFL ; flag no relational operators seen
6096 LB168 jsr GETCCH ; get input character
6097 LB16A suba #0xb2 ; token for > (lowest relational operator)
6098 blo LB181 ; brif below relational operators
6099 cmpa #3 ; there are three relational operators, is it one?
6100 bhs LB181 ; brif not
6101 cmpa #1 ; set C if >
6102 rola ; shift C into bit 0 (4: <, 2: =, 1: >)
6103 eora TRELFL ; flip the bit for this operator
6104 cmpa TRELFL ; did the result get lower?
6105 blo LB1DF ; brif so - we have a duplicate so raise an error
6106 sta TRELFL ; save new operator flags
6107 jsr GETNCH ; munch the operator
6108 bra LB16A ; go see if we have another one
6109 LB181 ldb TRELFL ; do we have a relational comparison?
6110 bne LB1B8 ; brif so
6111 lbcc LB1F4 ; brif the token is above the relational operators
6112 adda #7 ; put operators starting at 0
6113 bhs LB1F4 ; brif we're above 0 - it's an operator, Jim
6114 adca VALTYP ; add carry, numeric flag, and modified token number
6115 lbeq LB60F ; brif we have string and A is + - do concatenation
6116 adca #-1 ; restore operator number
6117 pshs a ; save operator number
6118 asla ; times 2
6119 adda ,s+ ; and times 3 (3 bytes per entry)
6120 ldx #LAA51 ; point to operator pecedence and jump table
6121 leax a,x ; point to correct entry
6122 LB19F puls a ; get precedence of previous operation
6123 cmpa ,x ; is hit higher (or same) than the current one?
6124 bhs LB1FA ; brif so - we need to process that operator
6125 bsr LB143 ; TM error if we have a string
6126 LB1A7 pshs a ; save previous operation precedence
6127 bsr LB1D4 ; push operator handler address and FPA0 onto the stack
6128 ldx RELPTR ; get pointer to arithmetic/logical table entry for last operation
6129 puls a ; get back precedence
6130 bne LB1CE ; brif we had a relational operation
6131 tsta ; check precedence of previous operation
6132 lbeq LB220 ; brif end of expression
6133 bra LB203 ; go handle operation
6134 LB1B8 asl VALTYP ; get type of value to C
6135 rolb ; mix it in to bit 0 of relational flags
6136 bsr LB1C6 ; back up input pointer
6137 ldx #LB1CB ; point to relational operator precedence and handler
6138 stb TRELFL ; save relational comparison flags
6139 clr VALTYP ; result will be numeric
6140 bra LB19F ; to process the operation
6141 LB1C6 ldx CHARAD ; get input pointer
6142 jmp LAEBB ; back it up one and put it back
6143 LB1CB fcb 0x64 ; precedence of relational comparison
6144 fdb LB2F4 ; handler address for relational comparison
6145 LB1CE cmpa ,x ; is last done operation higher (or same) precedence?
6146 bhs LB203 ; brif so - go process it
6147 bra LB1A7 ; go push things on the stack and process this operation otherwise
6148 LB1D4 ldd 1,x ; get address of operatorroutine
6149 pshs d ; save it
6150 bsr LB1E2 ; push FPA0 onto the stack
6151 ldb TRELFL ; get back relational operator flags
6152 lbra LB15A ; go evaluate another operation
6153 LB1DF jmp LB277 ; raise a syntax error
6154 LB1E2 ldb FP0SGN ; get sign of FPA0
6155 lda ,x ; get precedence of this operation
6156 LB1E6 puls y ; get back original caller
6157 pshs b ; save sign
6158 LB1EA ldb FP0EXP ; get exponent
6159 ldx FPA0 ; get mantissa
6160 ldu FPA0+2
6161 pshs u,x,b ; stow FPA0 sign and mantissa
6162 jmp ,y ; return to caller
6163 LB1F4 ldx ZERO ; point to dummy value
6164 lda ,s+ ; get precedence of previous operation (and set flags)
6165 beq LB220 ; brif end of expression
6166 LB1FA cmpa #0x64 ; relational operation?
6167 beq LB201 ; brif so
6168 jsr LB143 ; type mismatch if string
6169 LB201 stx RELPTR ; save pointer to operator routine
6170 LB203 puls b ; get relational flags
6171 cmpa #0x5a ; NOT operation?
6172 beq LB222 ; brif so (it was unary)
6173 cmpa #0x7d ; unary negation?
6174 beq LB222 ; brif so
6175 lsrb ; shift value type flag out of relational flags
6176 stb RELFLG ; save relational operator flag
6177 puls a,x,u ; get FP value back
6178 sta FP1EXP ; set exponent and mantissa in FPA1
6179 stx FPA1
6180 stu FPA1+2
6181 puls b ; and the sign
6182 stb FP1SGN
6183 eorb FP0SGN ; set RESSGN if the two operand signs differ
6184 stb RESSGN
6185 LB220 ldb FP0EXP ; get exponent of FPA0
6186 LB222 rts ; return or transfer control to operator handler routine
6187 LB223 jsr RVEC15 ; do the RAM hook dance
6188 clr VALTYP ; set type to numeric
6189 jsr GETNCH ; get first character in the term
6190 bcc LB22F ; brif not numeric
6191 LB22C jmp LBD12 ; parse a number (and return)
6192 LB22F jsr LB3A2 ; set carry if not alpha
6193 bcc LB284 ; brif alpha character (variable)
6194 cmpa #'. ; decimal point?
6195 beq LB22C ; brif so - evaluate number
6196 cmpa #0xac ; minus?
6197 beq LB27C ; brif so - process unary negation
6198 cmpa #0xab ; plus?
6199 beq LB223 ; brif so - ignore unary "posation"
6200 cmpa #'" ; string delimiter?
6201 bne LB24E ; brif not
6202 LB244 ldx CHARAD ; get input pointer
6203 jsr LB518 ; go parse the string
6204 LB249 ldx COEFPT ; get address of end of string
6205 stx CHARAD ; move input pointer past string
6206 rts
6207 LB24E cmpa #0xa8 ; NOT?
6208 bne LB25F ; brif not
6209 lda #0x5a ; precedence of unary NOT
6210 jsr LB15A ; process the operand of NOT
6211 jsr INTCNV ; convert to integer in D
6212 coma ; do a bitwise complement
6213 comb
6214 jmp GIVABF ; resturn the result
6215 LB25F inca ; is it a function token?
6216 beq LB290 ; brif so
6217 LB262 bsr LB26A ; only other legal thing must be a (expr)
6218 jsr LB156 ; evaluate parentheticized expression
6219 LB267 ldb #') ; force a )
6220 skip2
6221 LB26A ldb #'( ; force a (
6222 skip2
6223 SYNCOMMA ldb #', ; force a ,
6224 LB26F cmpb [CHARAD] ; does character match?
6225 bne LB277 ; brif not
6226 jmp GETNCH ; each the character and return the next
6227 LB277 ldb #2*1 ; raise syntax error
6228 jmp LAC46
6229 LB27C lda #0x7d ; unary negation precedence
6230 jsr LB15A ; evaluate argument
6231 jmp LBEE9 ; flip sign of FPA0 and return
6232 LB284 jsr LB357 ; evaluate variable
6233 LB287 stx FPA0+2 ; save descriptor address in FPA0
6234 lda VALTYP ; test variable type
6235 bne LB222 ; brif string - we're done
6236 jmp LBC14 ; copy FP number from (X) into FPA0
6237 LB290 jsr GETNCH ; get the actual token number
6238 tfr a,b ; save it (for offsetting X)
6239 lslb ; two bytes per jump table entry (and lose high bit)
6240 jsr GETNCH ; eat the token byte
6241 cmpb #2*19 ; is it a valid token for Color Basic?
6242 bls LB29F ; brif so
6243 jmp [COMVEC+18] ; transfer control to Extended Basic if not
6244 LB29F pshs b ; save jump table offset
6245 cmpb #2*14 ; does it expect a numeric argument?
6246 blo LB2C7 ; brif so
6247 cmpb #2*18 ; does it need no arguments?
6248 bhs LB2C9 ; brif so
6249 bsr LB26A ; force a (
6250 lda ,s ; get token value
6251 cmpa #2*17 ; is it POINT?
6252 bhs LB2C9 ; brif so
6253 jsr LB156 ; evaluate first argument string
6254 bsr SYNCOMMA ; force a comma
6255 jsr LB146 ; TM error if string
6256 puls a ; get token value
6257 ldu FPA0+2 ; get string descriptor
6258 pshs u,a ; now we save the first string argument and the token value
6259 jsr EVALEXPB ; evaluate first numeric argument
6260 puls a ; get back token value
6261 pshs b,a ; save second argument and token value
6262 fcb 0x8e ; opcode of LDX immediate (skips two bytes)
6263 LB2C7 bsr LB262 ; force a (
6264 LB2C9 puls b ; get offset
6265 ldx COMVEC+8 ; get jump table pointer
6266 LB2CE abx ; add offset into table
6267 jsr [,x] ; go process function
6268 jmp LB143 ; make sure result is numeric
6269 ; operator OR
6270 LB2D4 skip1lda ; set flag to nonzero to signal OR
6271 ; operator AND
6272 LB2D5 clra ; set flag to zero to signal AND
6273 sta TMPLOC ; save AND/OR flag
6274 jsr INTCNV ; convert second argument to intenger
6275 std CHARAC ; save it
6276 jsr LBC4A ; move first argument to FPA0
6277 jsr INTCNV ; convert first argument to integer
6278 tst TMPLOC ; is it AND or OR?
6279 bne LB2ED ; brif OR
6280 anda CHARAC ; do the bitwise AND
6281 andb ENDCHR
6282 bra LB2F1 ; finish up
6283 LB2ED ora CHARAC ; do the bitwise OR
6284 orb ENDCHR
6285 LB2F1 jmp GIVABF ; return integer result
6286 ; relational comparision operators
6287 LB2F4 jsr LB148 ; TM error if type mismatch
6288 BNE LB309 ; brif we have a string comparison
6289 lda FP1SGN ; pack FPA1
6290 ora #0x7f
6291 anda FPA1
6292 sta FPA1
6293 ldx #FP1EXP ; point to packed FPA1
6294 jsr LBC96 ; compare FPA0 to FPA1
6295 bra LB33F ; handle truth comparison
6296 LB309 clr VALTYP ; the result of a comparison is always a number
6297 dec TRELFL ; remove the string flag from the comparison data
6298 jsr LB657 ; get string details for second argument
6299 stb STRDES ; save them in the temporary string descriptor
6300 stx STRDES+2
6301 ldx FPA1+2 ; get pointer to first argument descriptor
6302 jsr LB659 ; get string details for second argument
6303 lda STRDES ; get length of second argument
6304 pshs b ; save length of first argument
6305 suba ,s+ ; now A is the difference in string lengths
6306 beq LB328 ; brif string lengths are equal
6307 lda #1 ; flag for second argument is longer than first
6308 bcc LB328 ; brif second string is longer than first
6309 ldb STRDES ; get length of second string (shorter)
6310 nega ; invert default comparison result
6311 LB328 sta FP0SGN ; save default truth flag
6312 ldu STRDES+2 ; get pointer to start of second string
6313 incb ; compensate for DECB
6314 LB32D decb ; have we compared everything?
6315 bne LB334 ; brif not
6316 ldb FP0SGN ; get default truth value
6317 bra LB33F ; decide comparison truth
6318 LB334 lda ,x+ ; get byte from first argument
6319 cmpa ,u+ ; compare with second argument
6320 beq LB32D ; brif equal - keep comparing
6321 ldb #0xff ; negative if first string is > second
6322 bcc LB33F ; brif string A > string B
6323 negb ; invert result
6324 LB33F addb #1 ; convert to 0,1,2
6325 rolb ; shift left - now it's 4,2,1 for <, =, >
6326 andb RELFLG ; keep only the truth we care about
6327 beq LB348 ; brif no matching bits - it's false
6328 ldb #0xff ; set true
6329 LB348 jmp LBC7C ; convert result to FP and return it
6330 ; DIM command
6331 LB34B jsr SYNCOMMA ; make sure there's a comma between variables
6332 DIM ldb #1 ; flag that we're dimensioning
6333 bsr LB35A ; go allocate the variable
6334 jsr GETCCH ; are we done?
6335 bne LB34B ; brif not
6336 rts
6337 ; This routine parses a variable. For scalars, it will return a NULL string or 0 value number
6338 ; if it is called from "evaluate term". Otherwise, it allocates the variable. For arrays, it will
6339 ; allocate a default sized array if dimensioning is not underway and then attempt to look up
6340 ; the requested coordinates in that array. Otherwise, it will allocate an array based on the
6341 ; specified dimension values.
6342 LB357 clrb ; flag that we're not setting up an array
6343 jsr GETCCH
6344 LB35A stb DIMFLG ; save dimensioning flag
6345 LB35C sta VARNAM ; save first character of variable name
6346 jsr GETCCH ; get input character (why? we already have it)
6347 bsr LB3A2 ; set carry if not alpha
6348 lbcs LB277 ; brif our variable doesn't start with a letter
6349 clrb ; default second variable character to NUL
6350 stb VALTYP ; set value type to numeric
6351 jsr GETNCH ; get second character
6352 bcs LB371 ; brif numeric - numbers are allowed
6353 bsr LB3A2 ; set carry if not alpha
6354 bcs LB37B ; brif not alpha
6355 LB371 tfr a,b ; save set second character of variable name
6356 LB373 jsr GETNCH ; get an input character
6357 bcs LB373 ; brif numeric - still in variable name
6358 bsr LB3A2 ; set carry if not alpha
6359 bcc LB373 ; brif alpha - still in variable name
6360 LB37B cmpa #'$ ; do we have the string sigil?
6361 bne LB385 ; brif not
6362 com VALTYP ; set value type to string
6363 addb #0x80 ; set bit 7 of second variable character to indicate string
6364 jsr GETNCH ; eat the sigil
6365 LB385 stb VARNAM+1 ; save second variable name character
6366 ora ARYDIS ; merge array disable flag (will set bit 7 of input character if no arrays)
6367 suba #'( ; do we have a subscript?
6368 lbeq LB404 ; brif so
6369 clr ARYDIS ; disable the array disable flag - it's single use
6370 ldx VARTAB ; point to the start of the variable table
6371 ldd VARNAM ; get variable name
6372 LB395 cmpx ARYTAB ; are we at the top of the variable table?
6373 beq LB3AB ; brif so
6374 cmpd ,x++ ; does the variable name match (and move pointer to variable data)
6375 beq LB3DC ; brif so
6376 leax 5,x ; move to next table entry
6377 bra LB395 ; see if we have a match
6378 ; Set carry if not upper case alpha
6379 LB3A2 cmpa #'A ; set C if less than A
6380 bcs LB3AA ; brif less than A
6381 suba #'Z+1 ; set C if greater than Z
6382 suba #-('Z+1)
6383 LB3AA rts
6384 LB3AB ldx #ZERO ; point to empty location (NULL/0 value)
6385 ldu ,s ; get caller address
6386 cmpu #LB287 ; coming from "evaluate term"?
6387 beq LB3DE ; brif so - don't allocate
6388 ldd ARYEND ; get end of arrays
6389 std V43 ; save as top of source block
6390 addd #7 ; 7 bytes per scalar entry
6391 std V41 ; save as top of destination block
6392 ldx ARYTAB ; get bottom of arrays
6393 stx V47 ; save as bottom of source block
6394 jsr LAC1E ; move the arrays up to make a hole
6395 ldx V41 ; get new top of arrays
6396 stx ARYEND ; set new end of arrays
6397 ldx V45 ; get bottom of destination block
6398 stx ARYTAB ; set as new start of arrays
6399 ldx V47 ; get old end of variables
6400 ldd VARNAM ; get name of variable
6401 std ,x++ ; set variable name and advance X to the value
6402 clra ; zero out the variable value
6403 clrb
6404 std ,x
6405 std 2,x
6406 sta 4,x
6407 LB3DC stx VARPTR ; save descriptor address of return value
6408 LB3DE rts
6409 ; Various integer conversion routines
6410 LB3DF fcb 0x90,0x80,0x00,0x00,0x00 ; FP constant -32768
6411 LB3E4 jsr GETNCH ; fetch input character
6412 LB3E6 jsr LB141 ; evaluate numeric expression
6413 LB3E9 lda FP0SGN ; get sign of value
6414 bmi LB44A ; brif negative (raise FC error)
6415 INTCNV jsr LB143 ; TM error if string
6416 lda FP0EXP ; get exponent
6417 cmpa #0x90 ; is it within the range for a 16 bit integer?
6418 blo LB3FE ; brif smaller than 32768
6419 ldx #LB3DF ; point to -32678 constant
6420 jsr LBC96 ; is FPA0 equal to -32768?
6421 bne LB44A ; brif not - magnitude is too far negative
6422 LB3FE jsr LBCC8 ; move binary point to the right of FPA0 and correct sign
6423 ldd FPA0+2 ; get the resulting integer
6424 rts
6425 LB404 ldd DIMFLG ; get dimensioning flag and variable type
6426 pshs b,a ; save them (to avoid issues while evaluating dimension values)
6427 nop ; dead space caused by 1.2 revision
6428 clrb ; reset dimension counter
6429 LB40A ldx VARNAM ; get variable name
6430 pshs x,b ; save dimension counter and variable name
6431 bsr LB3E4 ; evaluate a dimension value (and skip either ( or ,)
6432 puls b,x,y ; get variable name, dimension counter, and dimensioning/type flag
6433 stx VARNAM ; restore variable name
6434 ldu FPA0+2 ; get dimension size/index
6435 pshs u,y ; save dimension size and dimensioning/type flag
6436 incb ; bump dimension counter
6437 jsr GETCCH ; get what's after the dimension count
6438 cmpa #', ; do we have another dimension?
6439 beq LB40A ; brif so - parse it
6440 stb TMPLOC ; save dimension counter
6441 jsr LB267 ; make sure we have a )
6442 puls a,b ; get back variable type and dimensioning flag
6443 std DIMFLG ; restore variable type and dimensioning flag
6444 ldx ARYTAB ; get start of arrays
6445 LB42A cmpx ARYEND ; are we at the end of the array table
6446 beq LB44F ; brif so
6447 ldd VARNAM ; get variable name
6448 cmpd ,x ; does it match?
6449 beq LB43B ; brif so
6450 ldd 2,x ; get length of this array
6451 leax d,x ; move to next array
6452 bra LB42A ; go check another entry
6453 LB43B ldb #2*9 ; code for redimensioned array error
6454 lda DIMFLG ; are we dimensioning?
6455 bne LB44C ; brif so - raise error
6456 ldb TMPLOC ; get number of dimensions given
6457 cmpb 4,x ; does it match?
6458 beq LB4A0 ; brif so
6459 LB447 ldb #8*2 ; raise "bad subscript"
6460 skip2
6461 LB44A ldb #4*2 ; raise "illegal function call"
6462 LB44C jmp LAC46 ; raise error
6463 LB44F ldd #5 ; 5 bytes per array entry
6464 std COEFPT ; initialize array size to entry size
6465 ldd VARNAM ; get variable name
6466 std ,x ; set array name
6467 ldb TMPLOC ; get dimension count
6468 stb 4,x ; set dimension count
6469 jsr LAC33 ; make sure we haven't overflowed memory
6470 stx V41 ; save array descriptor address
6471 LB461 ldb #11 ; default dimension value (zero-based, gives max index of 10)
6472 clra ; zero extend (??? why not LDD above?)
6473 tst DIMFLG ; are we dimensioning?
6474 beq LB46D ; brif not
6475 puls a,b ; get dimension size
6476 addd #1 ; account for zero based indexing
6477 LB46D std 5,x ; save dimension size
6478 bsr LB4CE ; multiply by accumulated array size
6479 std COEFPT ; save new array size
6480 leax 2,x ; move to next dimension
6481 dec TMPLOC ; have we done all dimensions?
6482 bne LB461 ; brif not
6483 stx TEMPTR ; save end of array descriptor (minus 5)
6484 addd TEMPTR ; add total size of array to address of descriptor
6485 lbcs LAC44 ; brif it overflows memory
6486 tfr d,x ; save end of array for later
6487 jsr LAC37 ; does array fit in memory?
6488 subd #STKBUF-5 ; subtract out the "stack fudge factor" but add 5 to the result
6489 std ARYEND ; save new end of arrays
6490 clra ; set up for clearing
6491 LB48C leax -1,x ; move back one
6492 sta 5,x ; blank out a byte in the array data
6493 cmpx TEMPTR ; have we reached the array header?
6494 bne LB48C ; brif not
6495 ldx V41 ; get address of start of descriptor
6496 lda ARYEND ; get MSB of end of array back (B still has LSB)
6497 subd V41 ; subtract start of descriptor
6498 std 2,x ; save length of array in array header
6499 lda DIMFLG ; are we dimensioning?
6500 bne LB4CD ; brif so - we're done
6501 LB4A0 ldb 4,x ; get number of dimensions
6502 stb TMPLOC ; initialize counter
6503 clra ; initialize accumulated offset
6504 clrb
6505 LB4A6 std COEFPT ; save accumulated offset
6506 puls a,b ; get desired index
6507 std FPA0+2 ; save it
6508 cmpd 5,x ; is it in range for this dimension?
6509 bhs LB4EB ; brif not
6510 ldu COEFPT ; get accumulated offset
6511 beq LB4B9 ; brif first dimension
6512 bsr LB4CE ; multiply accumulated offset by dimension length
6513 addd FPA0+2 ; add in offset into this dimension
6514 LB4B9 leax 2,x ; move to next dimension in header
6515 dec TMPLOC ; done all dimensions?
6516 bne LB4A6 ; brif not
6517 std ,--s ; save D for multiply by 5 (should be pshs d)
6518 aslb ; times 2
6519 rola
6520 aslb ; times 4
6521 rola
6522 addd ,s++ ; times 5
6523 leax d,x ; add in offset from start of array data
6524 leax 5,x ; offset to end of header
6525 stx VARPTR ; save pointer to element data
6526 LB4CD rts
6527 ; multiply 16 bit number at 5,x by the 16 bit number in COEFPT; return result in D; BS error if carry
6528 LB4CE lda #16 ; 16 shifts to do a multiply
6529 sta V45 ; save shift counter
6530 ldd 5,x ; get multiplier
6531 std BOTSTK ; save it
6532 clra ; zero out product
6533 clrb
6534 LB4D8 aslb ; shift product left
6535 rola
6536 bcs LB4EB ; brif we have a carry
6537 asl COEFPT+1 ; shift other factor left
6538 rol COEFPT
6539 bcc LB4E6 ; brif no carry - this bit position is 0
6540 addd BOTSTK ; add in multiplier at this bit position
6541 bcs LB4EB ; brif carry - do an error
6542 LB4E6 dec V45 ; have we done all 16 bits?
6543 bne LB4D8 ; brif not
6544 rts
6545 LB4EB jmp LB447 ; raise a BS error
6546 ; MEM function
6547 ; BUG: this doesn't account for the STKBUF fudge factor used for memory availability checks
6548 MEM tfr s,d ; get stack pointer where we can do math
6549 subd ARYEND ; calculate number of bytes between the stack and the top of arrays
6550 skip1 ; return result
6551 ; Convert unsigned value in B to FP
6552 LB4F3 clra ; zero extend
6553 ; Convert signed value in D to FP
6554 GIVABF clr VALTYP ; set value type to numeric
6555 std FPA0 ; save value in FPA0
6556 ldb #0x90 ; exponent for top two bytes to be an integer
6557 jmp LBC82 ; finish conversion to integer
6558 ; STR$ function
6559 STR jsr LB143 ; make sure we have a number
6560 ldu #STRBUF+2 ; convert FP number to string in temporary string buffer
6561 jsr LBDDC
6562 leas 2,s ; don't return to the function evaluator (which will do a numeric type check)
6563 ldx #STRBUF+1 ; point to number string
6564 bra LB518 ; to stash the string in string space and return to the "evaluate term" caller
6565 ; Reserve B bytes of string space. Return start in X and FRESPC
6566 LB50D stx V4D ; save X somewhere in case the caller needs it
6567 LB50F bsr LB56D ; allocate string space
6568 LB511 stx STRDES+2 ; save pointer to allocated space in the temporary descriptor
6569 stb STRDES ; save length in the temporary descriptor
6570 rts
6571 LB516 leax -1,x ; move pointer back one (to compensate for the increment below)
6572 ; Scan from X until either NUL or one of the string terminators is found
6573 LB518 lda #'" ; set terminator to be string delimiter
6574 LB51A sta CHARAC ; set both delimiters
6575 sta ENDCHR
6576 LB51E leax 1,x ; move to next character
6577 stx RESSGN ; save start of string
6578 stx STRDES+2 ; save start of string in the temporary string descriptor
6579 ldb #-1 ; initialize length counter to -1 (compensate for initial INCB)
6580 LB526 incb ; bump string length
6581 lda ,x+ ; get character from string
6582 beq LB537 ; brif end of line
6583 cmpa CHARAC ; is it delimiter #1?
6584 beq LB533 ; brif so
6585 cmpa ENDCHR ; is it delimiter #2?
6586 bne LB526 ; brif not - keep scanning
6587 LB533 cmpa #'" ; string delimiter?
6588 beq LB539 ; brif so - don't move pointer back
6589 LB537 leax -1,x ; move pointer back (so we don't consume the delimiter)
6590 LB539 stx COEFPT ; save end of string address
6591 stb STRDES ; save string length
6592 ldu RESSGN ; get start of string
6593 cmpu #STRBUF+2 ; is it at the start of the string buffer?
6594 bhi LB54C ; brif so - don't copy it to string space
6595 bsr LB50D ; allocate string space
6596 ldx RESSGN ; point to beginning of the string
6597 jsr LB645 ; copy string data (B bytes) from (X) to (FRESPC)
6598 ; Put temporary string descriptor on the string stack
6599 LB54C ldx TEMPPT ; get top of string stack
6600 cmpx #CFNBUF ; is the string stack full?
6601 bne LB558 ; brif not
6602 ldb #15*2 ; code for "string formula too complex"
6603 LB555 jmp LAC46 ; raise error
6604 LB558 lda STRDES ; get string length
6605 sta 0,x ; save it in the string stack descriptor
6606 ldd STRDES+2 ; get string data pointer
6607 std 2,x ; save in string stack descriptor
6608 lda #0xff ; set value type to string
6609 sta VALTYP
6610 stx LASTPT ; set pointer to last used entry on the string stack
6611 stx FPA0+2 ; set pointer to descriptor in the current evaluation value
6612 leax 5,x ; advance string stack pointer
6613 stx TEMPPT
6614 rts
6615 ; Reserve B bytes in string space. If there isn't enough space, try compacting string space and
6616 ; then try the allocation again. If it still fails, raise OS error.
6617 LB56D clr GARBFL ; flag that compaction not yet done
6618 LB56F clra ; zero extend the length
6619 pshs d ; save requested string length
6620 ldd STRTAB ; get current bottom of strings
6621 subd ,s+ ; calculate new bottom of strings and remove zero extension
6622 cmpd FRETOP ; does the string fit?
6623 blo LB585 ; brif not - try compaction
6624 std STRTAB ; save new bottom of strings
6625 ldx STRTAB ; get bottom of strings
6626 leax 1,x ; now X points to the real start of the allocated space
6627 stx FRESPC ; save the string pointer
6628 puls b,pc ; restore length and return
6629 LB585 ldb #2*13 ; code for out of string space
6630 com GARBFL ; have we compacted string space yet?
6631 beq LB555 ; brif so - raise error
6632 bsr LB591 ; compact string space
6633 puls b ; get back string length
6634 bra LB56F ; go try allocation again
6635 ; Compact string space
6636 ; This is an O(n^2) algorithm. It first searches all extant strings for the highest address data pointer
6637 ; that hasn't already been moved into the freshly compacted string space. If then moves that string data
6638 ; up to the highest address it can go to. It repeats this process over and over until it finds no string
6639 ; that isn't already in the compacted space. While doing this, it has to search all strings on the string
6640 ; stack (this is why the string stack is needed - so we can track anonymous strings), all scalar string
6641 ; variables, and *every* entry in every string array.
6642 LB591 ldx MEMSIZ ; get to of string space
6643 LB593 stx STRTAB ; save top of uncompacted stringspace
6644 clra ; zero out D and reset pointer to discovered variable to NULL
6645 clrb
6646 std V4B
6647 ldx FRETOP ; point to bottom of string space
6648 stx V47 ; save as lowest match address (match will be higher)
6649 ldx #STRSTK ; point to start of string stack
6650 LB5A0 cmpx TEMPPT ; are we at the top of the string stack?
6651 beq LB5A8 ; brif so - done with the string stack
6652 bsr LB5D8 ; check for string in uncompacted space (and advance pointer)
6653 bra LB5A0 ; check another on the string stack
6654 LB5A8 ldx VARTAB ; point to start of scalar variables
6655 LB5AA cmpx ARYTAB ; end of scalars?
6656 beq LB5B2 ; brif so
6657 bsr LB5D2 ; check for string in uncompacted space and advance pointer
6658 bra LB5AA ; check another variable
6659 LB5B2 stx V41 ; save address of end of variables (address of first array)
6660 LB5B4 ldx V41 ; get start of the next array
6661 LB5B6 cmpx ARYEND ; end of arrays?
6662 beq LB5EF ; brif so
6663 ldd 2,x ; get length of array
6664 addd V41 ; add to start of array
6665 std V41 ; save address of next array
6666 lda 1,x ; get second character of variable name
6667 bpl LB5B4 ; brif numeric
6668 ldb 4,x ; get number of dimensions
6669 aslb ; two bytes per dimension size
6670 addb #5 ; add in fixed overhead for array descriptor
6671 abx ; now X points to first array element
6672 LB5CA cmpx V41 ; at the start of the next array?
6673 beq LB5B6 ; brif so - go handle another array
6674 bsr LB5D8 ; check for string in uncompacted space (and advance pointer)
6675 bra LB5CA ; process next array element
6676 LB5D2 lda 1,x ; get second character of variable name
6677 leax 2,x ; move to variable data
6678 bpl LB5EC ; brif numeric
6679 LB5D8 ldb ,x ; get length of string
6680 beq LB5EC ; brif NULL - don't need to check data pointer
6681 ldd 2,x ; get data pointer
6682 cmpd STRTAB ; is it in compacted string space?
6683 bhi LB5EC ; brif so
6684 cmpd V47 ; is it better match than previous best?
6685 bls LB5EC ; brif not
6686 stx V4B ; save descriptor address of best match
6687 std V47 ; save new best data pointer match
6688 LB5EC leax 5,x ; move to next descriptor
6689 LB5EE rts
6690 LB5EF ldx V4B ; get descriptor address of the matched string
6691 beq LB5EE ; brif we didn't find one - we're done
6692 clra ; zero extend length
6693 ldb ,x ; get string length
6694 decb ; subtract one (we won't have a NULL string here)
6695 addd V47 ; now D points to the address of the end of the string data
6696 std V43 ; save as top address of move
6697 ldx STRTAB ; set top of uncompacted space as destination
6698 stx V41
6699 jsr LAC20 ; move string to top of uncompactedspace
6700 ldx V4B ; point to string descriptor
6701 ldd V45 ; get new data pointer address
6702 std 2,x ; update descriptor
6703 ldx V45 ; get bottom of copy destination
6704 leax -1,x ; move back below it
6705 jmp LB593 ; go search for another string to move (and set new bottom of string space)
6706 ; Concatenate two strings. We come here directly from the operator handler rather than via a JSR.
6707 LB60F ldd FPA0+2 ; get string descriptor for the first string
6708 pshs d ; save it
6709 jsr LB223 ; evaluate a second string (concatenation is left associative)
6710 jsr LB146 ; make sure we have a string
6711 puls x ; get back first string descriptor
6712 stx RESSGN ; save it
6713 ldb ,x ; get length of first string
6714 ldx FPA0+2 ; get pointer to second string
6715 addb ,x ; add length of second string
6716 bcc LB62A ; brif combined length is OK
6717 ldb #2*14 ; raise string too long error
6718 jmp LAC46
6719 LB62A jsr LB50D ; reserve room for new string
6720 ldx RESSGN ; get descriptor address of the first string
6721 ldb ,x ; get length of first string
6722 bsr LB643 ; copy it to string space
6723 ldx V4D ; get descriptor address of second string
6724 bsr LB659 ; get string details for second string
6725 bsr LB645 ; copy second string into new string space
6726 ldx RESSGN ; get pointer to first string
6727 bsr LB659 ; remove it from the string stack if possible
6728 jsr LB54C ; put new string on the string stack
6729 jmp LB168 ; return to expression evaluator
6730 ; Copy B bytes to space pointed to by FRESPC
6731 LB643 ldx 2,x ; get source address from string descriptor
6732 LB645 ldu FRESPC ; get destination address
6733 incb ; compensate for decb
6734 bra LB64E ; do the copy
6735 LB64A lda ,x+ ; copy a byte
6736 sta ,u+
6737 LB64E decb ; done yet?
6738 bne LB64A ; brif not
6739 stu FRESPC ; save destination pointer
6740 rts
6741 ; Fetch details of string in FPA0+2 and remove from the string stack if possible
6742 LB654 jsr LB146 ; make sure we have a string
6743 LB657 ldx FPA0+2 ; get descriptor pointer
6744 LB659 ldb ,x ; get length of string
6745 bsr LB675 ; see if it's at the top of the string stack and remove it if so
6746 bne LB672 ; brif not removed
6747 ldx 5+2,x ; get start address of string just removed
6748 leax -1,x ; move pointer down 1
6749 cmpx STRTAB ; is it at the bottom of string space?
6750 bne LB66F ; brif not
6751 pshs b ; save length
6752 addd STRTAB ; add length to start of strings (A was cleared previously)
6753 std STRTAB ; save new string space start (deallocated space for this string)
6754 puls b ; get back string length
6755 LB66F leax 1,x ; restore pointer to pointing at the actual string data
6756 rts
6757 LB672 ldx 2,x ; get data pointer for the string
6758 rts
6759 ; Remove string pointed to by X from the string stack if it is at the top of the stack; return with
6760 ; A clear and Z set if string removed
6761 LB675 cmpx LASTPT ; is it at the top of the string stack?
6762 bne LB680 ; brif not - do nothing
6763 stx TEMPPT ; save new top of stack
6764 leax -5,x ; move the "last" pointer back as well
6765 stx LASTPT
6766 clra ; flag string removed
6767 LB680 rts
6768 ; LEN function
6769 LEN bsr LB686 ; get string details
6770 LB683 jmp LB4F3 ; return unsigned length in B
6771 LB686 bsr LB654 ; get string details and remove from string stack
6772 clr VALTYP ; set value type to numeric
6773 tstb ; set flags according to length
6774 rts
6775 ; CHR$ function
6776 CHR jsr LB70E ; get 8 bit unsigned integer to B
6777 LB68F ldb #1 ; allocate a one byte string
6778 jsr LB56D
6779 lda FPA0+3 ; get character code
6780 jsr LB511 ; save reserved string details in temp descriptor
6781 sta ,x ; put character in string
6782 LB69B leas 2,s ; don't go back to function handler - avoid numeric type check
6783 LB69D jmp LB54C ; return temporary string on string stack
6784 ; ASC function
6785 ASC bsr LB6A4 ; get first character of argument
6786 bra LB683 ; return unsigned code in B
6787 LB6A4 bsr LB686 ; fetch string details
6788 beq LB706 ; brif NULL string
6789 ldb ,x ; get character at start of string
6790 rts
6791 ; LEFT$ function
6792 LEFT bsr LB6F5 ; get arguments from the stack
6793 LB6AD clra ; clear pointer offset (set to start of string)
6794 LB6AE cmpb ,x ; are we asking for more characters than there are in the string?
6795 bls LB6B5 ; brif not
6796 ldb ,x ; only return the number that are in the string
6797 clra ; force starting offset to be the start of the string
6798 LB6B5 pshs b,a ; save offset and length
6799 jsr LB50F ; reserve space in string space
6800 ldx V4D ; point to original string descriptor
6801 bsr LB659 ; get string details
6802 puls b ; get string offset
6803 abx ; now X points to the start of the data to copy
6804 puls b ; get length of copy
6805 jsr LB645 ; copy the data to the allocated space
6806 bra LB69D ; return temp string on string stack
6807 ; RIGHT$ function
6808 RIGHT bsr LB6F5 ; get arguments from stack
6809 suba ,x ; subtract length of original string from desired length
6810 nega ; now A is offset into old string where we start copying
6811 bra LB6AE ; go handle everything else
6812 ; MID$ function
6813 MID ldb #255 ; default length is the whole string
6814 stb FPA0+3 ; save it
6815 jsr GETCCH ; see what we have after offset
6816 cmpa #') ; end of function?
6817 beq LB6DE ; brif so - no length
6818 jsr SYNCOMMA ; force a comma
6819 bsr EVALEXPB ; get length parameter
6820 LB6DE bsr LB6F5 ; get string and offset parameters from the stack
6821 beq LB706 ; brif we have a 0 offset requested (string offsets are 1-based)
6822 clrb ; clear length counter
6823 deca ; subtract one from position parameter (we work on 0-based, param is 1-based)
6824 cmpa ,x ; is start greater than length of string?
6825 bhs LB6B5 ; brif so - return NULL string
6826 tfr a,b ; save absolute position parameter
6827 subb ,x ; now B is postition less length
6828 negb ; now B is amount of string to copy
6829 cmpb FPA0+3 ; is it less than the length requested?
6830 bls LB6B5 ; brif so
6831 ldb FPA0+3 ; set length to the requested length
6832 bra LB6B5 ; go finish up copying the substring
6833 ; Common routine for LEFT$, RIGHT$, MID$ - check for ) and fetch string data and first parameter
6834 ; from the stack. These were evaluated in the function evaluation handler. (It's not clear that doing
6835 ; it that way is actually beneficial. However, this is what the ROM designers did, so here we are.)
6836 LB6F5 jsr LB267 ; make sure we have )
6837 ldu ,s ; get return address - we're going to mess with the stack
6838 ldx 5,s ; get address of string descriptor
6839 stx V4D ; save descriptor adddress
6840 lda 4,s ; get first numeric parameter in both A and B
6841 ldb 4,s
6842 leas 7,s ; clean up stack
6843 tfr u,pc ; return to original caller
6844 LB706 jmp LB44A ; raise FC error
6845 ; Evaluate an unsigned 8 bit expression to B
6846 LB709 jsr GETNCH ; move to next character
6847 EVALEXPB jsr LB141 ; evaluate a numeric expression
6848 LB70E jsr LB3E9 ; convert to integer in D
6849 tsta ; are we negative or > 255?
6850 bne LB706 ; brif so - FC error
6851 jmp GETCCH ; fetch current input character and return
6852 ; VAL function
6853 VAL jsr LB686 ; get string details
6854 lbeq LBA39 ; brif NULL string - return 0
6855 ldu CHARAD ; get input pointer so we can replace it later
6856 stx CHARAD ; point interpreter at string data
6857 abx ; calculate end address of the string
6858 lda ,x ; get byte after the end of the string
6859 pshs u,x,a ; save end of string address, input pointer, and character after end of string
6860 clr ,x ; put a NUL after the string (stops the number interpreter)
6861 jsr GETCCH ; get input character at start of string
6862 jsr LBD12 ; evaluate numeric expression in string
6863 puls a,x,u ; get back saved character and pointers
6864 sta ,x ; restore byte after string
6865 stu CHARAD ; restore interpeter's input pointer
6866 rts
6867 ; Evaluate unsigned expression to BINVAL, then evaluate an unsigned expression to B
6868 LB734 bsr LB73D ; evaluate expression
6869 stx BINVAL ; save result
6870 LB738 jsr SYNCOMMA ; make sure there's a comma
6871 bra EVALEXPB ; evaluate unsigned expression to B
6872 ; Evaluate unsigned expression in X
6873 LB73D jsr LB141 ; evaluate numeric expression
6874 LB740 lda FP0SGN ; is it negative?
6875 bmi LB706 ; brif so
6876 lda FP0EXP ; get exponent
6877 cmpa #0x90 ; largest possible exponent for 16 bits
6878 bhi LB706 ; brif too large
6879 jsr LBCC8 ; move binary point to right of FPA0
6880 ldx FPA0+2 ; get resulting unsigned value
6881 rts
6882 ; PEEK function
6883 PEEK bsr LB740 ; get address to X
6884 ldb ,x ; get the value at that address
6885 jmp LB4F3 ; return B as unsigned value
6886 ; POKE function
6887 POKE bsr LB734 ; evaluate address and byte value
6888 ldx BINVAL ; get address
6889 stb ,x ; put value there
6890 rts
6891 ; LLIST command
6892 LLIST ldb #-2 ; set output device to printer
6893 stb DEVNUM
6894 jsr GETCCH ; reset flags for input character and fall through to LIST
6895 ; LIST command
6896 LIST pshs cc ; save zero flag (end of statement)
6897 jsr LAF67 ; parse line number
6898 jsr LAD01 ; find address of that line
6899 stx LSTTXT ; save that address as the start of the list
6900 puls cc ; get back ent of statement flag
6901 beq LB784 ; brif end of line - list whole program
6902 jsr GETCCH ; are we at the end of the line (one number)?
6903 beq LB789 ; brif end of line
6904 cmpa #0xac ; is it "-"?
6905 bne LB783 ; brif not
6906 jsr GETNCH ; eat the "-"
6907 beq LB784 ; brif no second number - list to end of program
6908 jsr LAF67 ; evaluate the second number
6909 beq LB789 ; brif illegal number
6910 LB783 rts
6911 LB784 ldu #0xffff ; this will cause listing to do the entire program
6912 stu BINVAL
6913 LB789 leas 2,s ; don't return to the caller - we'll jump back to the main loop
6914 ldx LSTTXT ; get address of line to list
6915 LB78D jsr LB95C ; do a newline if needed
6916 jsr LA549 ; do a break check
6917 ldd ,x ; get address of next line
6918 bne LB79F ; brif not end of program
6919 LB797 jsr LA42D ; close output file
6920 clr DEVNUM ; reset device to screen
6921 jmp LAC73 ; go back to immediate mode
6922 LB79F stx LSTTXT ; save new line address
6923 ldd 2,x ; get line number of this line
6924 cmpd BINVAL ; is it above the end line?
6925 bhi LB797 ; brif so - return
6926 jsr LBDCC ; display line number
6927 jsr LB9AC ; put a space after it
6928 ldx LSTTXT ; get line address
6929 bsr LB7C2 ; detokenize the line
6930 ldx [LSTTXT] ; get pointer to next line
6931 ldu #LINBUF+1 ; point to start of detokenized line
6932 LB7B9 lda ,u+ ; get byte from detokenized line
6933 beq LB78D ; brif end of line
6934 jsr LB9B1 ; output character
6935 bra LB7B9 ; handle next character
6936 ; Detokenize a line from (X) to the line input buffer
6937 LB7C2 jsr RVEC24 ; do the RAM hook dance
6938 leax 4,x ; move past next line pointer and line number
6939 ldy #LINBUF+1 ; point to line input buffer (destination)
6940 LB7CB lda ,x+ ; get character from tokenized line
6941 beq LB820 ; brif end of input
6942 bmi LB7E6 ; brif it's a token
6943 cmpa #': ; colon?
6944 bne LB7E2 ; brif not
6945 ldb ,x ; get what's after the colon
6946 cmpb #0x84 ; ELSE?
6947 beq LB7CB ; brif so - suppress the colon
6948 cmpb #0x83 ; '?
6949 beq LB7CB ; brif so - suppress the colon
6950 skip2
6951 LB7E0 lda #'! ; placeholder for unknown token
6952 LB7E2 bsr LB814 ; stow output character
6953 bra LB7CB ; go process another input character
6954 LB7E6 ldu #COMVEC-10 ; point to command interptation table
6955 cmpa #0xff ; is it a function?
6956 bne LB7F1 ; brif not
6957 lda ,x+ ; get function token
6958 leau 5,u ; shift to the function half of the interpretation tables
6959 LB7F1 anda #0x7f ; remove token bias
6960 LB7F3 leau 10,u ; move to next command/function table
6961 tst ,u ; is this table active?
6962 beq LB7E0 ; brif not - use place holder
6963 LB7F9 suba ,u ; subtract number of tokens handled by this table entry
6964 bpl LB7F3 ; brif this token isn't handled here
6965 adda ,u ; undo extra subtraction
6966 ldu 1,u ; get reserved word list for this table
6967 LB801 deca ; are we at the right entry?
6968 bmi LB80A ; brif so
6969 LB804 tst ,u+ ; end of entry?
6970 bpl LB804 ; brif not
6971 bra LB801 ; see if we're there yet
6972 LB80A lda ,u ; get character from wordlist
6973 bsr LB814 ; put character in the buffer
6974 tst ,u+ ; end of word?
6975 bpl LB80A ; brif not
6976 bra LB7CB ; go handle another input character
6977 LB814 cmpy #LINBUF+LBUFMX ; is there room?
6978 bhs LB820 ; brif not
6979 anda #0x7f ; lose bit 7
6980 sta ,y+ ; save character in output
6981 clr ,y ; make sure there's always a NUL terminator
6982 LB820 rts
6983 ; Tokenize the line that the input pointer is pointing to; put result in the line input buffer; return
6984 ; length in D
6985 LB821 jsr RVEC23 ; do the RAM hook dance
6986 ldx CHARAD ; get input pointer
6987 ldu #LINBUF ; set destination pointer
6988 LB829 clr V43 ; clear alpha string flag
6989 clr V44 ; clear DATA flag
6990 LB82D lda ,x+ ; get input character
6991 beq LB852 ; brif end of input
6992 tst V43 ; are we handling an alphanumeric string?
6993 beq LB844 ; brif not
6994 jsr LB3A2 ; set carry if not alpha
6995 bcc LB852 ; brif alpha
6996 cmpa #'0 ; is it below the digits?
6997 blo LB842 ; brif so
6998 cmpa #'9 ; is it within the digits?
6999 bls LB852 ; brif so
7000 LB842 clr V43 ; flag that we're past the alphanumeric string
7001 LB844 cmpa #0x20 ; space?
7002 beq LB852 ; brif so - keep it
7003 sta V42 ; save scan delimiter
7004 cmpa #'" ; string delimiter?
7005 beq LB886 ; brif so - copy until another "
7006 tst V44 ; doing "DATA"?
7007 beq LB86B ; brif not
7008 LB852 sta ,u+ ; put character in output
7009 beq LB85C ; brif end of input
7010 cmpa #': ; colon?
7011 beq LB829 ; brif so - reset DATA and alpha string flags
7012 LB85A bra LB82D ; go process another input character
7013 LB85C clr ,u+ ; put a double NUL at the end
7014 clr ,u+
7015 tfr u,d ; calculate length of result (includes double NUL and an extra two bytes)
7016 subd #LINHDR
7017 ldx #LINBUF-1 ; point to one before the output
7018 stx CHARAD ; set input pointer there
7019 rts
7020 LB86B cmpa #'? ; print abbreviation?
7021 bne LB873 ; brif not
7022 lda #0x87 ; token for PRINT
7023 bra LB852 ; go stash it
7024 LB873 cmpa #'' ; REM abbreviation?
7025 bne LB88A ; brif not
7026 ldd #0x3a83 ; colon plus ' token
7027 std ,u++ ; put it in the output
7028 LB87C clr V42 ; set delimiter to NUL
7029 LB87E lda ,x+ ; get input
7030 beq LB852 ; brif end of line
7031 cmpa V42 ; at the delimiter?
7032 beq LB852 ; brif so
7033 LB886 sta ,u+ ; save in output
7034 bra LB87E ; keep scanning for delimiter
7035 LB88A cmpa #'0 ; is it below digits?
7036 blo LB892 ; brif so
7037 cmpa #';+1 ; is it digit, colon, or semicolon?
7038 blo LB852 ; brif so
7039 LB892 leax -1,x ; move input pointer back one (to point at this input character)
7040 pshs u,x ; save input and output pointers
7041 clr V41 ; set token type to 0 (command)
7042 ldu #COMVEC-10 ; point to command interpretation table
7043 LB89B clr V42 ; set token counter to 0 (0x80)
7044 LB89D leau 10,u ;
7045 lda ,u ; get number of reserved words
7046 beq LB8D4 ; brif this table isn't active
7047 ldy 1,u ; point to reserved words list
7048 LB8A6 ldx ,s ; get input pointer
7049 LB8A8 ldb ,y+ ; get character from reserved word table
7050 subb ,x+ ; compare with input character
7051 beq LB8A8 ; brif exact match
7052 cmpb #0x80 ; brif it was the last character in word and exact match
7053 bne LB8EA ; brif not
7054 leas 2,s ; remove original input pointer from stack
7055 puls u ; get back output pointer
7056 orb V42 ; create token value (B has 0x80 from above)
7057 lda V41 ; get token type
7058 bne LB8C2 ; brif function
7059 cmpb #0x84 ; is it ELSE?
7060 bne LB8C6 ; brif not
7061 lda #': ; silently add a colon before ELSE
7062 LB8C2 std ,u++ ; put two byte token into output
7063 bra LB85A ; go handle more input
7064 LB8C6 stb ,u+ ; save single byte token
7065 cmpb #0x86 ; DATA?
7066 bne LB8CE ; brif not
7067 inc V44 ; set DATA flag
7068 LB8CE cmpb #0x82 ; REM?
7069 beq LB87C ; brif so - skip over rest of line
7070 LB8D2 bra LB85A ; go handle more input
7071 LB8D4 ldu #COMVEC-5 ; point to interpretation table, function style
7072 LB8D7 com V41 ; invert token flag
7073 bne LB89B ; brif we haven't already done functions
7074 puls x,u ; restore input and output pointers
7075 lda ,x+ ; copy first character
7076 sta ,u+
7077 jsr LB3A2 ; set C if not alpha
7078 bcs LB8D2 ; brif not alpha - it isn't a variable
7079 com V43 ; set alphanumeric string flag
7080 bra LB8D2 ; process more input
7081 LB8EA inc V42 ; bump token number
7082 deca ; checked all in this table?
7083 beq LB89D ; brif so
7084 leay -1,y ; unconsume last compared character
7085 LB8F1 ldb ,y+ ; end of entry?
7086 bpl LB8F1 ; brif not
7087 bra LB8A6 ; check next reserved word
7088 ; PRINT command
7089 PRINT beq LB958 ; brif no argument - do a newline
7090 bsr LB8FE ; process print options
7091 clr DEVNUM ; reset output to screen
7092 rts
7093 LB8FE cmpa #'@ ; is it PRINT @?
7094 bne LB907 ; brif not
7095 LB902 jsr LA554 ; move cursor to correct location
7096 LB905 bra LB911 ; handle some more
7097 LB907 cmpa #'# ; device number specified?
7098 bne LB918 ; brif not
7099 jsr LA5A5 ; parse device number
7100 jsr LA406 ; check for valid output file
7101 LB911 jsr GETCCH ; get input character
7102 beq LB958 ; brif nothing - do newline
7103 jsr SYNCOMMA ; need comma after @ or #
7104 LB918 jsr RVEC9 ; do the RAM hook boogaloo
7105 LB91B beq LB965 ; brif end of input
7106 LB91D cmpa #0xa4 ; TAB(?
7107 beq LB97E ; brif so
7108 cmpa #', ; comma (next tab field)?
7109 beq LB966 ; brif so
7110 cmpa #'; ; semicolon (do not advance print position)
7111 beq LB997 ; brif so
7112 jsr LB156 ; evaluate expression
7113 lda VALTYP ; get type of value
7114 pshs a ; save it
7115 bne LB938 ; brif string
7116 jsr LBDD9 ; convert FP number to string
7117 jsr LB516 ; parse a string and put on string stack
7118 LB938 bsr LB99F ; print string
7119 puls b ; get back variable type
7120 jsr LA35F ; set up print parameters
7121 tst PRTDEV ; is it a display device?
7122 beq LB949 ; brif so
7123 bsr LB958 ; do a newline
7124 jsr GETCCH ; get input
7125 bra LB91B ; process more print stuff
7126 LB949 tstb ; set flags on print position
7127 bne LB954 ; brif not at start of line
7128 jsr GETCCH ; get current input
7129 cmpa #', ; comma?
7130 beq LB966 ; skip to next tab field if so
7131 bsr LB9AC ; send a space
7132 LB954 jsr GETCCH ; get input character
7133 bne LB91D ; brif not end of statement
7134 LB958 lda #0x0d ; carriage return
7135 bra LB9B1 ; send it to output
7136 LB95C jsr LA35F ; set up print parameters
7137 LB95F beq LB958 ; brif width is 0
7138 lda DEVPOS ; get line position
7139 bne LB958 ; brif not at start of line
7140 LB965 rts
7141 LB966 jsr LA35F ; set up print parameters
7142 beq LB975 ; brif line width is 0
7143 ldb DEVPOS ; get line position
7144 cmpb DEVLCF ; at or past last comma field?
7145 blo LB977 ; brif so
7146 bsr LB958 ; move to next line
7147 bra LB997 ; handle more stuff
7148 LB975 ldb DEVPOS ; get line position
7149 LB977 subb DEVCFW ; subtract a comma field width
7150 bhs LB977 ; brif we don't have a remainder yet
7151 negb ; now B is number of of spaces needed
7152 bra LB98E ; go advance
7153 LB97E jsr LB709 ; evaluate TAB distance
7154 cmpa #') ; closing )?
7155 lbne LB277 ; brif not
7156 jsr LA35F ; set up print parameters
7157 subb DEVPOS ; subtract print position from desired position
7158 bls LB997 ; brif we're already past it
7159 LB98E tst PRTDEV ; is it a display device?
7160 bne LB997 ; brif not
7161 LB992 bsr LB9AC ; output a space
7162 decb ; done enough?
7163 bne LB992 ; brif not
7164 LB997 jsr GETNCH ; get input character
7165 jmp LB91B ; process more items
7166 ; cpoy string from (X-1) to output
7167 STRINOUT jsr LB518 ; parse the string
7168 LB99F jsr LB657 ; get string details
7169 LB9A2 incb ; compensate for decb
7170 LB9A3 decb ; done all of the string?
7171 beq LB965 ; brif so
7172 lda ,x+ ; get character from string
7173 bsr LB9B1 ; send to output
7174 bra LB9A3 ; go do another character
7175 LB9AC lda #0x20 ; space character
7176 skip2
7177 LB9AF lda #'? ; question mark character
7178 LB9B1 jmp PUTCHR ; output character
7179 ; The floating point math package and related functions and operations follow from here
7180 ; to the end of the Color Basic ROM area
7181 LB9B4 ldx #LBEC0 ; point to FP constant 0.5
7182 bra LB9C2 ; add 0.5 to FPA0
7183 LB9B9 jsr LBB2F ; unpack FP data from (X) to FPA1
7184 ; subtraction operator
7185 LB9BC com FP0SGN ; invert sign of FPA0 (subtracting is adding the negative)
7186 com RESSGN ; that also inverts the sign differential
7187 bra LB9C5 ; go add the negative of FPA0 to FPA1
7188 LB9C2 jsr LBB2F ; unpack FP data from (X) to FPA1
7189 ; addition operator
7190 LB9C5 tstb ; check exponent of FPA0
7191 lbeq LBC4A ; copy FPA1 to FPA0 if FPA0 is 0
7192 ldx #FP1EXP ; point X to FPA1 (first operand) as the operand to denormalize
7193 LB9CD tfr a,b ; put exponent of FPA1 into B
7194 tstb ; is FPA1 0?
7195 beq LBA3E ; brif exponent is 0 - no-op; adding 0 to FPA0
7196 subb FP0EXP ; get difference in exponents - number of bits to shift the smaller mantissa
7197 beq LBA3F ; brif exponents are equal - no need to denormalize
7198 blo LB9E2 ; brif FPA0 > FPA1
7199 sta FP0EXP ; replace result exponent with FPA1's (FPA1 is bigger)
7200 lda FP1SGN ; also copy sign over
7201 sta FP0SGN
7202 ldx #FP0EXP ; point to FPA0 (we need to denormalize the smaller number)
7203 negb ; invert the difference - this is the number of bits to shift the mantissa
7204 LB9E2 cmpb #-8 ; do we have to shift by a whole byte?
7205 ble LBA3F ; brif so start by shifting whole bytes to the right
7206 clra ; clear overflow byte
7207 lsr 1,x ; shift high bit of mantissa right (LSR will force a zero into the high bit)
7208 jsr LBABA ; shift remainder of mantissa right -B times
7209 LB9EC ldb RESSGN ; get the sign flag
7210 bpl LB9FB ; brif signs are the same (we add the mantissas then)
7211 com 1,x ; complement the mantissa and extra precision bytes
7212 com 2,x
7213 com 3,x
7214 com 4,x
7215 coma
7216 adca #0 ; add one to A (COM sets C); this may cause a carry to enter the ADD below
7217 LB9FB sta FPSBYT ; save extra precision byte
7218 lda FPA0+3 ; add the main mantissa bytes (and propage carry from above)
7219 adca FPA1+3
7220 sta FPA0+3
7221 lda FPA0+2
7222 adca FPA1+2
7223 sta FPA0+2
7224 lda FPA0+1
7225 adca FPA1+1
7226 sta FPA0+1
7227 lda FPA0
7228 adca FPA1
7229 sta FPA0
7230 tstb ; were signs the same?
7231 bpl LBA5C ; brif so - number may have gotten bigger so normalize if needed
7232 LBA18 bcs LBA1C ; brif we had a carry - result is positive?)
7233 bsr LBA79 ; do a proper negation of FPA0 mantissa
7234 LBA1C clrb ; clear temporary exponent accumulator
7235 LBA1D lda FPA0 ; test high byte of mantissa
7236 bne LBA4F ; brif not 0 - we need to do bit shifting
7237 lda FPA0+1 ; shift left 8 bits
7238 sta FPA0
7239 lda FPA0+2
7240 sta FPA0+1
7241 lda FPA0+3
7242 sta FPA0+2
7243 lda FPSBYT
7244 sta FPA0+3
7245 clr FPSBYT
7246 addb #8 ; account for 8 bits shifted
7247 cmpb #5*8 ; shifted 5 bytes worth?
7248 blt LBA1D ; brif not
7249 LBA39 clra ; zero out exponent and sign - result is 0
7250 LBA3A sta FP0EXP ; set exponent and sign
7251 sta FP0SGN
7252 LBA3E rts
7253 LBA3F bsr LBAAE ; shift FPA0 mantissa to the right
7254 clrb ; clear carry
7255 bra LB9EC ; get on with adding
7256 LBA44 incb ; account for one bit shift
7257 asl FPSBYT ; shift mantissa and extra precision left
7258 rol FPA0+3
7259 rol FPA0+2
7260 rol FPA0+1
7261 rol FPA0
7262 LBA4F bpl LBA44 ; brif we haven't got a 1 in bit 7
7263 lda FP0EXP ; get exponent of result
7264 pshs b ; subtract shift count from exponent
7265 suba ,s+
7266 sta FP0EXP ; save adjusted exponent
7267 bls LBA39 ; brif we underflowed - set result to 0
7268 skip2
7269 LBA5C bcs LBA66 ; brif mantissa overflowed
7270 asl FPSBYT ; get bit 7 of expra precision to C (used for round off)
7271 lda #0 ; set to 0 without affecting C
7272 sta FPSBYT ; clear out extra precision bits
7273 bra LBA72 ; go round off result
7274 LBA66 inc FP0EXP ; bump exponent (for a right shift to bring carry in)
7275 beq LBA92 ; brif we overflowed
7276 ror FPA0 ; shift carry into mantissa, shift right
7277 ror FPA0+1
7278 ror FPA0+2
7279 ror FPA0+3
7280 LBA72 bcc LBA78 ; brif no round-off needed
7281 bsr LBA83 ; add one to mantissa
7282 beq LBA66 ; brif carry - need to shift right again
7283 LBA78 rts
7284 LBA79 com FP0SGN ; invert sign of value
7285 LBA7B com FPA0 ; first do a one's copmlement
7286 com FPA0+1
7287 com FPA0+2
7288 com FPA0+3
7289 LBA83 ldx FPA0+2 ; add one to mantissa (after one's complement gives two's complement)
7290 leax 1,x ; bump low word
7291 stx FPA0+2
7292 bne LBA91 ; brif no carry from low word
7293 ldx FPA0 ; bump high word
7294 leax 1,x
7295 stx FPA0
7296 LBA91 rts
7297 LBA92 ldb #2*5 ; code for overflow
7298 jmp LAC46 ; raise error
7299 LBA97 ldx #FPA2-1 ; point to FPA2
7300 LBA9A lda 4,x ; shift mantissa right by 8 bits
7301 sta FPSBYT
7302 lda 3,x
7303 sta 4,x
7304 lda 2,x
7305 sta 3,x
7306 lda 1,x
7307 sta 2,x
7308 lda FPCARY ; and handle extra precision on the left
7309 sta 1,x
7310 LBAAE addb #8 ; account for 8 bits shifted
7311 ble LBA9A ; brif more shifts needed
7312 lda FPSBYT ; get sub byte (extra precision)
7313 subb #8 ; undo the 8 added above
7314 beq LBAC4 ; brif difference is 0
7315 LBAB8 asr 1,x ; shift mantissa and sub byte one bit (keep mantissa high bit set)
7316 LBABA ror 2,x
7317 ror 3,x
7318 ror 4,x
7319 rora
7320 incb ; account for one shift
7321 bne LBAB8 ; brif not enought shifts yet
7322 LBAC4 rts
7323 LBAC5 fcb 0x81,0x00,0x00,0x00,0x00 ; packed FP 1.0
7324 LBACA bsr LBB2F ; unpack FP value from (X) to FPA1
7325 ; multiplication operator
7326 LBACC beq LBB2E ; brif exponent of FPA0 is 0 (result is 0)
7327 bsr LBB48 ; calculate exponent of product
7328 LBAD0 lda #0 ; zero out mantissa of FPA2
7329 sta FPA2
7330 sta FPA2+1
7331 sta FPA2+2
7332 sta FPA2+3
7333 ldb FPA0+3 ; multiply FPA1 by LSB of FPA0
7334 bsr LBB00
7335 ldb FPSBYT ; save extra precision byte
7336 stb VAE
7337 ldb FPA0+2
7338 bsr LBB00 ; again for next byte of FPA0
7339 ldb FPSBYT
7340 stb VAD
7341 ldb FPA0+1 ; again for next byte of FPA0
7342 bsr LBB00
7343 ldb FPSBYT
7344 stb VAC
7345 ldb FPA0 ; and finally for the high byte
7346 bsr LBB02
7347 ldb FPSBYT
7348 stb VAB
7349 jsr LBC0B ; copy mantissa from FPA2 to FPA0 (result)
7350 jmp LBA1C ; normalize
7351 LBB00 beq LBA97 ; brif multiplier is 0 - just shift, don't multiply
7352 LBB02 coma ; set carry
7353 LBB03 lda FPA2 ; get FPA2 MS byte
7354 rorb ; data bit to carry; will be 0 when all shifts done
7355 beq LBB2E ; brif 8 shifts done
7356 bcc LBB20 ; brif data bit is 0 - no addition
7357 lda FPA2+3 ; add mantissa of FPA1 and FPA2
7358 adda FPA1+3
7359 sta FPA2+3
7360 lda FPA2+2
7361 adca FPA1+2
7362 sta FPA2+2
7363 lda FPA2+1
7364 adca FPA1+1
7365 sta FPA2+1
7366 lda FPA2
7367 adca FPA1
7368 LBB20 rora ; shift carry into FPA2
7369 sta FPA2
7370 ror FPA2+1
7371 ror FPA2+2
7372 ror FPA2+3
7373 ror FPSBYT
7374 clra ; clear carry
7375 bra LBB03
7376 LBB2E rts
7377 ; Unpack FP value from (X) to FPA1
7378 LBB2F ldd 1,x ; copy mantissa (and sign)
7379 sta FP1SGN ; save sign bit
7380 ora #0x80 ; make sure mantissa has bit 7 set
7381 std FPA1
7382 ldb FP1SGN ; get sign
7383 eorb FP0SGN ; set if FPA0 sign differs
7384 stb RESSGN
7385 ldd 3,x ; copy remainder of mantissa
7386 std FPA1+2
7387 lda ,x ; and exponent
7388 sta FP1EXP
7389 ldb FP0EXP ; fetch FPA0 exponent and set flags
7390 rts
7391 ; Calculate eponent for product of FPA0 and FPA1
7392 LBB48 tsta ; is FPA1 zero?
7393 beq LBB61 ; brif so
7394 adda FP0EXP ; add to exponent of FPA0 (this is how scientific notation works)
7395 rora ; set V if we *don't* have an overflow
7396 rola
7397 bvc LBB61 ; brif exponent too larger or small
7398 adda #0x80 ; restore the bias
7399 sta FP0EXP ; set result exponent
7400 beq LBB63 ; brif 0 - clear FPA0
7401 lda RESSGN ; the result sign (negative if signs differ) is the result sign
7402 sta FP0SGN ; so set it as such
7403 rts
7404 LBB5C lda FP0SGN ; get sign of FPA0
7405 coma ; invert sign
7406 bra LBB63 ; zero sign and exponent
7407 LBB61 leas 2,s ; don't go back to caller (mul/div) - return to previous caller
7408 LBB63 lbpl LBA39 ; brif we underflowed - go zero things out
7409 LBB67 jmp LBA92 ; raise overflow error
7410 ; fast multiply by 10 - leave result in FPA0
7411 LBB6A jsr LBC5F ; copy FPA0 to FPA1 (for addition later)
7412 beq LBB7C ; brif exponent is 0 - it's a no-op then
7413 adda #2 ; this gives "times 4"
7414 bcs LBB67 ; raise overflow if required
7415 clr RESSGN ; set result sign to "signs the same"
7416 jsr LB9CD ; add FPA1 to FPA0 "times 5"
7417 inc FP0EXP ; times 10
7418 beq LBB67 ; brif overflow
7419 LBB7C rts
7420 LBB7D fcb 0x84,0x20,0x00,0x00,0x00 ; packed FP constant 10.0
7421 ; Divide by 10
7422 LBB82 jsr LBC5F ; move FPA0 to FPA1
7423 ldx #LBB7D ; point to constant 10
7424 clrb ; zero sign
7425 LBB89 stb RESSGN ; result will be positive or zero
7426 jsr LBC14 ; unpack constant 10 to FPA0
7427 skip2 ; fall through to division (divide FPA1 by 10)
7428 LBB8F bsr LBB2F ; unpack FP number from (X) to FPA1
7429 ; division operator
7430 LBB91 beq LBC06 ; brif FPA0 is 0 - division by zero
7431 neg FP0EXP ; get exponent of reciprocal of the divisor
7432 bsr LBB48 ; calculate exponent of quotient
7433 inc FP0EXP ; bump exponent (due to division algorithm below)
7434 beq LBB67 ; brif overflow
7435 ldx #FPA2 ; point to temporary storage location
7436 ldb #4 ; do 5 bytes
7437 stb TMPLOC ; save counter
7438 ldb #1 ; shift counter and quotient byte
7439 LBBA4 lda FPA0 ; compare mantissa of FPA0 to FPA1, set C if FPA1 less
7440 cmpa FPA1
7441 bne LBBBD
7442 lda FPA0+1
7443 cmpa FPA1+1
7444 bne LBBBD
7445 lda FPA0+2
7446 cmpa FPA1+2
7447 bne LBBBD
7448 lda FPA0+3
7449 cmpa FPA1+3
7450 bne LBBBD
7451 coma ; set C if FPA0 = FPA1 (it "goes")
7452 LBBBD tfr cc,a ; save "it goes" status
7453 rolb ; rotate carry into quotient
7454 bcc LBBCC ; brif carry clear - haven't done 8 shifts yet
7455 stb ,x+ ; save quotient byte
7456 dec TMPLOC ; done enough bytes?
7457 bmi LBBFC ; brif done all 5
7458 beq LBBF8 ; brif last byte
7459 ldb #1 ; reset shift counter and quotient byte
7460 LBBCC tfr a,cc ; get back carry status
7461 bcs LBBDE ; brif it "went"
7462 LBBD0 asl FPA1+3 ; shift mantissa (dividend) left
7463 rol FPA1+2
7464 rol FPA1+1
7465 rol FPA1
7466 bcs LBBBD ; brif carry - it "goes" so we have to bump quotient
7467 bmi LBBA4 ; brif high order bit is set - compare mantissas
7468 bra LBBBD ; otherwise, count a 0 bit and try next bit
7469 LBBDE lda FPA1+3 ; subtract mantissa of FPA0 from mantissa of FPA1
7470 suba FPA0+3
7471 sta FPA1+3
7472 lda FPA1+2
7473 sbca FPA0+2
7474 sta FPA1+2
7475 lda FPA1+1
7476 sbca FPA0+1
7477 sta FPA1+1
7478 lda FPA1
7479 sbca FPA0
7480 sta FPA1
7481 bra LBBD0 ; go check for another go
7482 LBBF8 ldb #0x40 ; only two bits in last byte (for rounding)
7483 bra LBBCC ; go do the last byte
7484 LBBFC rorb ; get low bits to bits 7,6 and C to bit 5
7485 rorb
7486 rorb
7487 stb FPSBYT ; save result extra precision
7488 bsr LBC0B ; move FPA2 mantissa to FPA0 (result)
7489 jmp LBA1C ; go normalize the result
7490 LBC06 ldb #2*10 ; division by zero
7491 jmp LAC46 ; raise error
7492 ; Copy mantissa of FPA2 to FPA0
7493 LBC0B ldx FPA2 ; copy high word
7494 stx FPA0
7495 ldx FPA2+2 ; copy low word
7496 stx FPA0+2
7497 rts
7498 ; unpack FP number at (X) to FPA0
7499 LBC14 pshs a ; save register
7500 ldd 1,x ; get mantissa high word and sign
7501 sta FP0SGN ; set sign
7502 ora #0x80 ; make sure mantissa always has bit 7 set
7503 std FPA0
7504 clr FPSBYT ; clear extra precision
7505 ldb ,x ; get exponent
7506 ldx 3,x ; copy mantissa low word
7507 stx FPA0+2
7508 stb FP0EXP ; save exponent (and set flags)
7509 puls a,pc ; restore register and return
7510 LBC2A ldx #V45 ; point to FPA4
7511 bra LBC35 ; pack FPA0 there
7512 LBC2F ldx #V40 ; point to FPA3
7513 skip2 ; fall through to pack FPA0 there
7514 LBC33 ldx VARDES ; get variable descriptor pointer
7515 ; Pack FPA0 to (X)
7516 LBC35 lda FP0EXP ; get exponent
7517 sta ,x ; save it
7518 lda FP0SGN ; get sign
7519 ora #0x7f ; force set low bits - only keep sign in high bit
7520 anda FPA0 ; merge in bits 6-0 of high byte of mantissa
7521 sta 1,x ; save it
7522 lda FPA0+1 ; copy next highest byte
7523 sta 2,x
7524 ldu FPA0+2 ; and the low word of the mantissa
7525 stu 3,x
7526 rts
7527 ; Copy FPA1 to FPA0; return with sign in A
7528 LBC4A lda FP1SGN ; copy sign
7529 LBC4C sta FP0SGN
7530 ldx FP1EXP ; copy exponent, mantissa high byte
7531 stx FP0EXP
7532 clr FPSBYT ; clear extra precision
7533 lda FPA1+1 ; copy mantissa second highest byte
7534 sta FPA0+1
7535 lda FP0SGN ; set sign for return
7536 ldx FPA1+2 ; copy low word of mantissa
7537 stx FPA0+2
7538 rts
7539 ; Copy FPA0 to FPA1
7540 LBC5F ldd FP0EXP ; copy exponent and high byte of mantissa
7541 std FP1EXP
7542 ldx FPA0+1 ; copy middle bytes of mantissa
7543 stx FPA1+1
7544 ldx FPA0+3 ; copy low byte of mantissa and sign
7545 stx FPA1+3
7546 tsta ; set flags on exponent
7547 rts
7548 ; check FPA0: return B = 0, if FPA0 is 0, 0xff if negative, and 0x01 if positive
7549 LBC6D ldb FP0EXP ; get exponent
7550 beq LBC79 ; brif 0
7551 LBC71 ldb FP0SGN ; get sign
7552 LBC73 rolb ; get sign to C
7553 ldb #0xff ; set for negative result
7554 bcs LBC79 ; brif negative
7555 negb ; set to 1 for positive
7556 LBC79 rts
7557 ; SGN function
7558 SGN bsr LBC6D ; get sign of FPA0
7559 LBC7C stb FPA0 ; save result
7560 clr FPA0+1 ; clear next lower 8 bits
7561 ldb #0x88 ; exponent if mantissa is 8 bit integer
7562 LBC82 lda FPA0 ; get high bits of mantissa
7563 suba #0x80 ; set C if mantissa was positive (will cause a negation if it was negative)
7564 LBC86 stb FP0EXP ; set exponent
7565 ldd ZERO ; clear out low word
7566 std FPA0+2
7567 sta FPSBYT ; clear extra precision
7568 sta FP0SGN ; set sign to positive
7569 jmp LBA18 ; normalize the result
7570 ; ABS function
7571 ABS clr FP0SGN ; force FPA0 to be positive (yes, it's that simple)
7572 rts
7573 ; Compare packed FP number at (X) to FPA0
7574 ; Return with B = -1, 0, 1 for FPA0 <, =, > (X) and flags set based on that
7575 LBC96 ldb ,x ; get exponent of (X)
7576 beq LBC6D ; brif (X) is 0
7577 ldb 1,x ; get MS byte of mantissa of (X)
7578 eorb FP0SGN ; set bit 7 if signs of (X) and FPA0 differ
7579 bmi LBC71 ; brif signs differ - no need to compare the magnitude
7580 LBCA0 ldb FP0EXP ; compare exponents and brif different
7581 cmpb ,x
7582 bne LBCC3
7583 ldb 1,x ; compare mantissa (but we have to pack the FPA0 bits first
7584 orb #0x7f ; keep only sign bit (note: signs are the same)
7585 andb FPA0 ; merge in the mantissa bits from FPA0
7586 cmpb 1,x ; do the packed versions match?
7587 bne LBCC3 ; brif not
7588 ldb FPA0+1 ; compare second byte of mantissas
7589 cmpb 2,x
7590 bne LBCC3
7591 ldb FPA0+2 ; compare third byte of mantissas
7592 cmpb 3,x
7593 bne LBCC3
7594 ldb FPA0+3 ; compare low byte of mantissas, but use subtraction so B = 0 on match
7595 subb 4,x
7596 bne LBCC3
7597 rts ; return B = 0 if (X) = FPA0
7598 LBCC3 rorb ; shift carry to bit 7 (C set if FPA0 < (X))
7599 eorb FP0SGN ; invert the comparision sense if the signs are negative
7600 bra LBC73 ; interpret comparison result
7601 ; Shift mantissa of FPA0 until the binary point is immediately to the right of the mantissa and set up the
7602 ; result as a two's complement value.
7603 LBCC8 ldb FP0EXP ; get exponent of FPA0
7604 beq LBD09 ; brif FPA0 is zero - we don't have to do anything, just blank it
7605 subb #0xa0 ; calculate number of shifts to get to the correct exponent (binary point to the right)
7606 lda FP0SGN ; do we have a positive number?
7607 bpl LBCD7 ; brif so
7608 com FPCARY ; negate the mantissa and set extra inbound precision to the correct sign
7609 jsr LBA7B
7610 LBCD7 ldx #FP0EXP ; point to FPA0
7611 cmpb #-8 ; moving by whole bytes?
7612 bgt LBCE4 ; brif not
7613 jsr LBAAE ; do bit shifting
7614 clr FPCARY ; clear carry in byte
7615 rts
7616 LBCE4 clr FPCARY ; clear the extra carry in precision
7617 lda FP0SGN ; get sign of value
7618 rola ; get sign to carry (so rotate repeats the sign)
7619 ror FPA0 ; shift the first bit
7620 jmp LBABA ; do the shifting dance
7621 ; INT function
7622 INT ldb FP0EXP ; get exponent
7623 cmpb #0xa0 ; is the number big enough that there can be no fractional part?
7624 bhs LBD11 ; brif so - we don't have to do anything
7625 bsr LBCC8 ; go shift binary point to the right of the mantissa
7626 stb FPSBYT ; save extra precision bits
7627 lda FP0SGN ; get original sign
7628 stb FP0SGN ; force result to be positive
7629 suba #0x80 ; set C if we had a positive result
7630 lda #0xa0 ; set exponent to match denormalized result
7631 sta FP0EXP
7632 lda FPA0+3 ; save low byte
7633 sta CHARAC
7634 jmp LBA18 ; go normalize (this will correct for the two's complement representation of negatives)
7635 LBD09 stb FPA0 ; replace mantissa of FPA0 with contents of B
7636 stb FPA0+1
7637 stb FPA0+2
7638 stb FPA0+3
7639 LBD11 rts
7640 ; Convert ASCII string to FP
7641 ; BUG: no overflow is checked on the decimal exponent in exponential notation.
7642 LBD12 ldx ZERO ; zero out FPA0 and temporaries
7643 stx FP0SGN
7644 stx FP0EXP
7645 stx FPA0+1
7646 stx FPA0+2
7647 stx V47
7648 stx V45
7649 bcs LBD86 ; brif input character is numeric
7650 jsr RVEC19 ; do the RAM hook dance
7651 cmpa #'- ; regular negative sign
7652 bne LBD2D ; brif not
7653 com COEFCT ; invert sign
7654 bra LBD31 ; process stuff after the sign
7655 LBD2D cmpa #'+ ; regular plus?
7656 bne LBD35 ; brif not
7657 LBD31 jsr GETNCH ; get character after sign
7658 bcs LBD86 ; brif numeric
7659 LBD35 cmpa #'. ; decimal point?
7660 beq LBD61 ; brif so
7661 cmpa #'E ; scientific notation
7662 bne LBD65 ; brif not
7663 jsr GETNCH ; eat the "E"
7664 bcs LBDA5 ; brif numeric
7665 cmpa #0xac ; negative sign (token)?
7666 beq LBD53 ; brif so
7667 cmpa #'- ; regular negative?
7668 beq LBD53 ; brif so
7669 cmpa #0xab ; plus sign (token)?
7670 beq LBD55 ; brif so
7671 cmpa #'+ ; regular plus?
7672 beq LBD55
7673 bra LBD59 ; brif no sign found
7674 LBD53 com V48 ; set exponent sign to negative
7675 LBD55 jsr GETNCH ; eat the sign
7676 bcs LBDA5 ; brif numeric
7677 LBD59 tst V48 ; is the exponent sign negatvie?
7678 beq LBD65 ; brif not
7679 neg V47 ; negate base 10 exponent
7680 bra LBD65
7681 LBD61 com V46 ; toggle decimal point flag
7682 bne LBD31 ; brif we haven't seen two decimal points
7683 LBD65 lda V47 ; get base 10 exponent
7684 suba V45 ; subtract number of places to the right
7685 sta V47 ; we now have a complete decimal exponent
7686 beq LBD7F ; brif we have no base 10 shifting required
7687 bpl LBD78 ; brif positive exponent
7688 LBD6F jsr LBB82 ; divide FPA0 by 10 (shift decimal point left)
7689 inc V47 ; bump exponent
7690 bne LBD6F ; brif we haven't reached 0 yet
7691 bra LBD7F ; return result
7692 LBD78 jsr LBB6A ; multiply by 10
7693 dec V47 ; downshift the exponent
7694 bne LBD78 ; brif not at 0 yet
7695 LBD7F lda COEFCT ; get desired sign
7696 bpl LBD11 ; brif it will be positive - no need to do anything
7697 jmp LBEE9 ; flip the sign of FPA0
7698 LBD86 ldb V45 ; get the decimal count
7699 subb V46 ; (if decimal seen, will add one; otherwise it does nothing)
7700 stb V45
7701 pshs a ; save new digit
7702 jsr LBB6A ; multiply partial result by 10
7703 puls b ; get back digit
7704 subb #'0 ; remove ASCII bias
7705 bsr LBD99 ; add B to FPA0
7706 bra LBD31 ; go process another digit
7707 LBD99 jsr LBC2F ; save FPA0 to FPA3
7708 jsr LBC7C ; convert B to FP number
7709 ldx #V40 ; point to FPA3
7710 jmp LB9C2 ; add FPA3 and FPA0
7711 LBDA5 ldb V47 ; get exponent value
7712 aslb ; times 2
7713 aslb ; times 4
7714 addb V47 ; times 5
7715 aslb ; times 10
7716 suba #'0 ; remove ASCII bias
7717 pshs b ; save acculated result
7718 adda ,s+ ; add new digit to accumulated result
7719 sta V47 ; save new accumulated decimal exponent
7720 bra LBD55 ; interpret another exponent character
7721 LBDB6 fcb 0x9b,0x3e,0xbc,0x1f,0xfd ; packed FP: 99999999.9
7722 LBDBB fcb 0x9e,0x6e,0x6b,0x27,0xfd ; packed FP: 999999999
7723 LBDC0 fcb 0x9e,0x6e,0x6b,0x28,0x00 ; pakced FP: 1E9
7724 LBDC5 ldx #LABE8-1 ; point to "IN" message
7725 bsr LBDD6 ; output the string
7726 ldd CURLIN ; get basic line number
7727 LBDCC std FPA0 ; save 16 bit unsigned integer
7728 ldb #0x90 ; exponent for upper 16 bits of FPA0 to be an integer
7729 coma ; set C (force normalization to treat as positive)
7730 jsr LBC86 ; zero bottom half, save exponent, and normalize
7731 bsr LBDD9 ; convert FP number to ASCII string
7732 LBDD6 jmp STRINOUT ; output string
7733 ; Convert FP number to ASCII string
7734 LBDD9 ldu #STRBUF+3 ; point to buffer address that will not cause string to go to string space
7735 LBDDC lda #0x20 ; default sign is a space character
7736 ldb FP0SGN ; get sign of value
7737 bpl LBDE4 ; brif positive
7738 lda #'- ; use negative sign
7739 LBDE4 sta ,u+ ; save sign
7740 stu COEFPT ; save output buffer pointer
7741 sta FP0SGN ; save sign character
7742 lda #'0 ; result is 0 if exponent is 0
7743 ldb FP0EXP ; get exponent
7744 lbeq LBEB8 ; brif FPA0 is 0
7745 clra ; base 10 exponent is 0 for > 1
7746 cmpb #0x80 ; is number > 1?
7747 bhi LBDFF ; brif so
7748 ldx #LBDC0 ; point to 1E+09
7749 jsr LBACA ; shift decimal to the right by 9 spaces
7750 lda #-9 ; account for shift
7751 LBDFF sta V45 ; save base 10 exponent
7752 LBE01 ldx #LBDBB ; point to 999999999
7753 jsr LBCA0 ; are we above that?
7754 bgt LBE18 ; brif so
7755 LBE09 ldx #LBDB6 ; point to 99999999.9
7756 jsr LBCA0 ; are we above that?
7757 bgt LBE1F ; brif in range
7758 jsr LBB6A ; multiply by 10 (we were small)
7759 dec V45 ; account for shift
7760 bra LBE09 ; see if we've come into range
7761 LBE18 jsr LBB82 ; divide by 10
7762 inc V45 ; account for shift
7763 bra LBE01 ; see if we've come into range
7764 LBE1F jsr LB9B4 ; add 0.5 to FPA0 (rounding)
7765 jsr LBCC8 ; do the integer dance
7766 ldb #1 ; default decimal flag (force immediate decimal)
7767 lda V45 ; get base 10 exponent
7768 adda #10 ; account for "unormalized" number
7769 bmi LBE36 ; brif number < 1.0
7770 cmpa #11 ; do we have more than 9 places?
7771 bhs LBE36 ; brif so - do scientific notation
7772 deca
7773 tfr a,b
7774 lda #2 ; force no scientific notation
7775 LBE36 deca ; subtract wo without affecting carry
7776 deca
7777 sta V47 ; save exponent - 0 is do not display in scientific notation
7778 stb V45 ; save number of places to left of decimal
7779 bgt LBE4B ; brif >= 1
7780 ldu COEFPT ; point to string buffer
7781 lda #'. ; put decimal
7782 sta ,u+
7783 tstb ; is there anything to left of decimal?
7784 beq LBE4B ; brif not
7785 lda #'0 ; store a zero
7786 sta ,u+
7787 LBE4B ldx #LBEC5 ; point to powers of 10
7788 ldb #0x80 ; set digit counter to 0x80
7789 LBE50 lda FPA0+3 ; add mantissa to power of 10
7790 adda 3,x
7791 sta FPA0+3
7792 lda FPA0+2
7793 adca 2,x
7794 sta FPA0+2
7795 lda FPA0+1
7796 adca 1,x
7797 sta FPA0+1
7798 lda FPA0
7799 adca ,x
7800 sta FPA0
7801 incb ; add one to digit counter
7802 rorb ; put carry into bit 7
7803 rolb ; set V if carry and sign differ
7804 bvc LBE50 ; brif positive mantissa or carry is 0 and negative mantissa
7805 bcc LBE72 ; brif negative mantissa
7806 subb #10+1 ; take 9's complement if adding mantissa
7807 negb
7808 LBE72 addb #'0-1 ; add ASCII bias
7809 leax 4,x ; move to next power of 10
7810 tfr b,a ; save digit
7811 anda #0x7f ; remove add/subtract flag
7812 sta ,u+ ; put in output
7813 dec V45 ; do we need a decimal yet?
7814 bne LBE84 ; brif not
7815 lda #'. ; put decimal
7816 sta ,u+
7817 LBE84 comb ; toggle bit 7 (add/sub flag)
7818 andb #0x80 ; only keep bit 7
7819 cmpx #LBEC5+9*4 ; done all places?
7820 bne LBE50 ; brif not
7821 LBE8C lda ,-u ; get last character
7822 cmpa #'0 ; was it 0?
7823 beq LBE8C ; brif so
7824 cmpa #'. ; decimal?
7825 bne LBE98 ; brif not
7826 leau -1,u ; move past decimal if it isn't needed
7827 LBE98 lda #'+ ; plus sign
7828 ldb V47 ; get scientific notation exponent
7829 beq LBEBA ; brif not scientific notation
7830 bpl LBEA3 ; brif positive exponent
7831 lda #'- ; negative sign for base 10 exponent
7832 negb ; switch to positive exponent
7833 LBEA3 sta 2,u ; put sign
7834 lda #'E ; put "E"
7835 sta 1,u
7836 lda #'0-1 ; init to ASCII 0 (compensate for INC)
7837 LBEAB inca ; bump digit
7838 subb #10 ; have we hit the correct one yet?
7839 bcc LBEAB ; brif not
7840 addb #'9+1 ; convert units digit to ASCII
7841 std 3,u ; put exponent in output
7842 clr 5,u ; put trailing NUL
7843 bra LBEBC ; go reset pointer
7844 LBEB8 sta ,u ; store last character
7845 LBEBA clr 1,u ; put NUL at the end
7846 LBEBC ldx #STRBUF+3 ; point to start of string
7847 rts
7848 LBEC0 fcb 0x80,0x00,0x00,0x00,0x00 ; packed FP 0.5
7849 LBEC5 fqb -100000000
7850 fqb 10000000
7851 fqb -1000000
7852 fqb 100000
7853 fqb -10000
7854 fqb 1000
7855 fqb -100
7856 fqb 10
7857 fqb -1
7858 LBEE9 lda FP0EXP ; get exponent of FPA0
7859 beq LBEEF ; brif 0 - don't flip sign
7860 com FP0SGN ; flip sign
7861 LBEEF rts
7862 ; Expand a polynomial of the form
7863 ; AQ+BQ^3+CQ^5+DQ^7..... where Q is FPA0 and X points to a table
7864 LBEF0 stx COEFPT ; save coefficient table pointer
7865 jsr LBC2F ; copy FPA0 to FPA3
7866 bsr LBEFC ; multiply FPA3 by FPA0
7867 bsr LBF01 ; expand polynomial
7868 ldx #V40 ; point to FPA3
7869 LBEFC jmp LBACA ; multiply FPA0 by FPA3
7870 LBEFF stx COEFPT ; save coefficient table counter
7871 LBF01 jsr LBC2A ; move FPA0 to FPA4
7872 ldx COEFPT ; get the current coefficient
7873 ldb ,x+ ; get the number of entries
7874 stb COEFCT ; save as counter
7875 stx COEFPT ; save new pointer
7876 LBF0C bsr LBEFC ; multiply (X) and FPA0
7877 ldx COEFPT ; get this coefficient
7878 leax 5,x ; move to next one
7879 stx COEFPT ; save new pointer
7880 jsr LB9C2 ; add (X) to FPA0
7881 ldx #V45 ; point X to FPA4
7882 dec COEFCT ; done all coefficients?
7883 bne LBF0C ; brif more left
7884 rts
7885 ; RND function
7886 RND jsr LBC6D ; set flags on FPA0
7887 bmi LBF45 ; brif negative - set seed
7888 beq LBF3B ; brif 0 - do random between 0 and 1
7889 bsr LBF38 ; convert to integer
7890 jsr LBC2F ; save range value
7891 bsr LBF3B ; get random number
7892 ldx #V40 ; point to FPA3
7893 bsr LBEFC ; multply (X) by FPA0
7894 ldx #LBAC5 ; point to FP 1.0
7895 jsr LB9C2 ; add 1 to FPA0
7896 LBF38 jmp INT ; return integer value
7897 LBF3B ldx RVSEED+1 ; move variable random number seed to FPA0
7898 stx FPA0
7899 ldx RVSEED+3
7900 stx FPA0+2
7901 LBF45 ldx RSEED ; move fixed seed to FPA1
7902 stx FPA1
7903 ldx RSEED+2
7904 stx FPA1+2
7905 jsr LBAD0 ; multiply them
7906 ldd VAD ; get lowest order product bytes
7907 addd #0x658b ; add a constant
7908 std RVSEED+3 ; save it as new seed
7909 std FPA0+2 ; save in result
7910 ldd VAB ; get high order extra product bytes
7911 adcb #0xb0 ; add upper bytes of constant
7912 adca #5
7913 std RVSEED+1 ; save as new seed
7914 std FPA0 ; save as result
7915 clr FP0SGN ; set result to positive
7916 lda #0x80 ; set exponent to 0 < FPA0 < 1
7917 sta FP0EXP
7918 lda FPA2+2 ; get a byte from FPA2
7919 sta FPSBYT ; save as extra precision
7920 jmp LBA1C ; go normalize FPA0
7921 RSEED fqb 0x40e64dab ; constant random number generator seed
7922 ; SIN function
7923 SIN jsr LBC5F ; copy FPA0 to FPA1
7924 ldx #LBFBD ; point to 2*pi
7925 ldb FP1SGN ; get sign of FPA1
7926 jsr LBB89 ; divide FPA0 by 2*pi
7927 jsr LBC5F ; copy FPA0 to FPA1
7928 bsr LBF38 ; convert FPA0 to an integer
7929 clr RESSGN ; set result to positive
7930 lda FP1EXP ; get exponent of FPA1
7931 ldb FP0EXP ; get exponent of FPA0
7932 jsr LB9BC ; subtract FPA0 from FPA1
7933 ldx #LBFC2 ; point to FP 0.25
7934 jsr LB9B9 ; subtract FPA0 from 0.25 (pi/2)
7935 lda FP0SGN ; get result sign
7936 pshs a ; save it
7937 bpl LBFA6 ; brif positive
7938 jsr LB9B4 ; add 0.5 (pi) to FPA0
7939 lda FP0SGN ; get sign of result
7940 bmi LBFA9 ; brif negative
7941 com RELFLG ; if 3pi/2 >= arg >= pi/2
7942 LBFA6 jsr LBEE9 ; flip sign of FPA0
7943 LBFA9 ldx #LBFC2 ; point to 0.25
7944 jsr LB9C2 ; add 0.25 (pi/2) to FPA0
7945 puls a ; get original sign
7946 tsta ; was it positive
7947 bpl LBFB7 ; brif so
7948 jsr LBEE9 ; flip result sign
7949 LBFB7 ldx #LBFC7 ; point to series coefficients
7950 jmp LBEF0 ; go calculate value
7951 LBFBD fcb 0x83,0x49,0x0f,0xda,0xa2 ; 2*pi
7952 LBFC2 fcb 0x7f,0x00,0x00,0x00,0x00 ; 0.25
7953 ; modified taylor series SIN coefficients
7954 LBFC7 fcb 6-1 ; six coefficients
7955 fcb 0x84,0xe6,0x1a,0x2d,0x1b ; -((2pi)^11)/11!
7956 fcb 0x86,0x28,0x07,0xfb,0xf8 ; ((2pi)^9)/9!
7957 fcb 0x87,0x99,0x68,0x89,0x01 ; -((2pi)^7)/7!
7958 fcb 0x87,0x23,0x35,0xdf,0xe1 ; ((2pi)^5)/5!
7959 fcb 0x86,0xa5,0x5d,0xe7,0x28 ; -(2pi)^3)/3!
7960 fcb 0x83,0x49,0x0f,0xda,0xa2 ; 2*pi
7961 ; these 12 bytes are unused
7962 fcb 0xa1,0x54,0x46,0x8f,0x13,0x8f,0x52,0x43
7963 fcb 0x89,0xcd,0xa6,0x81
7964 ; these are a copy of the interrupt vectors that live at the top of the ROM. It's not clear
7965 ; why these vectors have been modified since they are not actually used.
7966 fdb INT.SWI3 ; SWI3
7967 fdb INT.SWI2 ; SWI2
7968 fdb INT.FIRQ ; FIRQ
7969 fdb INT.IRQ ; IRQ
7970 fdb INT.SWI ; SWI
7971 fdb INT.NMI ; NMI
7972 fdb L8C1B ; RESET
7973 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7974 ; Coco3 internal ROM, upper 32K
7975 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7976 ; This is the initialization code specific to the Coco3. This handles copying the ROMs to RAM and adding various patches in.
7977 ; This sequence of code demonstrates clearly that the creators of the Coco3 additions were rushed and didn't have a clear
7978 ; understanding of the Coco3 hardware or how Color Basic works. There is evidence of last minute adjustments along with code
7979 ; that serves no purpose but which is still present.
7980 ;
7981 ; There is also a major bug. The F1 for burst phase invert enable is clearly supposed to be enabled for the HSCREEN graphics
7982 ; modes. However, the code that enables it actually patches the wrong byte in the graphics mode initializers. Instead of enabling
7983 ; the burst phase invert bit in FF98, it actually enables the FIRQ enable bit in FF90.
7984 SC000 orcc #0x50 ; make sure interrupts are disabled
7985 lds #0x5eff ; put the stack somewhere
7986 lda #0x12 ; nuclear green colour
7987 ldb #16 ; 16 palette registers
7988 ldx #PALETREG ; point to palette registers
7989 SC00D sta ,x+ ; set a palette register to green
7990 decb ; done?
7991 bne SC00D ; brif not
7992 ldx #MMUREG ; point to MMU registers
7993 leay MMUIMAGE,pcr ; point to MMU initializer
7994 ldb #16 ; there are 16 MMU registers
7995 SC01B lda ,y+ ; copy an MMU initializer
7996 sta ,x+
7997 decb ; done all?
7998 bne SC01B ; brif not
7999 lda #COCO+MMUEN+MC3+MC2+MC1 ; enable coco compatible, mmu, SCS, FExx, and 32K internal
8000 sta INIT0
8001 leax BEGMOVE,pcr ; point to start of relocated initialization code
8002 ldy #0x4000 ; point to RAM address where it goes
8003 SC02F ldd ,x++ ; copy four bytes
8004 ldu ,x++
8005 std ,y++
8006 stu ,y++
8007 cmpx #ENDMOVE ; copied everything?
8008 blo SC02F ; brif not
8009 jmp 0x4000 ; transfer control to code in RAM
8010 ; The rest runs from RAM. This allows it to mess with the ROM mapping (for the ROM/RAM copy). Unfortunately,
8011 ; this clobbers an 8K memory block *before* it determines that it isn't going to copy ROM to RAM which is
8012 ; somewhat problematic for things that intercept a warm start.
8013 BEGMOVE leas -1,s ; make a hole on the stack
8014 nop ; space fillers; probably something removed at the eleventh hour
8015 nop
8016 nop
8017 nop
8018 nop
8019 lda #0xff ; set GIME timer to maximum value and start it counting
8020 sta V.TIMER
8021 sta V.TIMER+1
8022 leax VIDIMAGE,pcr ; point to video mode initializer
8023 ldy #VIDEOMOD ; point to video mode registers
8024 SC056 lda ,x+ ; copy a byte
8025 sta ,y+
8026 cmpy #MMUREG ; done?
8027 bne SC056 ; brif not
8028 ldx #PIA1 ; point to PIA1
8029 ldd #0xff34 ; set up for initializing PIAs
8030 clr 1,x ; set PIA1 DA to direction mode
8031 clr 3,x ; set PIA1 DB to direction mode
8032 deca
8033 sta ,x ; set PIA1 DA bits 7-1 as output, 0 as input
8034 lda #0xf8 ; set PIA1 DB bits 7-3 as output, 2-0 as input
8035 sta 2,x
8036 stb 1,x ; set PIA1 DA to data mode
8037 stb 3,x ; set PIA1 DB to data mode
8038 clr 2,x ; set VDG to alpha-numeric
8039 lda #2 ; set RS232 to marking
8040 sta ,x
8041 lda #0xff
8042 ldx #PIA0 ; point to PIA0
8043 clr 1,x ; set PIA0 DA to direction mode
8044 clr 3,x ; set PIA0 DB to direction mode
8045 clr ,x ; set PIA0 DA to input
8046 sta 2,x ; set PIA0 DB to output
8047 stb 1,x ; set PIA0 DA to direction mode
8048 stb 3,x ; set PIA0 DB to direction mode
8049 ldb #12 ; there are 12 SAM bits to reset
8050 ldu #SAMREG ; point to SAM register
8051 SC091 sta ,u++ ; clear a bit
8052 decb ; done all?
8053 bne SC091 ; brif not
8054 sta SAMREG+9 ; put VDG display at 0x400
8055 tfr b,dp ; set direct page to 0
8056 clr 2,x ; strobe all keyboard columns (pointless)
8057 sta -3,u ; select RAM page 1 (also pointless)
8058 ldx #PIA0 ; point to PIA0 (unneeded - already points there)
8059 ldb #0xdf ; column strobe for F1
8060 stb 2,x ; strobe for F1
8061 lda ,x ; get row data
8062 coma ; set nonzero if F1 down
8063 anda #0x40
8064 sta ,s ; save F1 state for later
8065 ldy #2 ; check for two keys
8066 SC0B1 asrb ; shift strobe (why not just shift directly in the PIA?)
8067 stb 2,x ; strobe new column
8068 lda ,x ; get row data
8069 coma ; set nonzero if CTRL or ALT is down
8070 anda #0x40
8071 beq SC0C2 ; brif not - we don't have C-A-RESET
8072 leay -1,y ; done both?
8073 bne SC0B1 ; brif not
8074 lbra SC1F0 ; go do easter egg picture if C-A-RESET
8075 SC0C2 lda #COCO+MMUEN+MC3+MC1 ; turn off standard SCS (why?)
8076 sta INIT0
8077 ; This checks if we have a valid warm start routine. If there is one, we don't do a ROM/RAM copy. This and
8078 ; everything above could just as easily have been done from ROM.
8079 lda INT.FLAG ; are the bounce vectors valid?
8080 cmpa #0x55
8081 bne SC0F6 ; brif not - copy ROM to RAM
8082 lda RSTFLG ; is the DP reset vector marked valid?
8083 cmpa #0x55
8084 bne NOWARM ; brif not
8085 ldx RSTVEC ; does the vector point to NOP?
8086 lda ,x
8087 cmpa #0x12
8088 lbeq SC18C ; brif so - don't do ROM/RAM copy
8089 NOWARM clr MMUREG ; put bottom memory block in logical block 0 (replaces DP)
8090 lda RSTFLG ; does this give us a valid reset vector?
8091 cmpa #0x55
8092 bne SC0F1 ; brif not
8093 ldx RSTVEC ; does this routine point to a NOP?
8094 lda ,x
8095 cmpa #0x12
8096 lbeq SC18C ; brif so - don't do ROM/RAM copy and keep modified memory map
8097 SC0F1 lda #BLOCK7.0 ; restore memory map
8098 sta MMUREG
8099 SC0F6 ldx #DOSBAS ; point to the end of Color Basic
8100 ldy #EXBAS ; point to start of Extended Basic
8101 lbsr SC1AA ; copy them to RAM
8102 leay PATCHTAB,pcr ; point to patch table
8103 lda ,y+ ; get number of patches to be made
8104 SC106 pshs a ; save patch counter
8105 ldx ,y++ ; get address to patch
8106 ldb ,y+ ; get number of bytes in the patch
8107 SC10C lda ,y+ ; copy a byte
8108 sta ,x+
8109 decb ; done all in this patch?
8110 bne SC10C
8111 puls a ; get back patch counter
8112 deca ; done all patches?
8113 bne SC106 ; brif not
8114 clr TYCLR ; got back to ROM mode
8115 lda #COCO+MMUEN+MC3 ; set up for 16K split mode
8116 sta INIT0
8117 ldd DOSBAS ; is there a Disk Basic ROM signature?
8118 cmpa #'D ; (note that this should just be CMPD)
8119 bne SC137
8120 cmpb #'K
8121 bne SC137
8122 ldx #SUPERVAR ; point to end of Disk Basic ROM
8123 ldy #DOSBAS ; point to start of Disk Basic ROM
8124 bsr SC1AA ; copy it to RAM
8125 lbsr SC322 ; add patches to Disk Basic
8126 SC137 clr TYCLR ; go back to ROM mode
8127 lda #COCO+MMUEN+MC3+MC1 ; set 32K internal mocde
8128 sta INIT0
8129 ldx #H.CRSLOC ; point to end of the Coco3 additions
8130 ldy #SUPERVAR ; point to start of the Coco3 additions
8131 bsr SC1AA ; copy it to RAM
8132 lbsr SC1DE ; set up an easter egg
8133 leay INTIMAGE,pcr ; point to bounce vector initializer
8134 ldx #INT.FLAG ; point to bounce vectors
8135 ldb #19 ; 19 bytes in bounce vectors
8136 lbsr MOVE.XY ; initialize the bounce vectors
8137 clr TYSET ; enable RAM mode (the ROM/RAM copy already did this)
8138 tst ,s ; was F1 pressed?
8139 beq SC180 ; brif not
8140 ldx #IM.TEXT ; point to text mode initializers
8141 ldb #3 ; there are three sets of them
8142 leax 1,x ; move past the FF90 initializer
8143 SC165 lda ,x ; get video mode initializer
8144 ora #0x20 ; enable burst phase invert
8145 sta ,x ; update initializer
8146 leax 9,x ; move to next mode
8147 decb ; done all of them?
8148 bne SC165 ; brif not
8149 ldb #2 ; two graphics mode initalizers
8150 ldx #IM.GRAPH ; point to graphics mode initializers (should be +1; we're actually enabling GIME FIRQ)
8151 SC175 lda ,x ; get initializer
8152 ora #0x20 ; enable burst phase invert (or it would if X pointed to the right place)
8153 sta ,x ; save modified initializer
8154 leax 9,x ; move to next set
8155 decb ; done all of them?
8156 bne SC175 ; brif not
8157 SC180 ldx #VIDRAM ; point to start of VDG text screen
8158 lda #0x60 ; VDG space character
8159 SC185 sta ,x+ ; blank a character
8160 cmpx #VIDRAM+512 ; end of screen?
8161 blo SC185 ; brif not
8162 SC18C lda #COCO+MMUEN+MC3+MC2+MC1 ; turn the SCS back on
8163 sta INIT0
8164 tst ,s ; F1?
8165 beq SC19A ; brif not
8166 lda #0x20 ; enable burst phase invert
8167 sta VIDEOMOD
8168 SC19A ldx #PALETREG ; point to palette registers
8169 leay PALIMAGE,PCR ; point to palette initializer
8170 ldb #16 ; do 16 palette registers
8171 bsr MOVE.XY ; initialize palette
8172 leas 1,s ; clean up stack (not much point since it will be reset anyway)
8173 jmp RESVEC ; transfer control to the original Color Basic initialization routine
8174 SC1AA stx 0x5f02 ; save end copy address
8175 sts 0x5f00 ; save stack
8176 SC1B1 clr TYCLR ; go to ROM mode
8177 ldd ,y ; grab 8 bytes
8178 ldx 2,y
8179 ldu 4,y
8180 lds 6,y
8181 clr TYSET ; go to RAM mode
8182 std ,y ; save the 8 bytes
8183 stx 2,y
8184 stu 4,y
8185 sts 6,y
8186 leay 8,y ; move pointer forward
8187 cmpy 0x5f02 ; done yet?
8188 blo SC1B1 ; brif not
8189 lds 0x5f00 ; restore stack pointer
8190 rts
8191 MOVE.XY lda ,y+ ; copy a byte
8192 sta ,x+
8193 decb ; done all?
8194 bne MOVE.XY ; brif not
8195 rts
8196 SC1DE ldx #AUTHORMS ; point to author name easter egg
8197 leay SC30D,pcr ; point to encoded names
8198 ldb #21 ; 21 bytes in names
8199 SC1E7 lda ,y+ ; get encoded byte
8200 coma ; decode (wow. one's complement encoding.)
8201 sta ,x+ ; put in copied ROM
8202 decb ; done all?
8203 bne SC1E7 ; brif not
8204 rts
8205 SC1F0 clra ; set up to mark things as invalid
8206 sta INT.FLAG ; mark bounce vectors invalid
8207 sta RSTFLG ; mark reset vector invalid
8208 sta TYCLR ; go to ROM mode
8209 ldb #9 ; foreground colour for image
8210 stb PALETREG+10
8211 ldb #63 ; white background
8212 stb PALETREG+11
8213 ldx #AUTHPIC ; point to author picture data
8214 ldy #0xe00 ; put picture at 0xe00 in memory
8215 SC20A ldd ,x++ ; copy four bytes
8216 ldu ,x++
8217 std ,y++
8218 stu ,y++
8219 cmpx #AUTHPICe ; at end of picture data?
8220 blo SC20A ; brif not
8221 lda #0xf9 ; 256x192, CSS0 VDG mode
8222 sta PIA1+2
8223 clra ; this instruction is useless
8224 ldx #SAMREG ; point to SAM register
8225 sta ,x ; set SAM address to 0xe00 and video mode to 256x192
8226 sta 3,x
8227 sta 5,x
8228 sta 7,x
8229 sta 9,x
8230 sta 11,x
8231 WAITLOOP bra WAITLOOP ; freeze the system
8232 VIDIMAGE fcb 0x00,0x00,0x00,0x00,0x0f,0xe0,0x00,0x00
8233 PALIMAGE fcb 18,36,11,7,63,31,9,38,0,18,0,63,0,18,0,38
8234 MMUIMAGE fcb BLOCK7.0,BLOCK7.1,BLOCK6.4,BLOCK7.3
8235 fcb BLOCK7.4,BLOCK7.5,BLOCK7.6,BLOCK7.7
8236 fcb BLOCK7.0,BLOCK6.0,BLOCK6.1,BLOCK6.2
8237 fcb BLOCK6.3,BLOCK7.5,BLOCK6.5,BLOCK7.7
8238 PATCHTAB fcb 27 ; 27 patches to install
8239 ; Patch #1: enable warm start routine after ROM/RAM copy
8240 patch1 fdb XBWMST
8241 fcb patch2-*-1
8242 nop
8243 ; Patch #2: intercept tokenization routine
8244 patch2 fdb LB8D4
8245 fcb patch3-*-1
8246 jmp ALINK2
8247 ; Patch #3: intercept detokenization routine
8248 patch3 fdb LB7F3
8249 fcb patch4-*-1
8250 jmp ALINK3
8251 ; Patch #4: intercept Extended Basic's command interpretation handler
8252 patch4 fdb L8150
8253 fcb patch5-*-1
8254 jmp ALINK4
8255 nop
8256 ; Patch #5: intercept Extended Basic's function handler
8257 patch5 fdb L816C
8258 fcb patch6-*-1
8259 jmp ALINK5
8260 nop
8261 ; Patch #6 through patch #10 - extend &H and &O to allow 24 bit values
8262 patch6 fdb L8834
8263 fcb patch7-*-1
8264 jmp ALINK6A
8265 clr FPA0+1
8266 clr FPA0+2
8267 clr FPA0+3
8268 bra *-78
8269 clr FPA0
8270 bra *-47
8271 jmp ALINK6B
8272 patch7 fdb L87EB
8273 fcb patch8-*-1
8274 bra *+76
8275 nop
8276 rts
8277 ldx #FPA0+1
8278 patch8 fdb L880C
8279 fcb patch9-*-1
8280 bra *+55
8281 patch9 fdb L8826
8282 fcb patch10-*-1
8283 bcs *+25
8284 patch10 fdb L87E7
8285 fcb patch11-*-1
8286 bne *+7
8287 ; Patch #11 is needed because the above removed an RTS used by this routine
8288 patch11 fdb L886A
8289 fcb patch12-*-1
8290 bne *-124
8291 ; Patch #12 - intercept signon message display
8292 patch12 fdb L80B2
8293 fcb patch13-*-1
8294 jmp ALINK12
8295 ; Patch #13 - remove one carriage return from signon message
8296 patch13 fdb L80E8+82
8297 fcb patch14-*-1
8298 fcb 0
8299 ; Patch #14 - extend Extended Basic's graphics initialization routine
8300 patch14 fdb L9703
8301 fcb patch15-*-1
8302 jmp ALINK14
8303 ; Patch #15 - intercept break check
8304 patch15 fdb LADF0
8305 fcb patch16-*-1
8306 jmp ALINK15
8307 nop
8308 ; Patch #16 - intercept break check when handling "line input"
8309 patch16 fdb LA3C2
8310 fcb patch17-*-1
8311 jmp ALINK16
8312 nop
8313 ; Patch #17 - cause INPUT to respond to ON BRK
8314 patch17 fdb LB03C+1
8315 fcb patch18-*-1
8316 fdb ALINK17
8317 ; Patch #18 - intercept ON command
8318 patch18 fdb ON
8319 fcb patch19-*-1
8320 jmp ALINK18
8321 ; Patch #19 - add on extra stuff to end of NEW
8322 patch19 fdb LAD3F
8323 fcb patch20-*-1
8324 jmp ALINK19
8325 nop
8326 ; Patch #20 - intercept error handler
8327 patch20 fdb LAC46
8328 fcb patch21-*-1
8329 jmp ALINK20
8330 ; Patch #21 - intercept immediate mode loop
8331 patch21 fdb LAC73
8332 fcb patch22-*-1
8333 jmp ALINK21
8334 ; Patch #22 - intercept character to screen routine
8335 patch22 fdb LA30A
8336 fcb patch23-*-1
8337 jmp L8C37
8338 ; Patch #23 - intercept CLS
8339 patch23 fdb CLS
8340 fcb patch24-*-1
8341 jmp L8C46
8342 ; Patch #24 - intercept waiting for keypress with cursor routine
8343 patch24 fdb LA1B1
8344 fcb patch25-*-1
8345 jmp LA0CE
8346 nop
8347 nop
8348 nop
8349 nop
8350 nop
8351 ; Patch #25 - intercept PRINT @
8352 patch25 fdb LB902
8353 fcb patch26-*-1
8354 jmp ALINK25
8355 ; Patch #26 - intercept conditional newline routine
8356 patch26 fdb LB95C
8357 fcb patch27-*-1
8358 jmp ALINK26
8359 ; Patch #27 - intercept CLEAR handling in line input routine
8360 patch27 fdb LA38D
8361 fcb patch27e-*-1
8362 jmp ALINK27
8363 patch27e equ *
8364 ; Names of the authors in one's complemented ASCII
8365 SC30D fcb 0xab,0xd1,0xb7,0x9e,0x8d,0x8d,0x96,0x8c
8366 fcb 0xdf,0xd9,0xdf,0xab,0xd1,0xba,0x9e,0x8d
8367 fcb 0x93,0x9a,0x8c,0xf2,0xff
8368 SC322 lda DOSBAS+4 ; get MSB of DSKCON vector
8369 cmpa #0xd6 ; is it 0xd6?
8370 bne SC334 ; brif not - we have Disk Basic 1.1
8371 ldx #0xc0c6 ; point to patch address in Disk Basic 1.0
8372 leay SC355,pcr ; point to patch for Disk Basic 1.0
8373 ldb ,y+ ; get number of bytes to patch
8374 bra SC349 ; go patch it
8375 SC334 ldx #0xC8B4 ; point to Disk Basic 1.1 keyboard check (in the interpretation loop handler)
8376 lda #0x12 ; NOP opcode
8377 ldb #11 ; clobber 11 bytes (which check for a key down before calling the break check)
8378 SC33B sta ,x+ ; put a NOP
8379 decb ; done?
8380 bne SC33B ; brif not
8381 ldx #0xc0d9 ; point to the Disk Basic 1.1 patch address
8382 leay SC351,pcr ; point to patch for Disk Basic 1.1
8383 ldb ,y+ ; get number of bytes in patch
8384 SC349 lda ,y+ ; put a byte from the patch
8385 sta ,x+
8386 decb ; done yet?
8387 bne SC349 ; brif not
8388 rts
8389 ; Copyright message patch for Disk Basic 1.1
8390 SC351 fcb SC355-*-1
8391 jmp ALINK29
8392 ; Copyright message patch for Disk Basic 1.0
8393 SC355 fcb SC355e-*-1
8394 jmp ALINK28
8395 SC355e equ *
8396 ; This is the initializer for the bounce vector table. It sets up to transfer control to Color Basic's
8397 ; interrupt vectors at 0x100. These really should be JMP instead of LBRA, if only because JMP is faster.
8398 INTIMAGE fcb 0x55 ; valid vector table flag
8399 lbra (INTIMAGE+1)-(INT.JUMP)+SW3VEC ; SWI3
8400 lbra (INTIMAGE+1)-(INT.JUMP)+SW2VEC ; SWI2
8401 lbra (INTIMAGE+1)-(INT.JUMP)+FRQVEC ; FIRQ
8402 lbra (INTIMAGE+1)-(INT.JUMP)+IRQVEC ; IRQ
8403 lbra (INTIMAGE+1)-(INT.JUMP)+SWIVEC ; SWI
8404 lbra (INTIMAGE+1)-(INT.JUMP)+NMIVEC ; NMI
8405 ENDMOVE equ *
8406 ; Unused bytes
8407 fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
8408 fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
8409 fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
8410 fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
8411 fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
8412 fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
8413 fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
8414 fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
8415 fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF
8416 fcb 0xFF,0xFF,0xFF,0xFF,0x00,0x18,0x00,0x0E,0x00
8417 ; This is the "pmode 4" author picture easter egg
8418 AUTHPIC fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8419 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8420 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8421 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8422 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8423 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8424 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8425 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8426 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8427 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8428 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8429 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8430 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8431 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8432 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8433 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF
8434 fcb 0xFF,0xF7,0xFF,0xFB,0xEE,0xEF,0xFB,0xFF,0xBB,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xBB
8435 fcb 0xBB,0xBB,0xBF,0xBB,0xBB,0xFF,0xBF,0xFF,0xFE,0xEF,0xFF,0xFF,0xFF,0xEF,0x7F,0xFF
8436 fcb 0xFF,0xF7,0xBB,0xFF,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8437 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBF,0xBB,0xFF,0xBB,0x7F,0xFF
8438 fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xEE,0xEE,0xEF,0xFF,0xFE,0xFF,0xFE,0xEE,0xEE,0xFE,0xEE
8439 fcb 0xEE,0xEE,0xEF,0xEE,0xEE,0xEE,0xEE,0xEE,0xFE,0xEE,0xEE,0xEE,0xEE,0xEE,0x7F,0xFF
8440 fcb 0xFF,0xF3,0xBB,0xFF,0xBB,0xBB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8441 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBB,0xBB,0xBB,0xBB,0xBB,0x7F,0xFF
8442 fcb 0xFF,0xF6,0xAA,0xAE,0xAA,0xAE,0xAA,0xEA,0xBB,0xBB,0xFB,0xFF,0xBB,0xFF,0xBF,0xBF
8443 fcb 0xFF,0xFB,0xBF,0xBB,0xBB,0xBB,0xBB,0xBB,0xBA,0xEA,0xAA,0xEE,0xAE,0xEE,0x7F,0xFF
8444 fcb 0xFF,0xF3,0xBB,0xBF,0xBB,0xBB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8445 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBB,0xBB,0xBB,0xBB,0xBB,0x7F,0xFF
8446 fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEF,0xFE,0xEF,0xFF,0xFF,0xFF
8447 fcb 0xFF,0xFE,0xEF,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEF,0x7F,0xFF
8448 fcb 0xFF,0xF7,0xBB,0xBB,0xBB,0xBB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8449 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBB,0xBB,0xBB,0xBB,0x7F,0xFF
8450 fcb 0xFF,0xF6,0xAA,0xEE,0xAA,0xAA,0xAA,0xEA,0xAB,0xBB,0xBB,0xFF,0xBB,0xFF,0xFF,0xFF
8451 fcb 0xFF,0xFF,0xFF,0xFB,0xBF,0xFF,0xFF,0xBB,0xBB,0xEA,0xAE,0xAA,0xAA,0xAF,0x7F,0xFF
8452 fcb 0xFF,0xF7,0xBB,0xBB,0xBF,0xFF,0xFB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8453 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBB,0xBB,0xBB,0xBB,0x7F,0xFF
8454 fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xEF,0xEF,0xEE,0xEE,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8455 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xEE,0xFF,0xEF,0xEE,0xEE,0xEF,0x7F,0xFF
8456 fcb 0xFF,0xF7,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8457 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBB,0xBB,0x7F,0xFF
8458 fcb 0xFF,0xF7,0xEA,0xAA,0xBB,0xBB,0xBB,0xBB,0xBB,0xFB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF
8459 fcb 0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFB,0xFB,0xBB,0xBB,0xBA,0xAA,0xAA,0xEF,0x7F,0xFF
8460 fcb 0xFF,0xF7,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8461 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBB,0xBB,0xBB,0x7F,0xFF
8462 fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xFE,0xEE,0xEE,0xEE,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8463 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xEE,0xEF,0xFE,0xEE,0xEE,0xEE,0xEF,0x7F,0xFF
8464 fcb 0xFF,0xF7,0xBB,0xBB,0xFB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00
8465 fcb 0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBB,0xBB,0xBB,0x7F,0xFF
8466 fcb 0xFF,0xF6,0xEA,0xAB,0xAA,0xAB,0xBB,0xBB,0xBF,0xBF,0xFF,0xFF,0xFF,0x80,0x00,0x7F
8467 fcb 0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xFF,0xBB,0xBB,0xBF,0xAA,0xAA,0xAA,0xEF,0x7F,0xFF
8468 fcb 0xFF,0xF3,0xBB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8469 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBB,0xBB,0xBF,0x7F,0xFF
8470 fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xEF,0xEE,0xFF,0xFF,0xFF,0xEE,0xFF,0xFF,0x80,0x00,0x3F
8471 fcb 0xFF,0xFF,0x80,0x00,0x3F,0xFF,0xFF,0xEE,0xFE,0xEE,0xEE,0xEE,0xEE,0xEF,0x7F,0xFF
8472 fcb 0xFF,0xF3,0xBB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
8473 fcb 0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBB,0xBB,0xBF,0x7F,0xFF
8474 fcb 0xFF,0xF6,0xEE,0xAB,0xAE,0xEB,0xBB,0xBF,0xFB,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x1F
8475 fcb 0xFF,0xFF,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xBB,0xBB,0xAA,0xAA,0xBE,0xAB,0x7F,0xFF
8476 fcb 0xFF,0xF3,0xBB,0xBF,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8477 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFB,0xBB,0xBB,0xBF,0x7F,0xFF
8478 fcb 0xFF,0xF6,0xEE,0xEE,0xEE,0xEE,0xEE,0xEF,0xFE,0xEF,0xFF,0xFF,0xFF,0x80,0x00,0x0F
8479 fcb 0xFF,0xFE,0x00,0x00,0x3F,0xFF,0xFF,0xEF,0xEF,0xEE,0xEE,0xEE,0xEE,0xEF,0x7F,0xFF
8480 fcb 0xFF,0xF3,0xBB,0xBF,0xFB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
8481 fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0xFF,0xBB,0xBF,0x7F,0xFF
8482 fcb 0xFF,0xF6,0xEA,0xAB,0xBA,0xAB,0xBB,0xFB,0xFF,0xBF,0xFF,0xFF,0xFF,0x80,0x00,0x07
8483 fcb 0xFF,0xFC,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xFB,0xAA,0xFF,0xFE,0xEA,0xAB,0x7F,0xFF
8484 fcb 0xFF,0xF3,0xBB,0xBF,0xFB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8485 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xBF,0xFF,0xBB,0xBF,0x7F,0xFF
8486 fcb 0xFF,0xF6,0xEE,0xEE,0xFF,0xFE,0xEE,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x03
8487 fcb 0xFF,0xF8,0x00,0x00,0x3F,0xFF,0xFF,0xFE,0xEE,0xEE,0xFF,0xFE,0xEE,0xEF,0x7F,0xFF
8488 fcb 0xFF,0xF7,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
8489 fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xBB,0xBF,0xFF,0xBB,0xFF,0x7F,0xFF
8490 fcb 0xFF,0xF7,0xAA,0xFB,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x01
8491 fcb 0xFF,0xF0,0x00,0x00,0x3F,0xFF,0xFF,0xBB,0xBB,0xAE,0xBB,0xBE,0xAF,0xBB,0x7F,0xFF
8492 fcb 0xFF,0xF7,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8493 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0xFF,0xFF,0xBB,0xFF,0x7F,0xFF
8494 fcb 0xFF,0xF6,0xEE,0xEE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x80,0x08,0x00
8495 fcb 0xFF,0xE0,0x02,0x00,0x3F,0xFF,0xFF,0xFE,0xEF,0xEE,0xFF,0xEE,0xEF,0xEF,0x7F,0xFF
8496 fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
8497 fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xBB,0xFF,0x7F,0xFF
8498 fcb 0xFF,0xF7,0xAA,0xBB,0xBB,0xFB,0xBB,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0x80,0x0C,0x00
8499 fcb 0x7F,0xC0,0x06,0x00,0x3F,0xFF,0xFF,0xFF,0xBB,0xFF,0xFF,0xBF,0xEB,0xBB,0x7F,0xFF
8500 fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8501 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8502 fcb 0xFF,0xF6,0xEE,0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0E,0x00
8503 fcb 0x3F,0x80,0x0E,0x00,0x3F,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xEE,0xEE,0xFF,0x7F,0xFF
8504 fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
8505 fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8506 fcb 0xFF,0xF3,0xEA,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0x00
8507 fcb 0x1F,0x00,0x1E,0x00,0x3F,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xBF,0x7F,0xFF
8508 fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8509 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8510 fcb 0xFF,0xF7,0xEE,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0x80
8511 fcb 0x0E,0x00,0x3E,0x00,0x3F,0xFF,0xFF,0xEE,0xFF,0xFF,0xFF,0xFE,0xEF,0xEF,0x7F,0xFF
8512 fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
8513 fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0x7F,0xFF
8514 fcb 0xFF,0xF6,0xEA,0xBB,0xBB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0xC0
8515 fcb 0x00,0x00,0x7E,0x00,0x3F,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xBA,0xEF,0x7F,0xFF
8516 fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8517 fcb 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0x7F,0xFF
8518 fcb 0xFF,0xF6,0xEE,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0xE0
8519 fcb 0x00,0x00,0xFE,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xEF,0x7F,0xFF
8520 fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
8521 fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0x7F,0xFF
8522 fcb 0xFF,0xF6,0xEB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0xC0
8523 fcb 0x00,0x00,0x3E,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xEB,0x7F,0xFF
8524 fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00
8525 fcb 0x00,0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBA,0x7F,0xFF
8526 fcb 0xFF,0xF6,0xEE,0xEF,0xFF,0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xFF,0xFF,0x80,0x0C,0x00
8527 fcb 0x00,0x00,0x1E,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xEB,0x7F,0xFF
8528 fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xFF,0xFC,0x00,0x0F,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00
8529 fcb 0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xAA,0x7F,0xFF
8530 fcb 0xFF,0xF6,0xAB,0xBB,0xFF,0xFF,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0x80,0x0C,0x00
8531 fcb 0x00,0x00,0x06,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x79,0x9F,0xFB,0xAB,0x7F,0xFF
8532 fcb 0xFF,0xF7,0xBB,0xFF,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00
8533 fcb 0x00,0x38,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x03,0xFE,0xEE,0x7F,0xFF
8534 fcb 0xFF,0xF6,0xEF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x4F,0xFF,0xFF,0xFF,0x80,0x00,0x00
8535 fcb 0x01,0x7C,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0xFA,0xBB,0x7F,0xFF
8536 fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x01,0xFF,0xFF,0xF0,0x00,0x00,0x00
8537 fcb 0x03,0xFE,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x7E,0xEE,0x7F,0xFF
8538 fcb 0xFF,0xF3,0xBB,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x80,0x00,0x00
8539 fcb 0x0F,0xFF,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x3B,0xBB,0x7F,0xFF
8540 fcb 0xFF,0xF7,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0x00,0x00
8541 fcb 0x2F,0xFF,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x0E,0xEE,0x7F,0xFF
8542 fcb 0xFF,0xF6,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFF,0x80,0x00,0x01
8543 fcb 0xFF,0xFF,0x80,0x00,0x3F,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x07,0xBB,0x7F,0xFF
8544 fcb 0xFF,0xF7,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF0,0x00,0x00,0x03
8545 fcb 0xFF,0xFF,0x40,0x00,0x03,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x03,0xEE,0x7F,0xFF
8546 fcb 0xFF,0xF3,0xBB,0xFF,0xF0,0x00,0x00,0x00,0x01,0x00,0x1F,0xFF,0xFF,0x80,0x01,0x07
8547 fcb 0xFF,0xFF,0xA0,0x00,0x3F,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x01,0xBB,0x7F,0xFF
8548 fcb 0xFF,0xF7,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x01,0x80,0x1F,0xFF,0xFF,0xFE,0x0E,0x2F
8549 fcb 0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xEE,0x7F,0xFF
8550 fcb 0xFF,0xF6,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x65,0xE0,0x0F,0xFF,0xFF,0x80,0x0C,0x1F
8551 fcb 0xFF,0xFF,0xE0,0x00,0x3F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3B,0x7F,0xFF
8552 fcb 0xFF,0xF7,0xFF,0xFF,0xC0,0x00,0x00,0x0B,0xFF,0xF0,0x0F,0xFF,0xFC,0x00,0x18,0x0F
8553 fcb 0xF8,0x00,0x60,0x00,0x07,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x0E,0x7F,0xFF
8554 fcb 0xFF,0xF3,0xBB,0xFF,0xC0,0x00,0x01,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0x80,0x00,0x01
8555 fcb 0xF8,0x00,0x20,0x00,0x3F,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x1B,0x7F,0xFF
8556 fcb 0xFF,0xF7,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x03,0x03
8557 fcb 0xFF,0x7F,0xF0,0x03,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x0E,0x7F,0xFF
8558 fcb 0xFF,0xF7,0xFE,0xFF,0x80,0x01,0x5D,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xC0,0x07,0xF1
8559 fcb 0xFC,0x07,0xFC,0x00,0x3F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x03,0x7F,0xFF
8560 fcb 0xFF,0xF7,0xBF,0xFF,0x00,0x02,0xEF,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0x00,0x0E,0x00
8561 fcb 0x7C,0x00,0xF4,0x00,0x0C,0x7F,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x0E,0x7F,0xFF
8562 fcb 0xFF,0xF2,0xAB,0xFF,0x00,0x05,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xF8,0x1C,0x00
8563 fcb 0xFC,0x01,0xF8,0x01,0xFB,0xBF,0xFF,0xF8,0x00,0x00,0x0F,0xE1,0x80,0x0B,0x7F,0xFF
8564 fcb 0xFF,0xF7,0xBF,0xFF,0x00,0x03,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xF8,0x1F,0xC0
8565 fcb 0xFE,0x3F,0xFC,0x01,0xF6,0xDF,0xFF,0xF8,0x00,0x3F,0xFF,0xFF,0x80,0x0E,0x7F,0xFF
8566 fcb 0xFF,0xF6,0xEE,0xEE,0x00,0x07,0xFF,0xFF,0xFF,0xFE,0x0F,0xFE,0xFF,0xFC,0x1F,0xF1
8567 fcb 0xFF,0x9F,0xF8,0x37,0xF5,0xDF,0xFF,0xF8,0x00,0xFF,0xFF,0xFF,0x80,0x0B,0x7F,0xFF
8568 fcb 0xFF,0xF7,0xBF,0xFF,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xF8,0x0F,0xEF
8569 fcb 0x7F,0xFF,0xFC,0x03,0xF6,0xDF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0x80,0x06,0x7F,0xFF
8570 fcb 0xFF,0xF6,0xFF,0xBF,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0x07,0xFB,0xBB,0xFD,0xDF,0xFF
8571 fcb 0xEF,0xFF,0xF9,0x7F,0xFB,0xBF,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xC0,0x0B,0x7F,0xFF
8572 fcb 0xFF,0xF7,0xBF,0xFE,0x00,0x03,0xFF,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xFF,0x9F,0xFF
8573 fcb 0xFF,0xFF,0xFF,0xBF,0xFC,0x7F,0xFF,0xFC,0x75,0x0F,0xFF,0xCF,0xC0,0x0E,0x7F,0xFF
8574 fcb 0xFF,0xF6,0xFF,0xFE,0x00,0x07,0xF5,0x47,0xFF,0xE0,0x07,0xFF,0xEF,0xFF,0xCF,0xFD
8575 fcb 0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0xE0,0x07,0xC0,0x0F,0x7F,0xFF
8576 fcb 0xFF,0xF7,0xBF,0xFF,0x00,0x0F,0xF8,0x07,0xFF,0xDC,0x07,0xFF,0xFF,0xFF,0xCF,0xFB
8577 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x03,0xE0,0x0D,0x7F,0xFF
8578 fcb 0xFF,0xF6,0xFF,0xFE,0x00,0x1F,0xD1,0x1F,0xFF,0xEF,0x07,0xFF,0xFF,0xFF,0xFF,0xFF
8579 fcb 0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x7B,0xF0,0x0B,0x7F,0xFF
8580 fcb 0xFF,0xF3,0xBF,0xFE,0x00,0x1F,0xFF,0xEF,0xFE,0x81,0x07,0xFF,0xFF,0xFF,0x7F,0xF8
8581 fcb 0x40,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x60,0x01,0xFC,0x1D,0xF0,0x0D,0x7F,0xFF
8582 fcb 0xFF,0xF6,0xEE,0xFF,0x00,0x1F,0xFF,0x01,0xFE,0x01,0x87,0xFE,0xEE,0xFF,0xFF,0xF0
8583 fcb 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xE0,0x03,0xF0,0x67,0xF0,0x17,0x7F,0xFF
8584 fcb 0xFF,0xF3,0xBF,0xFE,0x00,0x1F,0xF8,0x01,0xFC,0x03,0x87,0xFF,0xFF,0xFF,0xFF,0xC0
8585 fcb 0x00,0x0F,0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,0xC0,0x03,0xF0,0x33,0xF0,0x5F,0x7F,0xFF
8586 fcb 0xFF,0xF6,0xAF,0xFE,0x00,0x1F,0xFF,0xF0,0xFE,0x0F,0x87,0xFF,0xBF,0xFF,0xFF,0x80
8587 fcb 0xFF,0x07,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0xFA,0xFF,0xF1,0xBB,0x7F,0xFF
8588 fcb 0xFF,0xF3,0xBF,0xBF,0x00,0x1F,0xFF,0xFE,0xFE,0x9B,0x87,0xFF,0xFF,0xFF,0xFF,0xBD
8589 fcb 0x80,0xF3,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x17,0xFF,0xFF,0xF4,0xEE,0x7F,0xFF
8590 fcb 0xFF,0xF6,0xEE,0xFF,0x00,0x1F,0xFF,0xFF,0xFF,0x03,0x87,0xEF,0xEE,0xEF,0xFF,0x00
8591 fcb 0x00,0x07,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x77,0xFF,0xFF,0xFE,0xBB,0x7F,0xFF
8592 fcb 0xFF,0xF3,0xBF,0xBF,0x00,0x0F,0xFF,0xEF,0xF8,0x83,0x87,0xFF,0xFF,0xFF,0xFF,0xBE
8593 fcb 0xBF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0xFF,0xFD,0xB3,0xFF,0xFF,0xFD,0xEE,0x7F,0xFF
8594 fcb 0xFF,0xF6,0xEE,0xEF,0x00,0x0F,0xFF,0xF8,0x7F,0xF7,0x8F,0xFF,0xFB,0xBF,0xFF,0xFF
8595 fcb 0xFF,0xF7,0xFC,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xBB,0x7F,0xFF
8596 fcb 0xFF,0xF3,0xBB,0xBB,0x00,0x0F,0xFF,0xF3,0x7F,0x0F,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF
8597 fcb 0xBF,0xE3,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xEE,0x7F,0xFF
8598 fcb 0xFF,0xF6,0xEE,0xEF,0x00,0x0F,0xFE,0xF7,0xFF,0xCF,0x8E,0xFF,0xFF,0xEF,0xFF,0xFF
8599 fcb 0x17,0xF7,0xFD,0xEF,0xEF,0xFE,0xFF,0xFF,0xFF,0x9F,0xFF,0xFF,0xFF,0xBB,0x7F,0xFF
8600 fcb 0xFF,0xF3,0xBB,0xBB,0x00,0x07,0xFF,0xFE,0xFF,0xC1,0x9F,0xFF,0xFF,0xFF,0xFF,0xFE
8601 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0xF7,0xFF,0xFE,0xEE,0x7F,0xFF
8602 fcb 0xFF,0xF6,0xEE,0xEE,0x00,0x03,0xFF,0xC4,0x1C,0x03,0x9B,0xFB,0xAF,0xBF,0xFF,0xFF
8603 fcb 0xFF,0xFF,0xFE,0xFB,0xFB,0xBB,0xFF,0xBF,0xFE,0x02,0xAB,0xFF,0xF8,0xFB,0x7F,0xFF
8604 fcb 0xFF,0xF3,0xBF,0xBA,0x04,0x03,0xFA,0x00,0x00,0x01,0x9F,0xFF,0xBB,0xFF,0xFB,0xFF
8605 fcb 0xFF,0xFF,0xFB,0xBF,0xFF,0xFB,0xFE,0xEF,0xFC,0x00,0x05,0xFF,0xF9,0xEE,0x7F,0xFF
8606 fcb 0xFF,0xF6,0xEE,0xEC,0x06,0x01,0xFC,0xA2,0x00,0x03,0x9F,0xEE,0xEE,0xEF,0xFE,0xFF
8607 fcb 0xFF,0xFF,0xFE,0xFF,0xFE,0xEE,0xEF,0xBF,0xFE,0x00,0x00,0x3F,0xFB,0xBB,0x7F,0xFF
8608 fcb 0xFF,0xF3,0xBB,0xB0,0x00,0x01,0xFA,0x10,0x00,0x03,0x9F,0xFB,0xBB,0xFF,0xFB,0xFF
8609 fcb 0xFF,0xFF,0xFB,0xBF,0xFF,0xFB,0xBE,0xEF,0xFC,0x0F,0x80,0x1F,0xF6,0xEE,0x7F,0xFF
8610 fcb 0xFF,0xF6,0xEE,0xEE,0x00,0x00,0x68,0x5F,0xFE,0x03,0x1B,0xAE,0xAE,0xFB,0xEE,0xFD
8611 fcb 0xFF,0xFF,0xFE,0xAB,0xBB,0xEA,0xFF,0xBF,0xF8,0x0B,0xFC,0x1F,0xFF,0xBB,0x7F,0xFF
8612 fcb 0xFF,0xF3,0xBB,0xBA,0x00,0x00,0x7B,0x0F,0xFE,0x00,0x1F,0xBB,0xBB,0xFF,0xFB,0xFF
8613 fcb 0xFF,0xFF,0xFB,0xBB,0xFF,0xBB,0xBE,0xEF,0xFC,0x07,0xFC,0x5F,0xF6,0xEE,0x7F,0xFF
8614 fcb 0xFF,0xF6,0xEE,0xEE,0x00,0x00,0x14,0x40,0x3C,0x00,0x0E,0xEE,0xEE,0xFF,0xFF,0xFF
8615 fcb 0xFF,0xFF,0xFE,0xEE,0xEE,0xEE,0xEF,0xBF,0xFE,0x00,0x61,0xFF,0xFF,0xBB,0x7F,0xFF
8616 fcb 0xFF,0xF3,0xBB,0x80,0x00,0x00,0x00,0x7E,0x00,0x00,0x3F,0xBB,0xFF,0xFF,0xBF,0xFF
8617 fcb 0xFF,0xFF,0xFF,0xBB,0xFF,0xBB,0xBE,0xEF,0xFF,0xE0,0x07,0xFF,0xFF,0xEE,0x7F,0xFF
8618 fcb 0xFF,0xF6,0xEE,0x00,0x00,0x00,0x00,0x3F,0xEE,0x80,0x2E,0xAB,0xBF,0xBE,0xFC,0xFF
8619 fcb 0xFF,0xFF,0xFE,0xEB,0xBB,0xAA,0xBB,0xBF,0xEF,0xFA,0xFF,0xFF,0xF8,0x0B,0x7F,0xFF
8620 fcb 0xFF,0xF3,0xBA,0x00,0x00,0xC0,0x00,0x0F,0xFE,0x00,0x3B,0xBF,0xFF,0xFB,0xB1,0xFF
8621 fcb 0xFF,0xFF,0xF3,0xBB,0xFF,0xBB,0xAE,0xEF,0xBF,0xD9,0x7F,0xFF,0xF8,0x02,0x7F,0xFF
8622 fcb 0xFF,0xF6,0xEC,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0xEE,0xEE,0xEF,0xEE,0xE1,0xFF
8623 fcb 0xFF,0xFF,0xF0,0xEE,0xEE,0xEE,0xEB,0xBF,0xEF,0x8E,0x3F,0xFF,0xF8,0x00,0x7F,0xFF
8624 fcb 0xFF,0xF3,0xBA,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0xBB,0xBB,0xBF,0xBB,0xB1,0xFF
8625 fcb 0xFF,0xFF,0xE0,0x3B,0xFF,0xBB,0xEE,0xFF,0xBB,0x00,0x5F,0xFF,0xF8,0x00,0x7F,0xFF
8626 fcb 0xFF,0xF6,0xE0,0x04,0x00,0x78,0x00,0x00,0x00,0x01,0xEE,0xAA,0xAE,0xEA,0xC0,0x7F
8627 fcb 0xFF,0xFF,0x80,0x0B,0xFF,0xEF,0xAB,0xFF,0xEF,0xC2,0x3F,0xFF,0xFF,0xE0,0x7F,0xFF
8628 fcb 0xFF,0xF3,0x80,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x3B,0xBB,0xBB,0xBB,0x00,0x3F
8629 fcb 0xFF,0xFF,0x00,0x03,0xFF,0xFE,0xEE,0xEF,0xBB,0xC0,0x7F,0xFF,0xFE,0xF8,0x7F,0xFF
8630 fcb 0xFF,0xF6,0x60,0xC0,0x00,0x7F,0x00,0x00,0x00,0x00,0x2E,0xEE,0xEE,0xEC,0x00,0x01
8631 fcb 0x3F,0xFC,0x00,0x00,0x6E,0xEF,0xFF,0xFB,0xEE,0xE2,0x3F,0xFF,0xFE,0x78,0x7F,0xFF
8632 fcb 0xFF,0xF0,0x98,0x60,0x00,0x3F,0x80,0x00,0x00,0x00,0x03,0xBB,0xBB,0xB8,0x00,0x00
8633 fcb 0x00,0x00,0x00,0x00,0x01,0xBB,0xBB,0xBA,0xBB,0x5F,0x9F,0xFF,0xFC,0xF8,0x7F,0xFF
8634 fcb 0xFF,0xF6,0x00,0x30,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x6A,0xEE,0xA0,0x00,0x00
8635 fcb 0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFA,0xEE,0x83,0xFF,0xFF,0xFC,0xF8,0x7F,0xFF
8636 fcb 0xFF,0xF4,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x05,0x13,0xBB,0x80,0x00,0x00
8637 fcb 0x00,0x00,0x00,0x00,0x00,0x2E,0xEE,0xEA,0x9B,0xA3,0xFF,0xFF,0xFD,0xF0,0x7F,0xFF
8638 fcb 0xFF,0xF0,0x00,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0x0E,0xEE,0x80,0x00,0x00
8639 fcb 0x00,0x00,0x00,0x00,0x00,0x2F,0xFE,0xAA,0x0E,0xED,0xFF,0xFF,0xF9,0xF0,0x7F,0xFF
8640 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x03,0xBB,0x80,0x00,0x00
8641 fcb 0x00,0x00,0x00,0x00,0x00,0x0A,0xBA,0xA8,0x0B,0xFB,0x7F,0xFF,0xF3,0xF0,0x7F,0xFF
8642 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x02,0x8A,0x80,0x00,0x00
8643 fcb 0x00,0x00,0x00,0x00,0x00,0x02,0xFE,0xA0,0x06,0xFE,0xFF,0xFF,0x07,0xF0,0x7F,0xFF
8644 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x00,0x07,0x03,0x80,0x00,0x00
8645 fcb 0x00,0x00,0x00,0x00,0x00,0x02,0xAA,0x80,0x07,0xF9,0xFF,0xFC,0x07,0xF4,0x7F,0xFF
8646 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x0F,0x14,0x0E,0x00,0x00,0x02,0x80,0x80,0x00,0x00
8647 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0x80,0xBF,0xFF,0xBF,0xF0,0x0F,0xF6,0x7F,0xFF
8648 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x03,0xFF,0xFC,0x00,0x00,0x03,0x00,0x00,0x00,0x00
8649 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0xEA,0x0F,0xFE,0x7C,0x77,0x80,0x1F,0xF6,0x7F,0xFF
8650 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0x00,0x00,0x00,0x00
8651 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x7F,0xFC,0xFE,0x80,0x00,0x1F,0xF7,0x7F,0xFF
8652 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x03,0x00,0x00,0x00,0x00
8653 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x37,0x3C,0xFE,0xC0,0x00,0xBF,0xF7,0x7F,0xFF
8654 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x07,0x7F,0xE0,0x00,0x00,0xF3,0x00,0x00,0x00,0x00
8655 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3E,0xFF,0x80,0x01,0xFF,0xF7,0x7F,0xFF
8656 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0xA3,0xFF,0xC0,0x00,0x00,0x63,0x00,0x00,0x00,0x00
8657 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFD,0xEE,0x80,0x07,0xFF,0xF7,0x7F,0xFF
8658 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x63,0xFF,0xC0,0x00,0x00,0x73,0x00,0x00,0x00,0x00
8659 fcb 0xFF,0x00,0x00,0x00,0x00,0x00,0x08,0x1F,0x78,0xF7,0xE8,0x9F,0xFF,0xFC,0x7F,0xFF
8660 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x77,0xBF,0x80,0x00,0x00,0x33,0x00,0x00,0x00,0x3F
8661 fcb 0xBB,0xE0,0x00,0x00,0x00,0x00,0x00,0x1F,0xF8,0x3B,0x55,0x7F,0x80,0x70,0x7F,0xFF
8662 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x01,0xFF,0x00,0x00,0x00,0x3B,0x00,0x00,0x00,0xFF
8663 fcb 0x3B,0xFC,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0x1D,0x8E,0xE7,0x82,0xF8,0x7F,0xFF
8664 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x30,0x00,0x00,0x01,0xFE
8665 fcb 0xF9,0x9F,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xC1,0x17,0xFF,0xFF,0xC0,0x7F,0xFF
8666 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0xF8
8667 fcb 0xFF,0x3F,0xE0,0x00,0x04,0x00,0x00,0x0F,0xBF,0xC2,0xEF,0xFF,0xFF,0x80,0x7F,0xFF
8668 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x1C,0x00,0x00,0x08,0xFB
8669 fcb 0xFF,0x37,0xE0,0x00,0x00,0x00,0x00,0x0F,0xBF,0xC1,0x1F,0xFF,0xFF,0x00,0x7F,0xFF
8670 fcb 0xFF,0xF0,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x1D,0x07
8671 fcb 0xFF,0xE3,0x68,0x00,0x00,0x00,0x00,0x07,0x7F,0xC7,0x3F,0xFF,0xFE,0x00,0x7F,0xFF
8672 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F
8673 fcb 0xFF,0xFB,0xF6,0x00,0x00,0x00,0x00,0x07,0x7F,0xE1,0x7F,0xFF,0xFC,0x00,0x7F,0xFF
8674 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x01,0xC6,0x7F
8675 fcb 0xFF,0xFF,0xE8,0x00,0x00,0x00,0x00,0x07,0x0F,0xF3,0x8F,0x97,0xFC,0x00,0x7F,0xFF
8676 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xB1,0xEF
8677 fcb 0xFF,0xEF,0xB7,0x00,0x00,0x00,0x00,0x07,0x83,0xE1,0xC6,0x00,0x78,0x00,0x7F,0xFF
8678 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xDF
8679 fcb 0xFF,0xD1,0xA2,0x00,0x00,0x40,0x00,0x03,0x00,0xF1,0xFF,0x14,0x20,0x00,0x7F,0xFF
8680 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF
8681 fcb 0xFF,0xFF,0xDF,0x00,0x00,0x00,0x00,0x03,0x06,0x70,0x7C,0x00,0xC0,0x00,0x7F,0xFF
8682 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF
8683 fcb 0xFF,0xFF,0xE7,0xE0,0x00,0x00,0x00,0x03,0x87,0xF1,0xF8,0x03,0x80,0x00,0x7F,0xFF
8684 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0xAF
8685 fcb 0xFF,0xFF,0xF7,0x00,0x00,0x00,0x00,0x03,0x8F,0xFB,0xF8,0x20,0x00,0x00,0x7F,0xFF
8686 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xBF
8687 fcb 0xFF,0xFF,0xBF,0xE0,0x00,0x00,0x00,0xF3,0x8D,0xFF,0xF8,0x5F,0x00,0x00,0x7F,0xFF
8688 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0xFF
8689 fcb 0xFF,0xFF,0x4F,0xF0,0x00,0x00,0x01,0xE3,0x87,0xFF,0xFC,0x6E,0x00,0x00,0x7F,0xFF
8690 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0xF7
8691 fcb 0xBF,0xFF,0xEF,0xE8,0x00,0x00,0x00,0x01,0x1F,0xFF,0xFF,0xFE,0x00,0x00,0x7F,0xFF
8692 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0xFF
8693 fcb 0x9F,0xFF,0xFD,0xF8,0x00,0x00,0x00,0x01,0xBF,0xFF,0xFF,0xFF,0x00,0x00,0x7F,0xFF
8694 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
8695 fcb 0xFF,0xFF,0x8F,0xE8,0x00,0x00,0x00,0x01,0xBF,0xFF,0xFF,0xFC,0x00,0x00,0x7F,0xFF
8696 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
8697 fcb 0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x01,0xBF,0xFF,0xFF,0xF8,0x00,0x00,0x7F,0xFF
8698 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
8699 fcb 0xFF,0x9F,0xFF,0xF8,0x00,0x00,0x00,0x01,0x3F,0xFF,0xFF,0xF0,0x00,0x00,0x7F,0xFF
8700 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x07,0xFF
8701 fcb 0x1F,0xFF,0xF5,0xFC,0x00,0x00,0x00,0x01,0x3F,0xFF,0xFF,0xE0,0x00,0x00,0x7F,0xFF
8702 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFC
8703 fcb 0x3F,0xFF,0xBF,0xF8,0x00,0x00,0x00,0x01,0x3F,0x85,0xFF,0xC0,0x00,0x00,0x7F,0xFF
8704 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF
8705 fcb 0xF7,0xFF,0xDF,0xF8,0x00,0x00,0x00,0x00,0x1D,0x2A,0x07,0x80,0x00,0x00,0x7F,0xFF
8706 fcb 0xFF,0xF0,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
8707 fcb 0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x01,0x06,0xFF,0x00,0x00,0x00,0x00,0x7F,0xFF
8708 fcb 0xFF,0xF0,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x1F,0xFF
8709 fcb 0xFF,0xFF,0xDF,0xF8,0x00,0x00,0x00,0x01,0x17,0x3D,0x95,0x00,0x00,0x00,0x7F,0xFF
8710 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x80,0x00,0x07,0xFF
8711 fcb 0xFF,0xFF,0xEF,0xF8,0x00,0x00,0x00,0x00,0x0E,0xEF,0xDA,0x00,0x00,0x00,0x7F,0xFF
8712 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF
8713 fcb 0xFF,0xFF,0xF7,0xF0,0x00,0x00,0x00,0x00,0x15,0xF7,0x80,0x00,0x00,0x00,0x7F,0xFF
8714 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF
8715 fcb 0xFF,0xFF,0xED,0xE0,0x00,0x00,0x00,0x00,0x0F,0xBF,0xEC,0x00,0x00,0x00,0x7F,0xFF
8716 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
8717 fcb 0xFF,0xFF,0xDC,0xE0,0x00,0x00,0x00,0x00,0x17,0x7F,0xD8,0x00,0x00,0x00,0x7F,0xFF
8718 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF
8719 fcb 0xFF,0xFF,0xBC,0xC0,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFF
8720 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF
8721 fcb 0xFF,0xFF,0xDE,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFF
8722 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF
8723 fcb 0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFF
8724 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF
8725 fcb 0xFF,0xFB,0xFF,0x80,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFF
8726 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xDF
8727 fcb 0xFE,0xC1,0xF2,0x00,0x00,0x00,0x00,0x18,0x7F,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFF
8728 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83
8729 fcb 0x00,0x1F,0xCC,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFF
8730 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00
8731 fcb 0x80,0x3F,0x98,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFF
8732 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2
8733 fcb 0x46,0x3E,0x60,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xE0,0x00,0x00,0x00,0x7F,0xFF
8734 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80
8735 fcb 0x33,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x60,0x00,0x00,0x00,0x7F,0xFF
8736 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0
8737 fcb 0x73,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x3A,0x80,0x00,0x00,0x00,0x7F,0xFF
8738 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0
8739 fcb 0x08,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xF6,0x00,0x00,0x00,0x00,0x7F,0xFF
8740 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0
8741 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xB6,0x00,0x00,0x00,0x00,0x7F,0xFF
8742 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8743 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xED,0x80,0x00,0x00,0x00,0x7F,0xFF
8744 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8745 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x2C,0x00,0x00,0x00,0x00,0x7F,0xFF
8746 fcb 0xFF,0xF0,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8747 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xB0,0x80,0x00,0x00,0x00,0x7F,0xFF
8748 fcb 0xFF,0xF0,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8749 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0x00,0x00,0x00,0x00,0x7F,0xFF
8750 fcb 0xFF,0xF0,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8751 fcb 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x00,0x7F,0xFF
8752 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8753 fcb 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x7F,0xFF,0xC0,0x00,0x00,0x00,0x7F,0xFF
8754 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8755 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x00,0x7F,0xFF
8756 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8757 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x00,0x7F,0xFF
8758 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8759 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x00,0x7F,0xFF
8760 fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8761 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8762 fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8763 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8764 fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8765 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8766 fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8767 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8768 fcb 0xFF,0xF7,0xFF,0xFF,0x3C,0xFF,0xF3,0x3F,0xFF,0xCF,0x9F,0xFF,0xFF,0xFF,0x03,0xFF
8769 fcb 0xCC,0xFF,0xFF,0xF3,0xFF,0xFF,0xF8,0x1F,0xFE,0x0F,0xFF,0x8F,0xFF,0xFF,0x7F,0xFF
8770 fcb 0xFF,0xF7,0xFF,0xFF,0x18,0xFF,0xF3,0x3F,0xFF,0xCF,0xFF,0xFF,0xFF,0xFF,0xCF,0xFF
8771 fcb 0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F,0xFE,0x7F,0xFF,0xCF,0xFF,0xFF,0x7F,0xFF
8772 fcb 0xFF,0xF7,0xFF,0xFF,0x00,0xFF,0xF3,0x31,0x9E,0x49,0x10,0xE1,0xFF,0xFF,0xCF,0xFF
8773 fcb 0xCC,0xC6,0x08,0x23,0x0F,0xFF,0xFE,0x7F,0xFE,0x7C,0x60,0xCC,0x70,0xFF,0x7F,0xFF
8774 fcb 0xFF,0xF7,0xFF,0xFF,0x24,0xFF,0xF0,0x3C,0xC0,0xC3,0x92,0x4F,0xFF,0xFF,0xCF,0xFF
8775 fcb 0xC0,0xF2,0x38,0xF2,0x7F,0xFF,0xFE,0x7F,0xFE,0x1F,0x23,0xC9,0x27,0xFF,0x7F,0xFF
8776 fcb 0xFF,0xF7,0xFF,0xFF,0x3C,0xFF,0xF3,0x30,0xC0,0xC7,0x92,0x63,0xFF,0xFF,0xCF,0xFF
8777 fcb 0xCC,0xC2,0x79,0xF3,0x1F,0xFF,0xFE,0x7F,0xFE,0x7C,0x27,0xC8,0x31,0xFF,0x7F,0xFF
8778 fcb 0xFF,0xF7,0xFF,0xFF,0x3C,0xFF,0xF3,0x24,0xE1,0xC3,0x92,0x79,0xFF,0xFF,0xCF,0xFF
8779 fcb 0xCC,0x92,0x79,0xF3,0xCF,0xFF,0xFE,0x7F,0xFE,0x79,0x27,0xC9,0xFC,0xFF,0x7F,0xFF
8780 fcb 0xFF,0xF7,0xFF,0xFF,0x3C,0x9F,0xF3,0x30,0xE1,0xC9,0x92,0x43,0xFF,0xFF,0xCE,0x7F
8781 fcb 0xCC,0xC2,0x79,0xF2,0x1F,0xFF,0xFE,0x73,0xFE,0x0C,0x27,0xCC,0x61,0xFF,0x7F,0xFF
8782 fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8783 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8784 fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8785 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8786 fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8787 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8788 fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8789 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8790 fcb 0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8791 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF
8792 fcb 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8793 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF
8794 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8795 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8796 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8797 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8798 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8799 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8800 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8801 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8802 AUTHPICe equ *
8803 ; Unused
8804 fcb 0xFF,0x00,0x00,0xA0,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8805 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8806 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8807 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8808 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8809 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8810 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8811 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8812 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8813 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8814 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8815 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEF,0xFF,0xFF,0xFF,0xFF
8816 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8817 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8818 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8819 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8820 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8821 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8822 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8823 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8824 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8825 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8826 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8827 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8828 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8829 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8830 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8831 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8832 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8833 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8834 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8835 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8836 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8837 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8838 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8839 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8840 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8841 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8842 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8843 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8844 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8845 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8846 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8847 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8848 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8849 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8850 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
8851 fcb 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
8852 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8853 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8854 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8855 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8856 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8857 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8858 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8859 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8860 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8861 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8862 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8863 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8864 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x40,0x00
8865 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8866 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00
8867 fcb 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
8868 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8869 ; The actual Super Extended Basic (SECB) extensions start here.
8870 ;
8871 ; Note that many routines in this area feature a "lbrn 0" instruction. This appears to be intended as a placeholder to allow
8872 ; patching into the routines similar to the RAM hooks in Color Basic except using direct overwiting of the instruction. It's
8873 ; completely pointless and probably illustrates that the writers of this code didn't really think through what they were doing.
8874 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8875 SUPERVAR fdb HRMODE ; address of direct page variables unique to SECB
8876 PRGTEXT fdb SETTEXT ; set video registers for text mode (indirect)
8877 PRGGRAPH fdb SETGRAPH ; set video registers for graphics mode (indirect)
8878 PRGMMU fdb SETMMU ; set MMU registers to their "default" (indirect)
8879 GETTEXT fdb SELTEXT ; put hi-res text screen in logical block 1 (indirect)
8880 GETBLOK0 fdb SELBLOK0 ; put block in B in logical block 0 (indirect)
8881 GETTASK0 fdb SELTASK0 ; re-select MMU task 0 (indirect)
8882 GETTAKS1 fdb SELTASK1 ; select MMU task 1(indirect)
8883 jmp LA05E ; execute non-self starting ROM
8884 SPARE0 fdb 0 ; undefined
8885 SPARE1 fdb 0 ; undefined
8886 SPARE2 fdb 0 ; undefined
8887 ; Set up video registers for the selected text screen. Given that the sets of video mode initializers are contiguous in
8888 ; memory, this would probably be better done with a simple sequence of MUL and ABX.
8889 SETTEXT pshs y,x,a ; save registers
8890 lbrn 0
8891 ldx #IM.TEXT ; point to 32 column video mode registers
8892 lda HRWIDTH ; get text mode
8893 beq SETVIDEO ; brif 32 column
8894 ldx #SE03B ; point to 40 column mode data
8895 cmpa #1 ; is it 40 column?
8896 beq SETVIDEO ; brif so
8897 ldx #SE044 ; assume 80 column
8898 bra SETVIDEO ; program video registers
8899 ; 32 column (VDG) initializer
8900 IM.TEXT fcb COCO+MMUEN+MC3+MC2 ; INIT0 (COCO bit enables VDG modes)
8901 fcb 0x00 ; VIDEOMOD (unused for VDG modes)
8902 fcb 0x00 ; VIDEORES (unused for VDG modes)
8903 fcb 0x00 ; V.BORDER (black)
8904 fcb 0x00 ; filler for reserved
8905 fcb 0x0f ; V.SCROLL - this value is needed to show a proper 12 lines per text row
8906 fdb 0xe000 ; V.OFFSET - SAM offsets operate in 0x7xxx
8907 fcb 0x00 ; H.OFFSET - no horizontal offset
8908 ; 40 column screen
8909 SE03B fcb MMUEN+MC3+MC2 ; INIT0 (disable VDG modes)
8910 fcb 0x03 ; VIDEOMOD - 8 lines per row
8911 fcb 0x05 ; VIDEORES - 40 columns, attributes enabled, 192 lines per field
8912 fcb 0x12 ; V.BORDER - nuclear green
8913 fcb 0x00 ; filler for reserved
8914 fcb 0x00 ; V.SCROLL - no offset
8915 fdb 0xd800 ; V.OFFSET - screen at 0x6c000
8916 fcb 0x00 ; H.OFFSET - no offset
8917 ; 80 column screen
8918 SE044 fcb MMUEN+MC3+MC2 ; INIT0 (disable VDG modes)
8919 fcb 0x03 ; VIDEOMOD - 8 lines per row
8920 fcb 0x15 ; VIDEORES - 80 columns, attributes enabled, 192 lines per field
8921 fcb 0x12 ; V.BORDER - nuclear green
8922 fcb 0x00 ; filler for reserved
8923 fcb 0x00 ; V.SCROLL - no offset
8924 fdb 0xd800 ; V.OFFSET - screen at 0x6c000
8925 fcb 0x00 ; H.OFFSET - no offset
8926 ; Set up video registers for the selected "HSCREEN" mode. Note that the two code paths for the resolution widths
8927 ; are unneeded.
8928 SETGRAPH pshs y,x,a ; save registers
8929 lbrn 0
8930 ldx #IM.GRAPH ; point to graphics initlializer
8931 ldy #RESTABLE ; point to resolution bytes table
8932 lda HRMODE ; get graphics mode
8933 cmpa #2 ; is it a 640 pixel mode?
8934 bls SE063 ; brif not
8935 ldx #SE079 ; point to 640 pixel registers
8936 SE063 suba #1 ; normalize mode numbers to start at 0
8937 lda a,y ; get resolution setting for this mode
8938 sta 2,x ; put it in the graphics mode initializer
8939 jmp SETVIDEO ; go set up video registers
8940 RESTABLE fcb 0x15 ; 320x192, 4 colours
8941 fcb 0x1e ; 320x192, 16 colours
8942 fcb 0x14 ; 640x192, 2 colours
8943 fcb 0x1d ; 640x192, 4 colours
8944 ; 320x192 graphics modes
8945 IM.GRAPH fcb MMUEN+MC3+MC2 ; INIT0 (disable VDG modes)
8946 fcb 0x80 ; VIDEOMOD - enable bit plane, one line per row
8947 fcb 0x00 ; VIDEORES - placeholder
8948 fcb 0x00 ; V.BORDER - black
8949 fcb 0x00 ; filler for reserved
8950 fcb 0x00 ; V.SCROLL - no offset
8951 fdb 0xc000 ; V.OFFSET - screen at 0x60000
8952 fcb 0x00 ; H.SCROLL - no offset
8953 ; 640x192 graphics modes (observe that these are identical to the 320x192 ones above)
8954 SE079 fcb MMUEN+MC3+MC2 ; INITo (disable VDG modes)
8955 fcb 0x80 ; VIDEOMOD - enable bit plane, one line per row
8956 fcb 0x00 ; VIDEORES - placeholder
8957 fcb 0x00 ; V.BORDER - black
8958 fcb 0x00 ; filler for reserved
8959 fcb 0x00 ; V.SCROLL - no offset
8960 fdb 0xc000 ; V.OFFSET - screen at 0x60000
8961 fcb 0x00 ; H.SCROLL - no offset
8962 ; Program video registers and INIT0 from (X); enter with A,X,Y pre-saved
8963 SETVIDEO lda ,x+ ; set INIT0
8964 sta INIT0
8965 ldy #VIDEOMOD ; point to start of video mode registers
8966 SE08B lda ,x+ ; set a register
8967 sta ,y+
8968 cmpy #MMUREG ; done all of them?
8969 blo SE08B ; brif not
8970 puls a,x,y,pc ; restore registers and return
8971 ; Set MMU registers to their default values. All 16 of them.
8972 SETMMU pshs y,x,b,a ; save registers
8973 leax IM.MMU,pcr ; point to MMU initializer
8974 bsr SE0F1 ; program MMU registers
8975 puls a,b,x,y,pc ; restore registers and return
8976 ; Set logical block 0 to the physical block in B. This is embarassingly inefficient since it sets
8977 ; *all 16* MMU registers to change one of them. All the faffing about with pointers and the call
8978 ; to set the MMU registers is pointless. It could be done with a single STB.
8979 SELBLOK0 pshs y,x,b,a ; save registers
8980 leax IM.MMU,pcr ; point to MMU initializer
8981 pshs x ; save it for later
8982 stb ,x ; set desired block in initializer
8983 bsr SE0F1 ; program *all 16* MMU registers (stupid)
8984 ldb #BLOCK7.0 ; get correct block number for logical block 0
8985 puls x ; get back pointer to the initializer
8986 stb ,x ; restore initializer value
8987 puls a,b,x,y,pc ; restore registers and return
8988 ; Put hi-res text screen in logical address space block 1. This is embarassingly ineffecient since
8989 ; it sets *all 16* MMU registers to change only one. All the faffing about with pointers and the
8990 ; call to set the MMU registers is pointless. It could be done with a singel LD/ST sequence.
8991 SELTEXT pshs y,x,b,a ; save registers
8992 leax IM.MMU,pcr ; point to MMU initializer
8993 pshs x ; save pointer for later
8994 ldb #BLOCK6.6 ; get block number for text screen
8995 stb 1,x ; put in logical block 1 of initializer
8996 bsr SE0F1 ; program *all 16* MMU registers (stupid)
8997 puls x ; get back pointer
8998 ldb #BLOCK7.1 ; get proper block for logical block 1
8999 stb 1,x ; put it back in the initializer
9000 puls a,b,x,y,pc ; restore registers and return
9001 ; Get block 6.4 (HBUFF buffers) to logical block 6 of task 1. This is embarassingly inefficient
9002 ; since it sets *all 16* MMU registers to change only one. All the faffing about with pointers and
9003 ; the call to set the MMU registers ispointless. It could be done with a single LD/ST sequence.
9004 SE0CB pshs y,x,b,a ; save registers
9005 leax IM.MMU,pcr ; point to MMU initializer
9006 pshs x ; save pointer for later
9007 ldb #BLOCK6.4 ; get block for the HBUFF buffers
9008 stb 14,x ; put in logical block 6, task 1
9009 bsr SE0F1 ; program *all 16* MMU registers (stupid)
9010 puls x ; get back pointer
9011 ldb #BLOCK6.5 ; get default block for logical block 6 of task 1
9012 stb 14,x ; put it back in the initializer
9013 puls a,b,x,y,pc ; restore registers and return
9014 ; MMU initializer
9015 IM.MMU fcb BLOCK7.0,BLOCK7.1,BLOCK7.2,BLOCK7.3 ; task 0: map 0x70000-0x7ffff
9016 fcb BLOCK7.4,BLOCK7.5,BLOCK7.6,BLOCK7.7
9017 fcb BLOCK7.0,BLOCK6.0,BLOCK6.1,BLOCK6.2 ; task 1: put hires gfx at 0x2000 and a stack block at 0xc000
9018 fcb BLOCK6.3,BLOCK7.5,BLOCK6.5,BLOCK7.7
9019 ; Set all 16 MMU registers from the initializer pointed to by X.
9020 SE0F1 ldy #MMUREG ; point to MMU registers
9021 ldb #16 ; there are 16 to set
9022 SE0F7 lda ,x+ ; set a register
9023 sta ,y+
9024 decb ; done all?
9025 bne SE0F7 ; brif not
9026 rts
9027 ; Select task register 0 as the active MMU set. Enter with stack in a temporary location which
9028 ; holds the original stack pointer. Note that the return could be done simply as jmp [V42] instead
9029 ; of pushing the return address onto the stack. Interrupts will be enabled on the way out.
9030 SELTASK0 std V40 ; temp save D
9031 ldd ,s ; get return address
9032 std V42 ; save it
9033 ldd 2,s ; get original stack pointer
9034 std V44 ; save it
9035 clrb ; reset INIT1 to task 0 (and slow timer), could just be CLR INIT1
9036 stb INIT1
9037 lds V44 ; restore original stack pointer
9038 ldd V42 ; get back return address
9039 pshs d ; set return address on stack
9040 ldd V40 ; get back original D
9041 andcc #0xaf ; re-enable interrupts
9042 rts
9043 ; Select task register 1 as the active MMU set. Exit with interrupts disabled and the original
9044 ; stack pointer saved at the top of the temporary stack. Note that jmp [V42] could be used to
9045 ; return instead of pushing the return address back on the stack.
9046 SELTASK1 orcc #0x50 ; disable interrupts
9047 std V40 ; temp save D
9048 puls d ; get return address
9049 std V42 ; save it
9050 sts V44 ; save stack pointer
9051 ldb #1 ; set to enable task 1, slow timer input
9052 stb INIT1
9053 lds #TMPSTACK ; point to temporary stack location (top of the C000-Dfff range)
9054 ldd V44 ; get old stack pointer
9055 pshs d ; stash it
9056 ldd V42 ; put original return address back
9057 pshs d
9058 ldd V40 ; restore original D
9059 rts
9060 ; Tokenziation patch
9061 ALINK2 tst V41 ; is it a function token?
9062 bne SE152 ; brif so
9063 lda V42 ; get token value
9064 cmpa #0x62 ; have we reached the first SECB token?
9065 bls SE148 ; brif not
9066 ldu #COMVEC-5 ; point to function table and go again
9067 jmp LB8D7 ; re-enter mainline code
9068 SE148 lda #0x62 ; force tokens to start at the correct number (above Disk Basic)
9069 ldu #EBCOMTAB-10 ; point to SECB command table
9070 SE14D sta V42 ; set token counter to SECB values
9071 jmp LB89D ; re-enter mainstream still in command mode
9072 SE152 lda V42 ; get token number
9073 cmpa #0x29 ; have we run through SECB functions yet?
9074 bls SE15B ; brif not
9075 jmp LB8D7 ; re-enter mainline code (end of processing)
9076 SE15B lda #0x29 ; force token into SECB range (this leaves one unused)
9077 ldu #EBCOMTAB-5 ; point to SECB function table
9078 bra SE14D ; go transfer control back to mainline with new settings
9079 EBCOMTAB fcb 23 ; number of keywords (commands)
9080 fdb COMDIC20 ; keyword table (commands)
9081 fdb ALINK4 ; interpretation handler (commands)
9082 fcb 5 ; number of keywords (functions)
9083 fdb FUNDIC20 ; keyword table (functions)
9084 fdb ALINK5 ; interpretation handler (functions)
9085 fcb 0x00,0x00,0x00,0x00,0x00,0x00 ; marker for no further tables
9086 ; Detokenization patch. This routine has a bug. It freezes if an unknown token is encountered instead
9087 ; of using the placeholder.
9088 ALINK3 leau 10,u ; move to next table
9089 tst ,u ; valid table?
9090 lbne LB7F9 ; brif so - re-enter mainline code
9091 leax -1,x ; get token number
9092 lda ,x+
9093 anda #0x7f ; remove token bias
9094 cmpa #0x62 ; SECB command?
9095 blo SE18B ; brif not
9096 suba #0x62 ; zero-base SECB token number
9097 ldu #EBCOMTAB-10 ; point to command table
9098 bra ALINK3 ; go try again
9099 SE18B suba #0x29 ; zero-base function token
9100 ldu #EBCOMTAB-5 ; point to SECB function table
9101 bra ALINK3 ; go try again
9102 ; Command interpretation patch
9103 ALINK4 cmpa #0xe2 ; is it within the SECB range?
9104 blo SE19A ; brif not (below)
9105 cmpa #0xf8 ; is it above range?
9106 bls SE19E ; brif not - we have a SECB command
9107 SE19A jmp [COMVEC+23] ; transfer control onward to Disk Basic
9108 SE19E suba #0xe2 ; normalize SECB commands to 0
9109 ldx #COMDIS20 ; point to jump table for SECB commands
9110 jmp LADD4 ; go dispatch command
9111 ; Function processing patch
9112 ALINK5 cmpb #0x29*2 ; is it an SECB function?
9113 blo SE1AE ; brif not (below)
9114 cmpb #0x2d*2 ; is it still an SECB function?
9115 bls SE1B2 ; brif so
9116 SE1AE jmp [COMVEC+28] ; transfer control to Disk Basic
9117 SE1B2 subb #0x29*2 ; normalize SECB functions to 0
9118 cmpb #2*2 ; do we need to parse a parameter?
9119 bhs SE1BF ; brif not
9120 pshs b ; save token offset
9121 jsr LB262 ; parse parenthetical expression
9122 puls b ; get back token offset
9123 SE1BF ldx #FUNDIS20 ; point to jump table for SECB functions
9124 jmp LB2CE ; go dispatch function call
9125 ; Keyword table (commands) for SECB
9126 COMDIC20 fcs 'WIDTH' ; 0xe2
9127 fcs 'PALETTE' ; 0xe3
9128 fcs 'HSCREEN' ; 0xe4
9129 fcs 'LPOKE' ; 0xe5
9130 fcs 'HCLS' ; 0xe6
9131 fcs 'HCOLOR' ; 0xe7
9132 fcs 'HPAINT' ; 0xe8
9133 fcs 'HCIRCLE' ; 0xe9
9134 fcs 'HLINE' ; 0xea
9135 fcs 'HGET' ; 0xeb
9136 fcs 'HPUT' ; 0xec
9137 fcs 'HBUFF' ; 0xed
9138 fcs 'HPRINT' ; 0xee
9139 fcs 'ERR' ; 0xef
9140 fcs 'BRK' ; 0xf0
9141 fcs 'LOCATE' ; 0xf1
9142 fcs 'HSTAT' ; 0xf2
9143 fcs 'HSET' ; 0xf3
9144 fcs 'HRESET' ; 0xf4
9145 fcs 'HDRAW' ; 0xf5
9146 fcs 'CMP' ; 0xf6
9147 fcs 'RGB' ; 0xf7
9148 fcs 'ATTR' ; 0xf8
9149 ; Jump table for SECB commands
9150 COMDIS20 fdb WIDTH ; 0xe2 WIDTH
9151 fdb PALETTE ; 0xe3 PALETTE
9152 fdb HSCREEN ; 0xe4 HSCREEN
9153 fdb LPOKE ; 0xe5 LPOKE
9154 fdb HCLS ; 0xe6 HCLS
9155 fdb HCOLOR ; 0xe7 HCOLOR
9156 fdb HPAINT ; 0xe8 HPAINT
9157 fdb HCIRCLE ; 0xe9 HCIRCLE
9158 fdb HLINE ; 0xea HLINE
9159 fdb HGET ; 0xeb HGET
9160 fdb HPUT ; 0xec HPUT
9161 fdb HBUFF ; 0xed HBUFF
9162 fdb HPRINT ; 0xee HPRINT
9163 fdb ERR ; 0xef ERR (should be LB277)
9164 fdb BRK ; 0xf0 BRK (should be LB277)
9165 fdb LOCATE ; 0xf1 LOCATE
9166 fdb HSTAT ; 0xf2 HSTAT
9167 fdb HSET ; 0xf3 HSET
9168 fdb HRESET ; 0xf4 HRESET
9169 fdb HDRAW ; 0xf5 HDRAW
9170 fdb CMP ; 0xf6 CMP
9171 fdb RGB ; 0xf7 RGB
9172 fdb ATTR ; 0xf8 ATTR
9173 ; Keyword table for SECB functions
9174 FUNDIC20 fcs 'LPEEK' ; 0xa9
9175 fcs 'BUTTON' ; 0xaa
9176 fcs 'HPOINT' ; 0xab
9177 fcs 'ERNO' ; 0xac
9178 fcs 'ERLIN' ; 0xad
9179 ; Jump table for SECB functions
9180 FUNDIS20 fdb LPEEK ; 0xa9 LPEEK
9181 fdb BUTTON ; 0xaa BUTTON
9182 fdb HPOINT ; 0xab HPOINT
9183 fdb ERNO ; 0xac ERNO
9184 fdb ERLIN ; 0xad ERLIN
9185 ; Signon message patch
9186 ALINK12 ldx #L80E8-1 ; point to ECB's message
9187 jsr STRINOUT ; display it
9188 ldx #MWAREMS-1 ; point to Microware string
9189 jsr STRINOUT ; display it
9190 jmp L80B8 ; return to mainline code
9191 ; Signon message patch for Disk Basic 1.0
9192 ALINK28 ldx #DISK20MS-1 ; point to modified message
9193 jmp DC0DC-19 ; return to mainline code
9194 ; Signon message patch for Disk Basic 1.1
9195 ALINK29 ldx #DISK21MS-1 ; point to modified message
9196 jmp DC0DC ; return to mainline code
9197 DISK20MS fcc 'DISK EXTENDED COLOR BASIC 2.0'
9198 fcb 0x0d
9199 fcc 'COPR. 1981, 1986 BY TANDY'
9200 fcb 0x0d
9201 fcc 'UNDER LICENSE FROM MICROSOFT'
9202 fcb 0x0d
9203 MWAREMS fcc 'AND MICROWARE SYSTEMS CORP.'
9204 fcb 0x0d,0x0d,0x00
9205 DISK21MS fcc 'DISK EXTENDED COLOR BASIC 2.1'
9206 fcb 0x0d
9207 fcc 'COPR. 1982, 1986 BY TANDY'
9208 fcb 0x0d
9209 fcc 'UNDER LICENSE FROM MICROSOFT'
9210 fcb 0x0d
9211 fcc 'AND MICROWARE SYSTEMS CORP.'
9212 fcb 0x0d,0x0d,0x00
9213 ; Extended Basic extra initialization patch
9214 ALINK14 clra ; set up to clear things
9215 clrb
9216 lbrn 0
9217 stb H.CRSATT ; reset cursor attributes
9218 std HRMODE ; reset to VDG screen and no HSCREEN graphics
9219 std H.ONBRK ; reset ON BRK destination
9220 std H.ONERR ; reset ON ERR destinatin
9221 sta H.BCOLOR ; default HSCREEN background to 0
9222 lda #1 ; default HSCREEN foreground to 1
9223 sta H.FCOLOR
9224 lda #BLOCK6.4 ; map the HGET/HPUT buffers
9225 sta MMUREG
9226 ldd #0xffff ; mark as empty
9227 std 0
9228 lda #BLOCK7.0 ; restore memory map
9229 sta MMUREG
9230 jmp LAD19 ; go finish initializing (NEW)
9231 ; ON command patch
9232 ALINK18 cmpa #0xef ; ERR?
9233 beq ERR ; brif so
9234 cmpa #0xf0 ; BRK?
9235 beq BRK ; brif so
9236 jsr EVALEXPB ; evaluate the ON index argument
9237 jmp LAF45 ; return to mainline code
9238 SE3C2 jsr GETNCH ; eat the ERR/BRK token
9239 cmpa #0x81 ; GO?
9240 bne SE3CF ; brif not
9241 jsr GETNCH ; eat the GO
9242 cmpa #0xa5 ; TO?
9243 bne SE3CF ; brif not
9244 rts
9245 SE3CF leas 2,s ; clean up stack (not needed)
9246 jmp LB277 ; raise syntax error
9247 ; ERR jumps here if used as a command
9248 ; NOTE: you can do ERR <char> GOTO (where <char> is a single character that doesn't prevent GOTO from being tokenized
9249 ERR bsr SE3C2 ; check for GOTO
9250 jsr GETNCH ; eat the "TO"
9251 jsr LAF67 ; evaluate destination line number
9252 ldd BINVAL ; get line number
9253 std H.ONERR ; set error destination
9254 ldd CURLIN ; get current line number
9255 std H.ONERRS ; save line number where ON ERR was executed
9256 rts
9257 ; BRK jump shere if used as a command.
9258 ; Same note as for ERR applies.
9259 BRK bsr SE3C2 ; check for GOTO
9260 jsr GETNCH ; eat the "TO"
9261 jsr LAF67 ; evaluate destination line number
9262 ldd BINVAL ; get line number
9263 std H.ONBRK ; set break destination
9264 ldd CURLIN ; get current line number
9265 std H.ONBRKS ; save line number where ON BRK was executed
9266 rts
9267 ; Patches for &H parsing
9268 ALINK6A lsl 2,x ; multiply accumulator by 2
9269 rol 1,x
9270 rol ,x
9271 lbcs LBA92 ; brif we overflowed
9272 decb ; done enough shifts?
9273 bne ALINK6A ; brif not
9274 suba #'0 ; remove ASCII bias
9275 adda 2,x ; add digit to accumulator (this cannot cause carry)
9276 sta 2,x
9277 rts
9278 ALINK6B lbcs L8800 ; brif numeric
9279 jmp L883F ; return to mainline
9280 ; Line input patch
9281 ALINK16 cmpa #3 ; is it BREAK?
9282 orcc #1 ; set C for BREAK
9283 bne SE426 ; brif not BREAK
9284 pshs a,cc ; save character and break status
9285 lda HRMODE ; is it graphics mode?
9286 beq SE424 ; brif not
9287 clr HRMODE ; disable graphics mode
9288 jsr SETTEXT
9289 SE424 puls cc,a ; get back BREAK status and character
9290 SE426 jmp LA3C6 ; return to mainline
9291 ; Break check patch
9292 ALINK15 cmpa #3 ; BREAK?
9293 beq SE430 ; brif so
9294 jmp LADF4 ; re-enter mainline
9295 SE430 lda #1 ; BREAK flag
9296 sta H.ERRBRK
9297 lda CURLIN ; immediate mode?
9298 inca
9299 beq SE43F ; brif so
9300 ldd H.ONBRK ; is ON BRK active?
9301 bne SE449 ; brif so
9302 SE43F lda HRMODE ; graphics m ode?
9303 beq SE446 ; brif not
9304 jsr SETTEXT ; set text mode
9305 SE446 jmp STOP ; go handle BREAK
9306 SE449 std BINVAL ; set destination line number
9307 tst H.ERRBRK ; error or break?
9308 bne SE458 ; brif break
9309 lds FRETOP ; reset stack pointer
9310 ldd #LADC4 ; return to main loop
9311 pshs d
9312 SE458 jsr LAEEB ; move to end of line
9313 leax 1,x ; move past line terminator
9314 ldd BINVAL ; get desired line number
9315 cmpd CURLIN ; is it here or later?
9316 bhi SE466 ; brif so
9317 ldx TXTTAB ; start search at beginning
9318 SE466 jsr LAD05 ; find program line
9319 lbcs SE51E ; brif not found
9320 jmp LAEBB ; reset input pointer and return to main loop
9321 ; Error handling patch
9322 ALINK20 clr H.ERRBRK ; flag error handling
9323 lda CURLIN ; immediate mode?
9324 inca
9325 beq SE47D ; brif so
9326 ldx H.ONERR ; is ON ERR in effect
9327 bne SE4B3 ; brif so
9328 SE47D pshs a ; save register
9329 lda HRMODE ; set flags on graphics mode
9330 puls a ; get back A
9331 beq SE488 ; brif not graphics mode
9332 jsr SETTEXT ; force text mode
9333 SE488 cmpb #38*2 ; HG error?
9334 bne SE49F ; brif not
9335 jsr LB95C ; do newline
9336 jsr LB9AF ; do ?
9337 leax BAS20ERR,pcr ; point to error string
9338 SE496 jsr LACA0 ; display two character error message
9339 jsr LACA0
9340 jmp LAC65 ; return to mainline code
9341 SE49F cmpb #39*2 ; HP error?
9342 bne SE4B0 ; brif not
9343 jsr LB95C ; do newline
9344 jsr LB9AF ; do ?
9345 leax BAS20ERR+2,pcr ; point to error string
9346 jmp SE496 ; go finish up
9347 SE4B0 jmp LAC49 ; return to mainline error handler
9348 SE4B3 stb H.ERROR ; save error number
9349 pshs b ; save error number
9350 ldd CURLIN ; get current line number
9351 std H.ERLINE ; save line number where error occurred
9352 puls b ; get back error number
9353 cmpb #3*2 ; OD error?
9354 bne SE4C7 ; brif not
9355 ldd BINVAL ; restore input pointer
9356 std CHARAD
9357 SE4C7 tfr x,d ; save error destination line
9358 lbra SE449 ; go transfer control to error handler
9359 BAS20ERR fcc 'HR' ; 38 Hi resolution graphics error
9360 fcc 'HP' ; 39 Hi resolutuion print error
9361 ; NEW handling patch
9362 ALINK19 pshs d ; save D
9363 clra ; set up to clear things
9364 clrb
9365 std OLDPTR ; reset CONT address
9366 std H.ONBRK ; reset ON BRK line
9367 std H.ONERR ; reset ON ERR line
9368 std H.ERLINE ; reset error source line
9369 lda #0xff ; set error number to -1
9370 sta H.ERROR
9371 puls d ; restore d
9372 jmp LAD43 ; return to mainline
9373 ; ERNO function
9374 ERNO clra ; zero extend error number
9375 ldb H.ERROR ; get error number
9376 cmpb #0xff ; real?
9377 bne SE4F4 ; brif so
9378 sex ; return "-1"
9379 bra SE4FA
9380 SE4F4 cmpb #0xf1 ; error number 0xf1?
9381 bne SE4F9 ; brif not
9382 comb ; turn it back into UL error
9383 SE4F9 asrb ; error numbers are pre-multiplied by 2 - undo that
9384 SE4FA jmp GIVABF ; return error number
9385 ; ERLIN function
9386 ERLIN ldd H.ERLINE ; get the line number where the error occurred
9387 bra SE4FA ; return it - BUG: will treat lines above 32767 as negative
9388 ; Immediate mode patch
9389 ALINK21 jsr SETTEXT ; force text mode
9390 jsr LB95C ; do line feed if needed
9391 orcc #0x50 ; disable interrupts
9392 lda #BLOCK6.4 ; map HGET/HPUT buffers
9393 sta MMUREG
9394 ldd #0xffff ; mark buffers empty
9395 std 0
9396 lda #BLOCK7.0 ; restore memory map
9397 sta MMUREG
9398 andcc #0xaf ; re-enable interrupts
9399 jmp LAC76 ; return to mainline
9400 ; Handle undefined line in ON ERR or ON BRK
9401 SE51E tst H.ERRBRK ; break?
9402 beq SE528 ; brif not
9403 ldd H.ONBRKS ; get line number where ON BRK is
9404 bra SE52B
9405 SE528 ldd H.ONERRS ; get line number where ON ERR is
9406 SE52B std CURLIN ; reset the current line number there
9407 ldb #7*2 ; undefined line number
9408 jmp LAC49 ; raise error (bypass ON ERR check)
9409 ; INPUT patch
9410 ALINK17 ldd H.ONBRK ; is ON BRK operating?
9411 lbeq LAE11 ; brif not
9412 pshs d ; save destination line
9413 lda #1 ; set BREAK flag
9414 sta H.ERRBRK
9415 puls d ; get destination line
9416 lbra SE449 ; go handle ON BRK in INPUT
9417 ; LPOKE command
9418 LPOKE jsr LB141 ; evaluate numeric expression (address)
9419 lbrn 0
9420 bsr SE58E ; convert to extended address
9421 cmpb #BLOCK7.7 ; valid block number?
9422 lbhi LB44A ; brif not
9423 pshs x,b ; save block and offset
9424 jsr SYNCOMMA ; require a comma
9425 jsr EVALEXPB ; evaluate value to put in memory
9426 tfr b,a ; save value in A
9427 puls b,x ; get back block and offset
9428 cmpb #BLOCK7.7 ; valid block (we already tested this!!)
9429 lbhi LB44A ; brif not
9430 orcc #0x50 ; clobber interrupts
9431 lbsr SELBLOK0 ; map the block (by writing *all 16* MMU registers)
9432 sta ,x ; save byte in memory
9433 lbsr SETMMU ; unmap block (by writing *all 16* MMU registers)
9434 andcc #0xaf ; re-enable interrupts
9435 rts
9436 ; LPEEK function
9437 LPEEK bsr SE58E ; convert to block and offset
9438 lbrn 0
9439 cmpb #BLOCK7.7 ; valid block?
9440 lbhi LB44A ; brif not
9441 orcc #0x50 ; clobber interrupts
9442 lbsr SELBLOK0 ; map the block (by writing *all 16* MMU registers)
9443 ldb ,x ; get memory contents
9444 lbsr SETMMU ; restore map (by writing *all 16* MMU registers)
9445 andcc #0xaf ; re-enable interrupts
9446 jmp LB4F3 ; return B as unsigned
9447 SE58E pshs a ; save register
9448 lda FP0EXP ; is it in range for 0x80000?
9449 cmpa #0x93
9450 bls SE59A ; brif so
9451 ldb #BLOCK7.7+1 ; return illegal block number
9452 bra SE5AF
9453 SE59A jsr LBCC8 ; shift binary point to right of mantissa
9454 ldd FPA0+2 ; get low bits
9455 anda #0x1f ; mask off block number bits
9456 tfr d,x ; now X has the block offset
9457 ldd FPA0+1 ; get high bits
9458 asra ;* shift block number to the right of B; note that
9459 rorb ;* asr *should* be lsr but it works here because of
9460 asra ;* the maximum range of the value
9461 rorb
9462 asra
9463 rorb
9464 asra
9465 rorb
9466 asra
9467 rorb
9468 SE5AF puls a,pc ; restore registers and return
9469 ; BUTTON command
9470 BUTTON jsr INTCNV ; get button number
9471 lbrn 0
9472 cmpb #3 ; button number in range?
9473 lbhi LB44A ; raise error if not
9474 tfr b,a ; save button number
9475 clrb ; set B to 0xff (strobe no keyboard columns)
9476 comb
9477 ldx #PIA0 ; point to PIA0
9478 stb 2,x ; strobe nothing
9479 ldb ,x ; get button data
9480 cmpb #0x0f ; buttons are on bottom four rows
9481 beq SE5EA ; brif no buttons down
9482 leax SE5D5,pcr ; point to button mask routines
9483 asla ; four bytes per button routine
9484 asla
9485 jmp a,x ; jump to appropriate routine
9486 SE5D5 andb #1 ; keep button 1, right joystick
9487 bra SE5E3
9488 andb #4 ; keep button #1, left joystick
9489 bra SE5E3
9490 andb #2 ; keep button #2, right joystick
9491 bra SE5E3
9492 andb #8 ; keep button #2, left joystick
9493 SE5E3 bne SE5EA ; brif button was not down
9494 ldd #1 ; return nonzero if button down
9495 bra SE5EC ; return result
9496 SE5EA clra ; return zero if not down
9497 clrb
9498 SE5EC jsr GIVABF ; return result
9499 rts
9500 ; PALETTE command
9501 PALETTE cmpa #0xf7 ; RGB?
9502 lbrn 0
9503 bne SE600 ; brif not
9504 jsr GETNCH ; munch the RGB
9505 SE5FA leax IM.RGB,pcr ; point to RGB palette initializer
9506 bra SE634 ; go set palette registers
9507 SE600 cmpa #0xf6 ; CMP?
9508 bne SE60C ; brif not
9509 jsr GETNCH ; eat the CMP
9510 SE606 leax IM.CMP,pcr ; point to CMP palette initializer
9511 bra SE634 ; go set palette registers
9512 SE60C jsr SE7B2 ; evaluate two expressions
9513 ldx #PALETREG ; point to palette registers
9514 ldy #IM.PALET ; point to palette register images
9515 lda BINVAL+1 ; get palette number
9516 cmpa #16 ; valid entry?
9517 lbhs LB44A ; brif not 0-15
9518 leax a,x ; offset the pointers to the right entries
9519 leay a,y
9520 ldb VERBEG+1 ; get colour number
9521 cmpb #63 ; valid?
9522 bls SE62A ; brif so
9523 ldb #63 ; maximize to 63 (white)
9524 SE62A orcc #0x50 ; disable interrupts
9525 sync ; synchronize to VSYNC
9526 stb ,x ; set palette register
9527 stb ,y ; record it in image
9528 andcc #0xaf ; restore interrupts
9529 rts
9530 SE634 pshs x ; save source pointer
9531 ldy #IM.PALET ; point to palette register live image
9532 bsr SE648 ; copy source to the live image
9533 puls x ; get source back
9534 ldy #PALETREG ; point to palette registers
9535 orcc #0x50 ; disable interrupts
9536 sync ; synchronize to VSYNC
9537 bsr SE648 ; copy the colour values into the palette registers
9538 rts
9539 SE648 ldb #16-1 ; BUG: should be 16 - this doesn't set register #15
9540 SE64A lda ,x+ ; set a register
9541 sta ,y+
9542 decb ; done all?
9543 bne SE64A ; brif not
9544 andcc #0xaf ; re-enable interrupts
9545 rts
9546 IM.CMP fcb 18,36,11,7,63,31,9,38 ; palette values for CMP
9547 fcb 0,18,0,63,0,18,0,38
9548 IM.RGB fcb 18,54,9,36,63,27,45,38 ; palette values for RGB
9549 fcb 0,18,0,63,0,18,0,38
9550 ; CMP and RGB commands just jump to the relevant implementations above
9551 RGB bra SE5FA
9552 CMP bra SE606
9553 IM.PALET fcb 18,36,11,7,63,31,9,38 ; live palette images
9554 fcb 0,18,0,63,0,18,0,38
9555 ; HSCREEN command
9556 HSCREEN cmpa #0 ; end of line? BUG: won't work if colon terminates the command
9557 lbrn 0
9558 bne SE693 ; brif not end of line
9559 clrb ; default to HSCREEN 0 - turn off graphics
9560 bra SE69C
9561 SE693 jsr EVALEXPB ; evaluate HSCREEN argument
9562 cmpb #4 ; only 4 HSCREEN modes
9563 lbhi LB44A ; brif out of range
9564 SE69C stb HRMODE ; set graphics mode
9565 cmpb #0 ; HSCREEN 0?
9566 bne SE6A5 ; brif not
9567 jmp SETTEXT ; set text mode (disable graphics)
9568 SE6A5 stb HRMODE ; set graphics mode (we already did!)
9569 ldx #SE6CB ; point to bytes/row table
9570 subb #1 ; normalize mode to 0
9571 lda b,x ; get bytes per row value
9572 sta HORBYT ; set it
9573 cmpb #1 ; is it 1 or 2?
9574 bgt SE6B9 ; brif not
9575 ldd #160 ; default coordinate for middle of 320 screen
9576 bra SE6BC
9577 SE6B9 ldd #320 ; default coordainte for middle of 640 screen
9578 SE6BC std HORDEF ; set default horizontal coordinate
9579 ldd #96 ; set default vertical coordinate to middle
9580 std VERDEF
9581 ldb H.BCOLOR ; get background colour
9582 bsr CLRHIRES ; clear hi-res graphics screen
9583 jmp SETGRAPH ; set up to display the screen
9584 SE6CB fcb 80,160,80,160 ; bytes per row values for HSCREEN 1 through 4
9585 ; HCLS command
9586 HCLS bne SE6D6 ; brif not end of statement
9587 ldb H.BCOLOR ; get background colour as default
9588 bra CLRHIRES ; go clear screen
9589 SE6D6 bsr SE70E ; evaluate colour number
9590 CLRHIRES tst HRMODE ; graphics mode?
9591 beq SE6EF ; brif not
9592 bsr PIXELFIL ; get all pixels set byte
9593 jsr SELTASK1 ; swap screen in
9594 ldx #HRESSCRN ; point to start of screen
9595 SE6E4 stb ,x+ ; set a byte worth of pixels
9596 cmpx #HRESSCRN+0x8000 ; end of graphics memory?
9597 bne SE6E4 ; brif not
9598 jsr SELTASK0 ; restore memory map
9599 rts
9600 SE6EF ldb #38*2 ; code for HR error
9601 jmp LAC46 ; raise error
9602 ; HCOLOR command
9603 HCOLOR cmpa #', ; was a foreground colour given?
9604 lbrn 0
9605 beq SE705 ; brif not
9606 bsr SE70E ; evaluate colour number
9607 stb H.FCOLOR ; save foreground colour
9608 jsr GETCCH ; is there something after the foreground?
9609 beq SE70D ; brif not
9610 SE705 jsr SYNCOMMA ; insist on a comma
9611 bsr SE70E ; evaluate colour number
9612 stb H.BCOLOR ; set background colour
9613 SE70D rts
9614 ; Evaluate a colour number and make sure it's between 0 and 15 inclusive
9615 SE70E jsr EVALEXPB ; evaluate colour
9616 SE711 cmpb #16 ; is it in range?
9617 lbhs LB44A ; brif not
9618 rts
9619 SE718 jsr SE731 ; set working colour and pixel bytes to default
9620 jsr GETCCH ; is there a colour number?
9621 beq SE72F ; brif not
9622 cmpa #') ; )?
9623 beq SE72F ; brif so - no colour
9624 jsr SYNCOMMA ; insist on a comma
9625 cmpa #', ; another comma?
9626 beq SE72F ; brif so - colour not specified
9627 jsr SE70E ; evaluate colour
9628 bsr SE73B ; set working colour and pixel bytes
9629 SE72F jmp GETCCH ; get current character and return
9630 SE731 ldb H.FCOLOR ; get foreground colour
9631 tst SETFLG ; doing set?
9632 bne SE73B ; brif so
9633 ldb H.BCOLOR ; use background colour if doing reset
9634 SE73B stb WCOLOR ; save working colour
9635 bsr PIXELFIL ; get all pixel byte
9636 stb ALLCOL ; save all pixel byte
9637 rts
9638 ; Return B with all pixels set to colour number in B
9639 PIXELFIL pshs x ; save registers
9640 lda HRMODE ; get graphics mode
9641 suba #1 ; normalize mode numbers to start at 0
9642 ldx #SE759 ; point to colour masks
9643 andb a,x ; now B has only the relevant low bits of colour number
9644 lda HRMODE ; get graphics mode
9645 suba #1 ; normalize mode numbers to start at 0
9646 ldx #SE75D ; point to multiplier table
9647 lda a,x ; get multplier
9648 mul ; now B has all pixels set
9649 puls x,pc ; restore registers and return
9650 SE759 fcb 0x03,0x0f,0x01,0x03 ; colour masks to keep only necessary low bits
9651 SE75D fcb 0x55,0x11,0xff,0x55 ; multipliers to duplicate colour value across all pixels
9652 ; HSET command
9653 HSET lda #1 ; HSET flag
9654 bra SE76A
9655 ; HRESET command
9656 HRESET clra ; HRESET flag
9657 lbrn 0
9658 SE76A tst HRMODE ; are we in a graphics mode?
9659 beq SE6EF ; brif not - raise error
9660 sta SETFLG ; save our set/reset state
9661 jsr LB26A ; insist on (
9662 jsr SE7AA ; evaluate coordindates
9663 tst SETFLG ; resetting?
9664 bne SE77F ; brif so
9665 jsr SE731 ; set working colour and pixel byte
9666 bra SE782
9667 SE77F jsr SE718 ; evaluate colour number if present
9668 SE782 jsr LB267 ; insist on a )
9669 jsr HCALPOS ; fetch screen pointer address and pixel mask
9670 SE788 jsr SELTASK1 ; map the screen
9671 jsr SE792 ; set or reset the pixel
9672 jsr SELTASK0 ; unmap the screen
9673 rts
9674 SE792 ldb ,x ; get byte on screen
9675 pshs b ; save it
9676 tfr a,b ; duplicate mask
9677 coma ; invert the mask for clearing the screen data
9678 anda ,x ; reset the pixel
9679 andb ALLCOL ; set pixel mask to correct colour
9680 pshs b ; merge pixel colour into screen data
9681 ora ,s+
9682 sta ,x ; put modified data on screen
9683 suba ,s+ ; nonzero if the screen changed
9684 ora CHGFLG ; merge with existing change flag
9685 sta CHGFLG
9686 rts
9687 SE7AA jsr SE7B2 ; evaluate coordinates
9688 SE7AD ldu #HORBEG ; point to horizontal coordinates
9689 SE7B0 rts ; dummy "normalization" routine
9690 rts ; pointles RTS
9691 ; Evaluate two expressions (usually coordinates)
9692 SE7B2 jsr LB734 ; evaluate two expressions, first in BINVAL, second in B
9693 ldy #HORBEG ; point to horizontal coordinates
9694 SE7B9 cmpb #192 ; in range vertically?
9695 blo SE7BF ; brif so
9696 ldb #191 ; set to maximum coordinate
9697 SE7BF clra ; zero extend vertical
9698 std 2,y ; set vertical coordinate
9699 lda HRMODE ; get graphics mode
9700 cmpa #2 ; is it 1 or 2?
9701 bgt SE7CD ; brif not
9702 ldd #319 ; maximum coordinate for modes 1 and 2
9703 bra SE7D0
9704 SE7CD ldd #639 ; maximum coordindate for modes 3 and 4
9705 SE7D0 cmpd BINVAL ; is our max less than the specified one?
9706 blo SE7D7 ; brif so - keep max
9707 ldd BINVAL ; use specified coordinate
9708 SE7D7 std ,y ; save horizontal coordinate
9709 rts
9710 ; Calculate pixel mask and memory address for pixel
9711 HCALPOS bsr SE7E6 ; point to correct routine for current mode
9712 jmp ,u ; execute it
9713 CALTABLE fdb G2BITPIX ; HSCREEN 1
9714 fdb G4BITPIX ; HSCREEN 2
9715 fdb G1BITPIX ; HSCREEN 3
9716 fdb G2BITPIX ; HSCREEN 4
9717 SE7E6 ldu #CALTABLE ; point to routine table
9718 lda HRMODE ; get graphicsmode
9719 suba #1 ; zero-base it
9720 asla ; two bytes per address
9721 ldu a,u ; get routine address
9722 rts
9723 PIX1MASK fcb 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 ; pixel masks for 1 bpp
9724 PIX2MASK fcb 0xc0,0x30,0x0c,0x03 ; pxiel masks for 2 bpp
9725 PIX4MASK fcb 0xf0,0x0f ; pixel masks for 4 bpp
9726 G1BITPIX pshs u,b ; save registers
9727 ldb HORBYT ; get bytes per row
9728 lda VERBEG+1 ; get vergical coord
9729 mul ; now D is the offset to the start of the row
9730 addd #HRESSCRN ; add in start of screen in memory
9731 tfr d,x ; put it in a pointer
9732 ldd HORBEG ; get horiztonal coordindate
9733 lsra ; 8 pixels per byte do divide by 8
9734 rorb
9735 lsra
9736 rorb
9737 lsra
9738 rorb
9739 leax d,x ; offset to correct byte row
9740 lda HORBEG+1 ; get pixel number
9741 anda #7 ; keep only byte offset
9742 ldu #PIX1MASK ; point to 1 bpp masks
9743 lda a,u ; get pixel mask
9744 puls b,u,pc ; restore registers and return
9745 G2BITPIX pshs u,b ; save registers
9746 ldb HORBYT ; get number of bytes per row
9747 lda VERBEG+1 ; get horizontal coordinate
9748 mul ; now D is the offset to the start of the row
9749 addd #HRESSCRN ; add in memory offset to the screen
9750 tfr d,x ; put that in a pointer
9751 ldd HORBEG ; get horizontal coordinate
9752 lsra ; 4 pixels per byte so divide by 4
9753 rorb
9754 lsra
9755 rorb
9756 leax d,x ; now X points to the correct memory byte
9757 lda HORBEG+1 ; get horizontal coordinate
9758 anda #3 ; keep only the pixel number in the byte
9759 ldu #PIX2MASK ; point to 2 bpp pixel masks
9760 lda a,u ; get mask for this pixel
9761 puls b,u,pc ; restore registers and return
9762 G4BITPIX pshs u,b ; save registers
9763 ldb HORBYT ; get bytes per row
9764 lda VERBEG+1 ; get vertical coordinate
9765 mul ; now D is the offset to the start of the row
9766 addd #HRESSCRN ; add in memory address of start of screen
9767 tfr d,x ; put it in a pointer
9768 ldd HORBEG ; get horizontal coordinate
9769 lsra ; divide by 2 - only 2 pixels per byte
9770 rorb
9771 leax d,x ; now X points to the memory address of the pixel
9772 lda HORBEG+1 ; get horiztonal coordinate
9773 anda #1 ; keep offset into byte
9774 ldu #PIX4MASK ; point to 4 bpp pixel masks
9775 lda a,u ; get pixel mask
9776 puls b,u,pc ; restore registers and return
9777 ; HPOINT function
9778 HPOINT tst HRMODE ; is there a graphics mode?
9779 lbeq SE6EF ; brif not - raise error
9780 jsr LB26A ; insist on (
9781 jsr SE7AA ; evaluate coordinates
9782 jsr LB267 ; insist on )
9783 jsr SELTASK1 ; map the screen
9784 jsr HCALPOS ; get screen pointer
9785 tfr a,b ; save mask
9786 andb ,x ; get pixel data
9787 SE875 lsra ; is the pixel aligned right?
9788 bcs SE87B ; brif so
9789 lsrb ; shift right
9790 bra SE875 ; see if it's aligned yet
9791 SE87B jsr LB4F3 ; return colour number
9792 jsr SELTASK0 ; restore memory map
9793 rts
9794 ; HLINE command
9795 HLINE tst HRMODE ; is there a graphics mode active?
9796 lbeq SE6EF ; brif not - raise error
9797 lbrn 0
9798 cmpa #'( ; is there (?
9799 beq SE899 ; brif so - we have start coords
9800 cmpa #0xac ; -?
9801 beq SE899 ; brif no start given
9802 ldb #'@ ; make sure it's @ if not
9803 jsr LB26F
9804 SE899 jsr SE9E1 ; get start/end coords
9805 ldx HOREND ; put end in the defaults
9806 stx HORDEF
9807 ldx VEREND
9808 stx VERDEF
9809 jsr SYNCOMMA ; make sure comma
9810 cmpa #0xbe ; PRESET?
9811 beq SE8B4 ; brif so
9812 cmpa #0xbd ; PSET?
9813 lbne LB277 ; brif not
9814 ldb #1 ; set flag
9815 skip1lda
9816 SE8B4 clrb ; reset flag
9817 pshs b ; save set/reset flag
9818 jsr GETNCH ; eat the PSET/PRESET token
9819 jsr SEA0D ; normalize start/end
9820 puls b ; get back set/reset flag
9821 stb SETFLG ; save set/reset flag
9822 jsr SE731 ; set active colour byte
9823 jsr GETCCH ; is there more?
9824 lbeq SE94E ; brif not - no box
9825 jsr SYNCOMMA ; insist on a comma
9826 ldb #'B ; insist on a B
9827 jsr LB26F
9828 bne SE8EB ; brif something after B
9829 bsr SE906 ; draw horizontal line (top)
9830 bsr SE931 ; draw vertical line (left)
9831 ldx HORBEG ; save horizontal start
9832 pshs x
9833 ldx HOREND ; set up to draw vertical line (right)
9834 stx HORBEG
9835 bsr SE931 ; draw vertical line (right)
9836 puls x ; restore start coord
9837 stx HORBEG
9838 ldx VEREND ; set up to draw horizontal line (bottom)
9839 stx VERBEG
9840 bra SE906 ; draw horizontal line (bottom) and return
9841 SE8EB ldb #'F ; insist on F
9842 jsr LB26F
9843 bra SE8F6 ; draw a filled box
9844 SE8F2 leax -1,x ; move vertical coordinate up one
9845 SE8F4 stx VERBEG ; save new vertical coordinate
9846 SE8F6 jsr SE906 ; draw horizontal line
9847 ldx VERBEG ; get current coordinate
9848 cmpx VEREND ; above or below end?
9849 beq SE905 ; brif done
9850 bhs SE8F2 ; brif below - move up
9851 leax 1,x ; move down (we're above)
9852 bra SE8F4 ; draw another line
9853 SE905 rts
9854 SE906 ldx HORBEG ; get starting coordinate
9855 pshs x ; save it
9856 jsr SE9DB ; get absolute horizontal difference
9857 bcc SE913 ; brif end > start
9858 ldx HOREND ; get ending coordinate
9859 stx HORBEG ; save as starting position
9860 SE913 tfr d,y ; save difference (pixel count)
9861 leay 1,y ; bump it (coords are inclusive)
9862 jsr HCALPOS ; calculate pixel address
9863 puls u ; get start coordinate
9864 stu HORBEG ; restore it
9865 lbsr SEA16 ; point to routine to move pixel pointer right
9866 SE921 sta VD7 ; save pixel mask
9867 jsr SE788 ; turn on pixel
9868 lda VD7 ; get back pixel mask
9869 jsr ,u ; move one pixel right
9870 leay -1,y ; done all pixels?
9871 bne SE921 ; brif not
9872 rts
9873 SE92F puls d ; clean up stack
9874 SE931 ldd VERBEG ; get vertical start
9875 pshs d ; save it
9876 jsr SE9CD ; calculate absolute vertical difference
9877 bcc SE93E ; brif end > start
9878 ldx VEREND ; swap coordinate
9879 stx VERBEG
9880 SE93E tfr d,y ; save difference (pixel count)
9881 leay 1,y ; coordinates are inclusive
9882 jsr HCALPOS ; get screen pointer
9883 puls u ; get original start coord
9884 stu VERBEG ; restore it
9885 lbsr SEA21 ; get routine to move down one row
9886 bra SE921 ; draw vertical line
9887 SE94E ldy #SE9B8 ; point to vertical increment routine
9888 jsr SE9CD ; calculate absolute vertical difference
9889 beq SE906 ; draw horizontal if difference is 0
9890 bcc SE95D ; brif vertical end > vertical start
9891 ldy #SE9C6 ; point to decrement vertical routine
9892 SE95D pshs b,a ; save vertical difference
9893 ldu #SE9B1 ; point to horitzontal increment routine
9894 jsr SE9DB ; calculate absolute horizontal difference
9895 beq SE92F ; draw vertical line if difference is 0
9896 bcc SE96C ; brif horizontal end > horizontal start
9897 ldu #SE9BF ; point to decrement horizontal routine
9898 SE96C cmpd ,s ; compare horiztonal difference with vertical difference
9899 puls x ; get vertical difference back
9900 bhs SE977 ; brif horizontal difference is greater
9901 exg u,y ; swap major/minor directions
9902 exg d,x
9903 SE977 pshs u,d ; save larger difference and incr/decr routine
9904 pshs d ; save larger difference
9905 lsra ; divide larger difference by 2
9906 rorb
9907 bcs SE988 ; brif odd
9908 cmpu #SE9B8+1 ; inc or dec?
9909 blo SE988 ; brif inc
9910 subd #1 ; move back of dec (round down)
9911 SE988 pshs x,d ; save smaller difference and inc/dec
9912 jsr SE7E6 ; point to screen address routine
9913 SE98D jsr ,u ; convert coordinates to screen address
9914 jsr SE788 ; turn on pxiel
9915 ldx 6,s ; done all?
9916 beq SE9AD ; brif so
9917 leax -1,x ; account for pixel just drawn
9918 stx 6,s
9919 jsr [8,s] ; bump coordinate
9920 ldd ,s ; get minor coordinate increment counter
9921 addd 2,s ; add to minor coordinate
9922 std ,s ; save new minor increment
9923 subd 4,s ; subtract largest difference
9924 bcs SE98D ; brif result not bigger than largest difference
9925 std ,s ; save new minor increment
9926 jsr ,y ; inc/dec minor
9927 bra SE98D ; draw another pixel
9928 SE9AD puls x ; clean up stack
9929 puls d,x,y,u,pc ; clean up stack and return
9930 SE9B1 ldx HORBEG ; bump horizontal coord
9931 leax 1,x
9932 stx HORBEG
9933 rts
9934 SE9B8 ldx VERBEG ; bump vertical coord
9935 leax 1,x
9936 stx VERBEG
9937 rts
9938 SE9BF ldx HORBEG ; reduce horizontal coord
9939 leax -1,x
9940 stx HORBEG
9941 rts
9942 SE9C6 ldx VERBEG ; reduce vertical coord
9943 leax -1,x
9944 stx VERBEG
9945 SE9CC rts
9946 SE9CD ldd VEREND ; get vertical end
9947 subd VERBEG ; get subtract start
9948 SE9D1 bcc SE9CC ; brif end > start
9949 pshs cc ; save flag for which is >
9950 nega ; negate difference
9951 negb
9952 sbca #0
9953 puls cc,pc ; restore status andreturn
9954 SE9DB ldd HOREND ; get horizontal end coord
9955 subd HORBEG ; subtract start coord
9956 bra SE9D1 ; handle going negative
9957 ; Evaluate two sets of coordinates
9958 SE9E1 ldx HORDEF ; set start to default
9959 stx HORBEG
9960 ldx VERDEF
9961 stx VERBEG
9962 cmpa #0xac ; -?
9963 beq SE9F0 ; brif so - use default start
9964 jsr SEA04 ; evaluate coordinate pair
9965 SE9F0 ldb #0xac ; insist on -
9966 jsr LB26F
9967 jsr LB26A ; insist on (
9968 jsr LB734 ; evaluate two expressions (X, B)
9969 ldy #HOREND ; point to end coords
9970 jsr SE7B9 ; validate end coords
9971 bra SEA0A ; handle rest of evaluation
9972 SEA04 jsr LB26A ; insist on (
9973 jsr SE7B2 ; evaluate coordinates with range check
9974 SEA0A jmp LB267 ; insist on )
9975 SEA0D jsr SE7AD ; "normalize" start
9976 ldu #HOREND ; point to end coords
9977 jmp SE7B0 ; "normalize" end
9978 ; Point U to routine to move pixel to right
9979 SEA16 ldu #SEA25 ; point to jump table
9980 ldb HRMODE ; get graphics mode
9981 subb #1 ; zero-base it
9982 aslb ; two bytes per entry
9983 ldu b,u ; get routine address
9984 rts
9985 SEA21 ldu #SEA45 ; point to routine to move down one row
9986 rts
9987 SEA25 fdb SEA34 ; HSCREEN 1 right
9988 fdb SEA3D ; HSCREEN 2 right
9989 fdb SEA2D ; HSCREEN 3 right
9990 fdb SEA34 ; HSCREEN 4 right
9991 SEA2D lsra ; move pixel mask right
9992 bcc SEA33 ; brif not changing bytes
9993 rora ; shift mask back around to left
9994 leax 1,x ; move byte forward
9995 SEA33 rts
9996 SEA34 lsra ; move one pixel right
9997 lsra
9998 bcc SEA33 ; brif same byte
9999 lda #0xc0 ; reset pixel mask
10000 leax 1,x ; move to next byte
10001 rts
10002 SEA3D coma ; flip pixels
10003 cmpa #0xf0 ; did we move to a new byte?
10004 bne SEA44 ; brif not
10005 leax 1,x ; move to next byte
10006 SEA44 rts
10007 SEA45 ldb HORBYT ; get number of bytes per row
10008 abx ; move ahead that many
10009 rts
10010 ; HCIRCLE command
10011 HCIRCLE tst HRMODE ; graphics mode?
10012 lbeq SE6EF ; brif not - raise error
10013 lbrn 0
10014 cmpa #'@ ; is there @ before coords?
10015 bne SEA59 ; brif not
10016 jsr GETNCH ; eat the @
10017 SEA59 jsr SEB60 ; get max coords for video mode
10018 jsr SEA04 ; parse centre coords
10019 jsr SE7AD ; normalize coordinates (ha ha)
10020 ldx ,u ; get horizontal coordinate
10021 stx VCB ; save it
10022 ldx 2,u ; get vertical coordinate
10023 stx VCD ; save it
10024 jsr SYNCOMMA ; insist on a comma
10025 jsr LB73D ; evaluate expression into X (radius)
10026 ldu #VCF ; point to temp storage area
10027 stx ,u ; save radius
10028 jsr SE7B0 ; normalize - pointless
10029 lda #1 ; put into "set" mode
10030 sta SETFLG
10031 jsr SE718 ; evaluate colour
10032 ldx #0x100 ; default H/W ratio (1:1)
10033 jsr GETCCH ; is the an HW ratio?
10034 beq SEA95 ; brif not
10035 jsr SYNCOMMA ; insist on comma
10036 jsr LB141 ; evaluate HW ratio
10037 lda FP0EXP ; multiply by 256
10038 adda #8
10039 sta FP0EXP
10040 jsr LB740 ; fetch HW ratio to X (with a fixed 8 bit fraction part)
10041 SEA95 lda HRMODE ; get graphics mode
10042 cmpa #2 ; is it a 320 mode?
10043 bhi SEA9F ; brif not
10044 tfr x,d ; double HW ratio for 320 modes
10045 leax d,x
10046 SEA9F stx VD1 ; save H/W ratio
10047 ldb #1 ; go into SET mode
10048 stb SETFLG
10049 stb VD8 ; flag for "first arc"
10050 jsr SEB7B ; evaluate start point (octant, subarc)
10051 pshs d ; save start point
10052 jsr SEB7B ; evaluate end point
10053 std VD9 ; save end point
10054 puls d ; get back start point
10055 SEAB3 pshs d ; save current circle position
10056 ldx HOREND ; switch previous end coords in as the start
10057 stx HORBEG
10058 ldx VEREND
10059 stx VERBEG
10060 ldu #CIRCDATA+2 ; point to sines/cosines table
10061 anda #1 ; is it an even octant?
10062 beq SEAC7 ; brif so
10063 negb ; swap arc order for odd octants
10064 addb #8
10065 SEAC7 aslb ; four bytes per table entry
10066 aslb
10067 leau b,u ; now U points to the correct entry
10068 pshs u ; save table entry
10069 jsr SEBBD ; calculate horizontal offset
10070 puls u ; get back table pointer
10071 leau -2,u ; move to other entry
10072 pshs x ; save horizontal offset
10073 jsr SEBBD ; calculaute vertical offset
10074 puls y ; get back horizontal offset
10075 lda ,s ; get octant number
10076 anda #3 ; is it 0 or 4?
10077 beq SEAE7 ; brif so
10078 cmpa #3 ; is it 3 or 7?
10079 beq SEAE7 ; brif so
10080 exg x,y ; swap horizontal and vertical otherwise
10081 SEAE7 stx HOREND ; save horizontal offset
10082 tfr y,d ; divide offset by 2
10083 lsra
10084 rorb
10085 ldx VD1 ; get H/W ratio
10086 jsr SEBCB ; multiply offset by ratio
10087 tfr y,d ; did MSB (bits 23-16) end up nonzero?
10088 tsta ; brif so - outside 16 bit range
10089 lbne LB44A ; brif so - raise error
10090 stb VEREND ; save vertical offset MSB
10091 tfr u,d ; get low bytes of result
10092 sta VEREND+1 ; save LSB (lose fractional part)
10093 lda ,s ; get octant number
10094 cmpa #2 ; 0 or 1?
10095 blo SEB13 ; brif so
10096 cmpa #6 ; 6 or h?
10097 bhs SEB13 ; brif so
10098 ldd VCB ; get horizontal center
10099 subd HOREND ; subtract offset (going left)
10100 bcc SEB20 ; brif we didn't go negative
10101 clra ; minimize to 0
10102 clrb
10103 bra SEB20
10104 SEB13 ldd VCB ; get horizontal centre
10105 addd HOREND ; add offset
10106 bcs SEB1E ; brif we overflowed
10107 cmpd VD3 ; did we overflow screen size?
10108 blo SEB20 ; brif not
10109 SEB1E ldd VD3 ; maximize horizontal coordinate
10110 SEB20 std HOREND ; save new horizontal coordinate
10111 lda ,s ; get octantnumber
10112 cmpa #4 ; is it 0-3 (bottom half)?
10113 blo SEB32 ; brif so
10114 ldd VCD ; get vertical centre
10115 subd VEREND ; subtract offset
10116 bcc SEB3F ; brif we didn't run past 0
10117 clra ; minimize to 0
10118 clrb
10119 bra SEB3F
10120 SEB32 ldd VCD ; get vertical centre
10121 addd VEREND ; add offset
10122 bcs SEB3D ; brif we overflowed
10123 cmpd VD5 ; did we go past end of screen?
10124 blo SEB3F ; brif not
10125 SEB3D ldd VD5 ; maximize to screen size
10126 SEB3F std VEREND ; save new vertical coord
10127 tst VD8 ; was this the first coordinate?
10128 bne SEB48 ; brif so - don't draw a line
10129 lbsr SE94E ; draw the subarc line
10130 SEB48 puls d ; get octant and arc
10131 lsr VD8 ; test if first point, and clear flag
10132 bcs SEB53 ; brif first coord
10133 cmpd VD9 ; at end of circle?
10134 beq SEB5F ; brif so
10135 SEB53 incb ; bump arc counter
10136 cmpb #8 ; done 8 subarcs?
10137 bne SEB5C ; brif not
10138 inca ; bump octant
10139 clrb ; reset arc counter
10140 anda #7 ; wrap octant number if needed
10141 SEB5C jmp SEAB3 ; move on with the next arc
10142 SEB5F rts
10143 SEB60 ldu #VD3 ; point to storage area
10144 ldx #639 ; set max horizontal coord for 640 mode
10145 stx ,u
10146 lda HRMODE ; get graphics mode
10147 cmpa #2 ; is it a 640 mode?
10148 bgt SEB73 ; brif so
10149 ldx #319 ; set max horzontalcoord for 320 mode
10150 stx ,u
10151 SEB73 ldx #191 ; all modes have a 191 vertical max
10152 stx 2,u
10153 jmp SE7B0 ; "normalize" coords
10154 SEB7B clrb ; default circle start/end to 0
10155 jsr GETCCH ; is there a fraction?
10156 beq SEB91 ; brif not
10157 jsr SYNCOMMA ; insist on a comma
10158 jsr LB141 ; evaluate circle fraction
10159 lda FP0EXP ; multiply by 64 (calculate # of 64ths)
10160 adda #6
10161 sta FP0EXP
10162 jsr LB70E ; fetch result as 8 bits unsigned
10163 andb #0x3f ; keep only the fraction part
10164 SEB91 tfr b,a ; copy fraction to A (for octant)
10165 andb #7 ; keep only arc number in B
10166 lsra ; shift octant number to right of A
10167 lsra
10168 lsra
10169 rts
10170 CIRCDATA fdb 0x0000,0x0001 ; subarc 0
10171 fdb 0xfec5,0x1919 ; subarc 1
10172 fdb 0xfb16,0x31f2 ; subarc 2
10173 fdb 0xf4fb,0x4a51 ; subarc 3
10174 fdb 0xec84,0x61f9 ; subarc 4
10175 fdb 0xe1c7,0x78ae ; subarc 5
10176 fdb 0xd4dc,0x8e3b ; subarc 6
10177 fdb 0xc5e5,0xa269 ; subarc 7
10178 fdb 0xb506,0xb506 ; subarc 8
10179 SEBBD ldx VCF ; get radius
10180 ldd ,u ; get sin/cos value
10181 beq SEBCA ; brif 0 - just use radius
10182 subd #1 ; subtract 1
10183 bsr SEBCB ; do the multiplication dance
10184 tfr y,x ; save result to X
10185 SEBCA rts
10186 SEBCB pshs u,y,x,b,a ; save registers and reserve storage
10187 clr 4,s ; clear high bits
10188 lda 3,s ; B*XL
10189 mul
10190 std 6,s ; save in partical result
10191 ldd 1,s ; A*XH
10192 mul
10193 addb 6,s ; add to partial product
10194 adca #0
10195 std 5,s
10196 ldb ,s ; A*XL
10197 lda 3,s
10198 mul
10199 addd 5,s ; add to partial product
10200 std 5,s
10201 bcc SEBEA
10202 inc 4,s
10203 SEBEA lda ,s ; A*XH
10204 ldb 2,s
10205 mul
10206 addd 4,s ; add to partial product
10207 std 4,s ; save final product bits
10208 puls a,b,x,y,u,pc ; save factors, retrieve result, and return
10209 ; HPAINT command
10210 HPAINT tst HRMODE ; do we have a grahpics mode?
10211 lbeq SE6EF ; brif not - raise error
10212 lbrn 0
10213 cmpa #'@ ; is there @ before the coords?
10214 bne SEC05 ; brif not
10215 jsr GETNCH ; eat the @
10216 SEC05 jsr SEA04 ; insist on (
10217 jsr SE7AD ; evaluate the coordinates
10218 lda #1 ; set up for "setting"
10219 sta SETFLG
10220 jsr SE718 ; evaluate colour code
10221 ldd WCOLOR ; get working colour and all pixels byte
10222 pshs d ; save them for later
10223 jsr GETCCH ; do we have a border colour?
10224 beq SEC1D ; brif not - use default
10225 jsr SE718 ; evaluate border colour
10226 SEC1D lda ALLCOL ; get border colour pixel byte
10227 sta VD8 ; save it
10228 puls d ; get paint colour details
10229 std WCOLOR ; restore them
10230 jsr SELTASK1 ; map the graphics screen
10231 clra ;* add a terminator block to the top of the stack
10232 pshs u,x,b,a ;* which is how HPAINT knows it's done
10233 jsr SEB60 ; get maximum coordinate values
10234 jsr SE7E6 ; point U to routine that selects a pixel
10235 stu VD9 ; save pixel selection routine address
10236 jsr SECBE ; paint from current coord to the left
10237 beq SEC47 ; brif no painting done - we started on the border
10238 jsr SED01 ; paint to the right
10239 lda #1 ; set up a record to paint down the screen
10240 sta VD7
10241 jsr SED2E
10242 neg VD7 ; set up a record to paint up the screen
10243 jsr SED2E
10244 SEC47 sts TMPSTK ; save stack pointer
10245 SEC4A tst CHGFLG ; see if a pixel changed
10246 bne SEC51 ; brif so
10247 lds TMPSTK ; get stack pointer back
10248 SEC51 puls a,b,x,u ; get data for the next line to handle
10249 clr CHGFLG ; flag nothing changed yet
10250 sts TMPSTK ; save new stack address
10251 leax 1,x ; add one to the start position
10252 STX HORBEG ; set it as the starting position
10253 stu VD1 ; save length of parent line
10254 sta VD7 ; save up/down flag
10255 beq SECBA ; brif up/down is 0 - end marker
10256 bmi SEC6A ; brif we're going up the screen
10257 incb ; bump vertical coord
10258 cmpb VD6 ; at end of screen?
10259 bls SEC6E ; brif not
10260 clrb ; wrap around - this will cause us to bail below
10261 SEC6A tstb ; is coord 0?
10262 beq SEC4A ; brif so - don't go upward
10263 decb ; move upward on the screen
10264 SEC6E stb VERBEG+1 ; save new vertical coordinate
10265 jsr SECBE ; paint to the left
10266 beq SEC86 ; brif no pixels changed
10267 cmpd #3 ; less than 3 painted?
10268 blo SEC80 ; brif so - no need to check for paintable data
10269 leax -2,x ; move coord left two
10270 jsr SED15 ; save block of paint data in the other direction (vertically)
10271 SEC80 jsr SED01 ; paint to the right
10272 SEC83 jsr SED2E ; save a block of paint data in the same direction
10273 SEC86 coma ; invert number of pixels painted (but "less 1")
10274 comb
10275 SEC88 addd VD1 ; add to length of parent line
10276 std VD1 ; now we have the new parent line length
10277 ble SECA5 ; brif parent line was shorter
10278 jsr SE9B1 ; bump horizontal
10279 jsr SECF1 ; check for border
10280 bne SEC9B ; brif not
10281 ldd #-1 ; count down
10282 bra SEC88 ; keep looking
10283 SEC9B jsr SE9BF ; move left
10284 jsr SED3A ; save horizontal coord
10285 bsr SECC7 ; paint to the right
10286 bra SEC83 ; save paint block and keep going
10287 SECA5 jsr SE9B1 ; bump horizontal coord
10288 leax d,x ; point to right of end of parent line
10289 stx HORBEG ; set as start coord
10290 coma ; negate pixel count (and subtract 2?)
10291 comb
10292 subd #1
10293 ble SECB7 ; brif line doesn't extend past right of parent
10294 tfr d,x ; save portion of line to the right as length
10295 bsr SED15 ; save block of paint data
10296 SECB7 jmp SEC4A ; go process more paint blocks
10297 SECBA jsr SELTASK0 ; unmap screen
10298 rts
10299 SECBE jsr SED3A ; point starting coord in end
10300 ldy #SE9BF ; point to dec horizontal
10301 bra SECCD ; paint line
10302 SECC7 ldy #SE9B1 ; point to incr horizontal coord
10303 jsr ,y ; skip first - already done
10304 SECCD ldu ZERO ; initial pixel counter to 0
10305 ldx HORBEG ; get starting coord
10306 SECD1 bmi SECEA ; brif off the left side
10307 cmpx VD3 ; at max value?
10308 bhi SECEA ; brif off right side
10309 pshs u,y ; save counter and inc/dec p ointer
10310 bsr SECF1 ; check for border
10311 beq SECE8 ; brif so - we're done
10312 jsr SE792 ; set pixel
10313 puls y,u ; restore count and inc/dec routine
10314 leau 1,u ; bump count
10315 jsr ,y ; adjust coord
10316 bra SECD1 ; go do another pixel
10317 SECE8 puls y,u ; get back counter and inc/dec pointer
10318 SECEA tfr u,d ; save paint counter in D and X
10319 tfr d,x
10320 subd ZERO ; set flags on counter
10321 rts
10322 SECF1 jsr [VD9] ; get address of pixel
10323 tfr a,b ; duplicate mask
10324 andb VD8 ; get pixel colour mask for the pixel
10325 pshs b,a ; save masks
10326 anda ,x ; merge in with pixel data on screen
10327 cmpa 1,s ; does it match? (Z set if so)
10328 puls a,b,pc ; restore masks and return
10329 SED01 std VCD ; save pixel count
10330 ldy HOREND ; get last horizontal coord
10331 bsr SED3A ; save current coord
10332 sty HORBEG ; start painting to right from the previous end
10333 bsr SECC7 ; go paint rightward
10334 ldx VCD ; get previous pixel count
10335 leax d,x ; now we have a total count for this line
10336 addd #1 ; bump it by one?
10337 rts
10338 SED15 std VCB ; save painted pixel count
10339 puls y ; get return address
10340 ldd HORBEG ; get start coord
10341 pshs x,d ; save start coord and line length
10342 lda VD7 ; get direction
10343 nega ; invert it
10344 SED20 ldb VERBEG+1 ; get vertical coordinate
10345 pshs b,a ; save direction and vertical coord
10346 pshs y ; put return address back
10347 ldb #6 ; make sure we didn't overflow the stack
10348 jsr SED3F
10349 ldd VCB ; get line length back
10350 rts
10351 SED2E std VCB ; save line length
10352 puls y ; get return address
10353 ldd HOREND ; get horizontal start
10354 pshs x,d ; save line length and horizontal coord
10355 lda VD7 ; get direction flag
10356 bra SED20 ; finish saving frame
10357 SED3A ldx HORBEG ; get start coord
10358 stx HOREND ; save it as end coord
10359 rts
10360 SED3F negb ; subtract B bytes from S
10361 leas b,s
10362 cmps #TMPSTACK-(0x2000+14) ; does it overflow? (14 extra is from the unused vectors at the top of the CB ROM area)
10363 lblo SED4E ; raise OM error if we did
10364 negb ; restore stack pointer
10365 leas b,s
10366 rts
10367 SED4E lds #TMPSTACK-2 ; reset stack (since we overflowed it)
10368 jsr SELTASK0 ; restore default memory map
10369 jmp LAC44 ; raise OM error
10370 ; HBUFF command
10371 HBUFF jsr LB73D ; evaluate buffer number to X
10372 lbrn 0
10373 cmpx #255 ; valid?
10374 lbhi LB44A ; brif not
10375 stx VD1 ; save buffer number
10376 beq SED72 ; don't get size if buffer 0 select
10377 jsr SYNCOMMA ; insist on a comma
10378 jsr LB73D ; evaluate size to X
10379 stx VD3 ; save buffer size
10380 SED72 jsr SE0CB ; map the buffers
10381 jsr SELTASK1
10382 ldd VD1 ; get buffer number
10383 tstb ; is it zero (not needed!)
10384 bne SED85 ; brif not
10385 ldd #0xffff ; clear all buffers
10386 std HRESBUFF
10387 bra SEDBD ; reset memory map and return
10388 SED85 ldy #HRESBUFF ; point to buffers
10389 ldd ,y ; get address of next block
10390 cmpd #0xffff ; empty buffer space?
10391 bne SED95 ; brif not
10392 bsr SEDC4 ; check for room in buffer space
10393 bra SEDB0 ; set up buffer
10394 SED95 ldb VD1+1 ; get buffer number
10395 SED97 cmpb 2,y ; is this buffer the same number?
10396 beq SEDD2 ; brif so - throw error
10397 ldu ,y ; get address of next buffer
10398 beq SEDA3 ; brif last buffer
10399 tfr u,y ; move on to next buffer
10400 bra SED97 ; see if we have a matching number here
10401 SEDA3 tfr y,u ; save start address to U
10402 ldd 3,y ; get size of last buffer
10403 leay 5,y ; move past header
10404 leay d,y ; move past buffer data
10405 bsr SEDC4 ; check for enough room
10406 sty ,u ; save pointer to the new buffer in previous header
10407 SEDB0 ldd #0 ; mark this as the last buffer
10408 std ,y
10409 ldb VD1+1 ; set buffer number
10410 stb 2,y
10411 ldd VD3 ; set buffer size
10412 std 3,y
10413 SEDBD jsr SELTASK0 ; restore memory map
10414 jsr SETMMU
10415 rts
10416 SEDC4 tfr y,x ; point X to the start of the buffer data
10417 leax 5,x
10418 ldd VD3 ; get length requested
10419 leax d,x ; point to end of new buffer
10420 cmpx #HRESBUFF+0x1f00 ; does it fit?
10421 bhi SEDD6 ; brif not
10422 rts
10423 SEDD2 ldb #9*2 ; code for redim array
10424 bra SEDD8
10425 SEDD6 ldb #6*2 ; code for out of memory
10426 SEDD8 lds #TMPSTACK-2 ; reset stack
10427 jsr SELTASK0 ; restore memory map
10428 jsr SETMMU
10429 jmp LAC46 ; raise error
10430 ; HGET command
10431 HGET ldx #SEEC0 ; point to HGET movement routine
10432 stx VD5 ; save it
10433 clrb ; flag for "GET"
10434 bra SEDF4 ; get on with things
10435 ; HPUT command
10436 HPUT ldx #SEEEF ; point to HPUT movement routine
10437 stx VD5 ; save it
10438 ldb #1 ; flag for "PUT"
10439 SEDF4 tst HRMODE ; check for graphics
10440 lbeq SE6EF ; brif not - raise error
10441 lbrn 0
10442 stb VD8 ; save GET/PUT flag
10443 cmpa #'@ ; is there @ before coords?
10444 bne SEE06 ; brif not
10445 jsr GETNCH ; eat the @
10446 SEE06 jsr SE9E1 ; evaluate box bounds
10447 jsr SYNCOMMA ; insist on a comma
10448 jsr EVALEXPB ; evaluate buffer number
10449 stb VD3 ; save buffer number
10450 clr VD4 ; default action to none
10451 jsr GETCCH ; is there an action flag?
10452 beq SEE38 ; brif not
10453 com VD4 ; flag for action flag specified
10454 jsr SYNCOMMA ; insist on a comma
10455 tst VD8 ; is it GET?
10456 bne SEE23 ; brif not
10457 lbra LB277 ; raise error
10458 SEE23 ldb #5 ; 5 possible actions
10459 ldx #SEEE0 ; point to action routine table address
10460 SEE28 ldu ,x++ ; get routine address
10461 cmpa ,x+ ; does the action match?
10462 beq SEE34 ; brif so
10463 decb ; checked all of them?
10464 bne SEE28 ; brif not
10465 jmp LB277 ; raise error
10466 SEE34 stu VD5 ; save action address
10467 jsr GETNCH ; eat the action token
10468 SEE38 jsr SE0CB ; map the buffers and screen
10469 jsr SELTASK1
10470 ldb VD3 ; get buffer number
10471 jsr SEF18 ; find the correct buffer's data
10472 ldd HORBEG ; get horizontal start
10473 cmpd HOREND ; is it less than end?
10474 ble SEE50 ; brif so
10475 ldx HOREND ; swap start/end horizontal coords
10476 stx HORBEG
10477 std HOREND
10478 SEE50 ldd VERBEG ; get vertical start
10479 cmpd VEREND ; less that end?
10480 ble SEE5D ; brif so
10481 ldx VEREND ; swap vertical coords
10482 stx VERBEG
10483 std VEREND
10484 SEE5D lda HRMODE ; get graphics mode
10485 ldb #0xf8 ; round off mask for mode 3 (1 bpp)
10486 cmpa #3 ; is it mode 3 (1 bpp)
10487 beq SEE6D ; brif so
10488 ldb #0xfc ; mask for mode 1 or 4 (2 bpp)
10489 cmpa #2 ; is it mode 2?
10490 bne SEE6D ; brif not - it's mode 1 or 4
10491 ldb #0xfe ; round off mask for mode 2 (4 bpp)
10492 SEE6D tfr b,a ; save round off in A and B - we need it twice
10493 anda HORBEG+1 ; round off horizontal start
10494 sta HORBEG+1
10495 andb HOREND+1 ; round of horizontal end coord
10496 stb HOREND+1
10497 jsr SE9DB ; calculate horizontal difference
10498 std HOREND ; save it
10499 jsr SE9CD ; calculate vertial difference
10500 addd #1 ; make it inclusive
10501 std VEREND ; save it
10502 lda HRMODE ; get graphics mode
10503 cmpa #2 ; HSCREEN 2?
10504 beq SEE96 ; divide pixel count by 2 for byte count
10505 cmpa #3 ; HSCREEN 3?
10506 bne SEE92 ; brif not - divide by 4 (HSCREEN 1, 4)
10507 lsr HOREND ; divide by 8 (falls through to by 4)
10508 ror HOREND+1
10509 SEE92 lsr HOREND ; divide by 4 (falls through to divide by 2)
10510 ror HOREND+1
10511 SEE96 lsr HOREND ; divide by 2
10512 ror HOREND+1
10513 ldd HOREND ; get byte count
10514 addd #1 ; make it inclusive of the end
10515 std HOREND
10516 jsr HCALPOS ; get pointer to screen location
10517 ldy VD5 ; point to action routine address
10518 SEEA7 ldb HOREND+1 ; get LS byte of byte count
10519 pshs x ; save line start pointer
10520 SEEAB jsr ,y ; perform movement action
10521 decb ; done all bytes?
10522 bne SEEAB ; brif not
10523 puls x ; get back line start
10524 jsr SEA45 ; move down one line
10525 dec VEREND+1 ; done all rows?
10526 bne SEEA7 ; brif not
10527 jsr SELTASK0 ; restore memory map
10528 jsr SETMMU
10529 rts
10530 SEEC0 lda ,x+ ; get a byte from screen
10531 bsr SEEC7 ; point to proper buffer location
10532 sta ,u ; save it
10533 rts
10534 SEEC7 ldu VCF ; get buffer pointer
10535 leau 1,u ; move to next byte
10536 stu VCF ; save new pointer
10537 cmpu VD1 ; did we run past the end of the buffer?
10538 bhi SEED3 ; brif so - raise error
10539 rts
10540 SEED3 lds #TMPSTACK-2 ; reset stack
10541 jsr SELTASK0 ; restore memory map
10542 jsr SETMMU
10543 jmp LB44A ; raise FC error
10544 SEEE0 fdb SEEEF ; PSET action routine
10545 fcb 0xbd ; PSET token
10546 fdb SEEF6 ; PRESET action routine
10547 fcb 0xbe ; PRESET token
10548 fdb SEF07 ; OR action routine
10549 fcb 0xb1 ; OR token
10550 fdb SEEFE ; AND action routine
10551 fcb 0xb0 ; AND token
10552 fdb SEF10 ; NOT action routine
10553 fcb 0xa8 ; NOT token
10554 SEEEF bsr SEEC7 ; point to buffer location
10555 lda ,u ; get byte from buffer
10556 sta ,x+ ; put it on screen
10557 rts
10558 SEEF6 bsr SEEC7 ; point to buffer location
10559 lda ,u ; get byte
10560 coma ; invert it
10561 sta ,x+ ; put it on screen
10562 rts
10563 SEEFE bsr SEEC7 ; point to buffer location
10564 lda ,u ; get byte from buffer
10565 anda ,x ; "AND" with screen data
10566 sta ,x+ ; put it on screen
10567 rts
10568 SEF07 bsr SEEC7 ; point to buffer location
10569 lda ,u ; get byte from buffer
10570 ora ,x ; "OR" with screen data
10571 sta ,x+ ; put on screen
10572 rts
10573 SEF10 bsr SEEC7 ; point to buffer address
10574 lda ,x ; get byte from screen (BUG: should be ,u to get from buffer)
10575 coma ; invert data
10576 sta ,x+ ; save on screen
10577 rts
10578 SEF18 ldy #HRESBUFF ; point to start of buffers
10579 lda ,y ; are there any buffers?
10580 cmpa #0xff
10581 bne SEF2C ; brif so
10582 jmp SEED3 ; raise error if no buffers
10583 SEF25 ldy ,y ; point to next buffer
10584 lbeq SEED3 ; brif end of buffers - raise error
10585 SEF2C cmpb 2,y ; is this the desired buffer?
10586 bne SEF25 ; brif not
10587 ldd 3,y ; get size of buffer
10588 leay 4,y ; point to start of data (less one for "pre-inc" on use
10589 sty VCF ; save buffer pointer
10590 leay 1,y ; point to actual data start
10591 leay d,y ; calculate address of end of buffer
10592 sty VD1 ; save end address
10593 rts
10594 ; HPRINT command
10595 HPRINT tst HRMODE ; graphics mode?
10596 lbeq SE6EF ; brif not - raise error
10597 lbrn 0
10598 jsr LB26A ; insist on (
10599 jsr SE7B2 ; evaluate coordinates
10600 jsr LB267 ; insist on )
10601 jsr SYNCOMMA ; insist on comma
10602 jsr LB156 ; evaluate print string
10603 tst VALTYP ; is it string?
10604 bne SEF62 ; brif not numeric (should be BMI)
10605 jsr LBDD9 ; convert number to string
10606 jsr LB516 ; save string in string space and all that jazz
10607 SEF62 jsr LB657 ; fetch string details
10608 stb H.PCOUNT ; save length in print count
10609 ldy #H.PBUF ; point to temporary string buffer
10610 SEF6C decb ; have we processed the whole string?
10611 bmi SEF75 ; brif so (or if the string length was > 128)
10612 lda ,x+ ; copy a character from the string into the buffer
10613 sta ,y+
10614 bra SEF6C ; see if we're done yet
10615 SEF75 lda HRMODE ; get graphics mode
10616 ldb #40 ; 40 characters on a 320 line
10617 cmpa #3 ; is it mode 1 or 2?
10618 blo SEF7F ; brif so
10619 ldb #80 ; 80 characters on a 640 line
10620 SEF7F clra ; zero extend line size
10621 subd HORBEG ; subtract first position from line length
10622 bmi SF001 ; brif we're printing off the side of the screen
10623 cmpb H.PCOUNT ; is the print count larger than characters left?
10624 bhi SEF8E ; brif not
10625 stb H.PCOUNT ; save remaining screen positions as print count
10626 beq SF001 ; brif nothing to print
10627 SEF8E lda #ROWMAX-1 ; get highest row number
10628 cmpa VERBEG+1 ; are we in range?
10629 bge SEF96 ; brif so
10630 sta VERBEG+1 ; force bottom row if not in range
10631 SEF96 jsr SF08C ; calculate actual pixel coordinates
10632 jsr HCALPOS ; get screen pointer
10633 ldy #H.PBUF ; point to string data
10634 ldb H.PCOUNT ; get number of characters to print
10635 SEFA3 lda ,y ; get character to print
10636 anda #0x7f ; lose bit 7 (character set repeats)
10637 suba #0x20 ; lose the "control" characters - no glyphs for those codes
10638 bpl SEFAD ; brif it was not a control character
10639 lda #0 ; use a space if it was
10640 SEFAD sta ,y+ ; put glyph number into the buffer
10641 decb ; processed all of them?
10642 bgt SEFA3 ; brif not
10643 lda HRMODE ; get graphics mode
10644 deca ; zero-base it
10645 asla ; two bytes per display routine
10646 ldy #SF002 ; point to display routine table
10647 ldy a,y ; point to display routine
10648 sty VD1 ; save it
10649 lda #8 ; 8 rows per character
10650 sta VD3 ; temp save row counter
10651 ldy #H.PBUF ; point to print buffer
10652 ldu #SF09D ; point to FONT data
10653 ldb H.FCOLOR ; get foreground colour
10654 jsr PIXELFIL ; get an all pixel byte
10655 stb ALLCOL ; save it
10656 jsr SELTASK1 ; map the screen
10657 lda H.PCOUNT ; get character count to display
10658 SEFD9 pshs y,x,a ; save buffer pointer, character count, and screen address
10659 SEFDB ldb ,y+ ; get character from buffer
10660 clra ; zero extend it
10661 aslb ;* 8 bytes per character entry (don't need rola after first
10662 aslb ;* because characters are only 7 bits
10663 rola
10664 aslb
10665 rola
10666 lda d,u ; get font data for this row
10667 jsr [VD1] ; display it
10668 dec H.PCOUNT ; done all characters on this row?
10669 bgt SEFDB ; brif not
10670 puls a,x,y ; get back character count, buffer pointer, and screen address
10671 dec VD3 ; have we done all the rows?
10672 beq SEFFE ; brif so
10673 sta H.PCOUNT ; restore print count
10674 leau 1,u ; move one row down the font data
10675 jsr SEA45 ; move one row down the screen
10676 bra SEFD9 ; go do another row of pixels
10677 SEFFE jsr SELTASK0 ; restore memory map
10678 SF001 rts
10679 SF002 fdb SF01A ; HSCREEN 1 (2 bpp)
10680 fdb SF045 ; HSCREEN 2 (4 bpp)
10681 fdb SF00A ; HSCREEN 3 (1 bpp)
10682 fdb SF01A ; HSCREEN 4 (2 bpp)
10683 SF00A pshs a ; save font data
10684 coma ; invert it
10685 anda ,x ; merge with screen - turns off pixels in the character
10686 sta ,x ; save it back on the screen
10687 puls a ; get back font data
10688 anda ALLCOL ; merge with colour data
10689 ora ,x ; merge with screen to fill hole created above
10690 sta ,x+ ; save it on screen
10691 rts
10692 SF01A pshs y ; save buffer pointer
10693 ldy #SF035 ; point to 2 bpp pixel masks
10694 tfr a,b ; copy character data (need two bytes per character)
10695 lsra ; use the upper 4 bits in first byte
10696 lsra
10697 lsra
10698 lsra
10699 lda a,y ; get pixel mask for all 16 possibilities for upper 4 bits
10700 jsr SF00A ; shove it on screen
10701 andb #0x0f ; lose upper bits for low half
10702 lda b,y ; get pixel mask for this pixel combination
10703 jsr SF00A ; shove that on screen too
10704 puls y ; restore buffer pointer
10705 rts
10706 SF035 fcb 0x00,0x03,0x0c,0x0f ; combined pixel masks for 16 possibilities for a 2 bpp byte
10707 fcb 0x30,0x33,0x3c,0x3f
10708 fcb 0xc0,0xc3,0xcc,0xcf
10709 fcb 0xf0,0xf3,0xfc,0xff
10710 SF045 pshs y,a ; save buffer pointer and font data
10711 ldy #SF06C ; point to 16 colour masks
10712 lsra ; fetch high 4 bits
10713 lsra
10714 lsra
10715 lsra
10716 asla ; two bytes per mask (this is NOT redundant - this and above clears bit 0)
10717 ldd a,y ; get two byte mask for these four bits
10718 jsr SF00A ; show upper 2 pixels
10719 tfr b,a ; show lower 2 pixels
10720 jsr SF00A
10721 puls a ; get back font data
10722 anda #0x0f ; lost upper bits
10723 asla ; two bytes per mask
10724 ldd a,y ; get mask data
10725 jsr SF00A ; show upper 2 pixels
10726 tfr b,a ; show lower 2 pixels
10727 jsr SF00A
10728 puls y ; restore buffer pointer
10729 rts
10730 SF06C fdb 0x0000,0x000f,0x00f0,0x00ff ; combined pixel masks for 16 possibilities for a 4 bpp double byte
10731 fdb 0x0f00,0x0f0f,0x0ff0,0x0fff
10732 fdb 0xf000,0xf00f,0xf0f0,0xf0ff
10733 fdb 0xff00,0xff0f,0xfff0,0xffff
10734 SF08C ldd HORBEG ; get horizontal character cell coordinate
10735 aslb ; times 8 - 8x8 font data; note first shift can't cause carry with max 79 for column number
10736 aslb
10737 rola
10738 aslb
10739 rola
10740 std HORBEG ; save actual horizontal pixel position of print position
10741 lda VERBEG+1 ; get vertical character cell coordinate
10742 asla ; times 8 - 8x8 font data
10743 asla
10744 asla
10745 sta VERBEG+1 ; save actual vertical pixel position of print position
10746 rts
10747 ; This is the HPRINT font, which is basically equivalent to the hardware font in the GIME for character codes
10748 ; 0x20 through 0x7f. It does not include the extra characters in the 0x00-0x1f range of the hardware character
10749 ; set. However, glyphs for those are actually included in the ROM above the end of the actual code.
10750 SF09D fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; SPACE
10751 fcb 0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00 ; !
10752 fcb 0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00 ; "
10753 fcb 0x28,0x28,0x7C,0x28,0x7C,0x28,0x28,0x00 ; #
10754 fcb 0x10,0x3C,0x50,0x38,0x14,0x78,0x10,0x00 ; $
10755 fcb 0x60,0x64,0x08,0x10,0x20,0x4C,0x0C,0x00 ; %
10756 fcb 0x20,0x50,0x50,0x20,0x54,0x48,0x34,0x00 ; &
10757 fcb 0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00 ; '
10758 fcb 0x08,0x10,0x20,0x20,0x20,0x10,0x08,0x00 ; (
10759 fcb 0x20,0x10,0x08,0x08,0x08,0x10,0x20,0x00 ; )
10760 fcb 0x00,0x10,0x54,0x38,0x38,0x54,0x10,0x00 ; *
10761 fcb 0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00 ; +
10762 fcb 0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x20 ; ,
10763 fcb 0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00 ; -
10764 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00 ; .
10765 fcb 0x00,0x04,0x08,0x10,0x20,0x40,0x00,0x00 ; /
10766 fcb 0x38,0x44,0x4C,0x54,0x64,0x44,0x38,0x00 ; 0
10767 fcb 0x10,0x30,0x10,0x10,0x10,0x10,0x38,0x00 ; 1
10768 fcb 0x38,0x44,0x04,0x38,0x40,0x40,0x7C,0x00 ; 2
10769 fcb 0x38,0x44,0x04,0x08,0x04,0x44,0x38,0x00 ; 3
10770 fcb 0x08,0x18,0x28,0x48,0x7C,0x08,0x08,0x00 ; 4
10771 fcb 0x7C,0x40,0x78,0x04,0x04,0x44,0x38,0x00 ; 5
10772 fcb 0x38,0x40,0x40,0x78,0x44,0x44,0x38,0x00 ; 6
10773 fcb 0x7C,0x04,0x08,0x10,0x20,0x40,0x40,0x00 ; 7
10774 fcb 0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00 ; 8
10775 fcb 0x38,0x44,0x44,0x38,0x04,0x04,0x38,0x00 ; 9
10776 fcb 0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00 ; :
10777 fcb 0x00,0x00,0x10,0x00,0x00,0x10,0x10,0x20 ; ;
10778 fcb 0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00 ; <
10779 fcb 0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00 ; =
10780 fcb 0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x00 ; >
10781 fcb 0x38,0x44,0x04,0x08,0x10,0x00,0x10,0x00 ; ?
10782 fcb 0x38,0x44,0x04,0x34,0x4C,0x4C,0x38,0x00 ; @
10783 fcb 0x10,0x28,0x44,0x44,0x7C,0x44,0x44,0x00 ; A
10784 fcb 0x78,0x24,0x24,0x38,0x24,0x24,0x78,0x00 ; B
10785 fcb 0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00 ; C
10786 fcb 0x78,0x24,0x24,0x24,0x24,0x24,0x78,0x00 ; D
10787 fcb 0x7C,0x40,0x40,0x70,0x40,0x40,0x7C,0x00 ; E
10788 fcb 0x7C,0x40,0x40,0x70,0x40,0x40,0x40,0x00 ; F
10789 fcb 0x38,0x44,0x40,0x40,0x4C,0x44,0x38,0x00 ; G
10790 fcb 0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00 ; H
10791 fcb 0x38,0x10,0x10,0x10,0x10,0x10,0x38,0x00 ; I
10792 fcb 0x04,0x04,0x04,0x04,0x04,0x44,0x38,0x00 ; J
10793 fcb 0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00 ; K
10794 fcb 0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00 ; L
10795 fcb 0x44,0x6C,0x54,0x54,0x44,0x44,0x44,0x00 ; M
10796 fcb 0x44,0x44,0x64,0x54,0x4C,0x44,0x44,0x00 ; N
10797 fcb 0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00 ; O
10798 fcb 0x78,0x44,0x44,0x78,0x40,0x40,0x40,0x00 ; P
10799 fcb 0x38,0x44,0x44,0x44,0x54,0x48,0x34,0x00 ; Q
10800 fcb 0x78,0x44,0x44,0x78,0x50,0x48,0x44,0x00 ; R
10801 fcb 0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00 ; S
10802 fcb 0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x00 ; T
10803 fcb 0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00 ; U
10804 fcb 0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00 ; V
10805 fcb 0x44,0x44,0x44,0x44,0x54,0x6C,0x44,0x00 ; W
10806 fcb 0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00 ; X
10807 fcb 0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00 ; Y
10808 fcb 0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00 ; Z
10809 fcb 0x38,0x20,0x20,0x20,0x20,0x20,0x38,0x00 ; ]
10810 fcb 0x00,0x40,0x20,0x10,0x08,0x04,0x00,0x00 ; \
10811 fcb 0x38,0x08,0x08,0x08,0x08,0x08,0x38,0x00 ; [
10812 fcb 0x10,0x38,0x54,0x10,0x10,0x10,0x10,0x00 ; UP ARROW
10813 fcb 0x00,0x10,0x20,0x7C,0x20,0x10,0x00,0x00 ; LEFT ARROW
10814 fcb 0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00 ; ^
10815 fcb 0x00,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00 ; a
10816 fcb 0x40,0x40,0x58,0x64,0x44,0x64,0x58,0x00 ; b
10817 fcb 0x00,0x00,0x38,0x44,0x40,0x44,0x38,0x00 ; c
10818 fcb 0x04,0x04,0x34,0x4C,0x44,0x4C,0x34,0x00 ; d
10819 fcb 0x00,0x00,0x38,0x44,0x7C,0x40,0x38,0x00 ; e
10820 fcb 0x08,0x14,0x10,0x38,0x10,0x10,0x10,0x00 ; f
10821 fcb 0x00,0x00,0x34,0x4C,0x4C,0x34,0x04,0x38 ; g
10822 fcb 0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x00 ; h
10823 fcb 0x00,0x10,0x00,0x30,0x10,0x10,0x38,0x00 ; i
10824 fcb 0x00,0x04,0x00,0x04,0x04,0x04,0x44,0x38 ; j
10825 fcb 0x40,0x40,0x48,0x50,0x60,0x50,0x48,0x00 ; k
10826 fcb 0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00 ; l
10827 fcb 0x00,0x00,0x68,0x54,0x54,0x54,0x54,0x00 ; m
10828 fcb 0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x00 ; n
10829 fcb 0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00 ; o
10830 fcb 0x00,0x00,0x78,0x44,0x44,0x78,0x40,0x40 ; p
10831 fcb 0x00,0x00,0x3C,0x44,0x44,0x3C,0x04,0x04 ; q
10832 fcb 0x00,0x00,0x58,0x64,0x40,0x40,0x40,0x00 ; r
10833 fcb 0x00,0x00,0x3C,0x40,0x38,0x04,0x78,0x00 ; s
10834 fcb 0x20,0x20,0x70,0x20,0x20,0x24,0x18,0x00 ; t
10835 fcb 0x00,0x00,0x44,0x44,0x44,0x4C,0x34,0x00 ; u
10836 fcb 0x00,0x00,0x44,0x44,0x44,0x28,0x10,0x00 ; v
10837 fcb 0x00,0x00,0x44,0x54,0x54,0x28,0x28,0x00 ; w
10838 fcb 0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x00 ; x
10839 fcb 0x00,0x00,0x44,0x44,0x44,0x3C,0x04,0x38 ; y
10840 fcb 0x00,0x00,0x7C,0x08,0x10,0x20,0x7C,0x00 ; z
10841 fcb 0x08,0x10,0x10,0x20,0x10,0x10,0x08,0x00 ; {
10842 fcb 0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x00 ; |
10843 fcb 0x20,0x10,0x10,0x08,0x10,0x10,0x20,0x00 ; }
10844 fcb 0x20,0x54,0x08,0x00,0x00,0x00,0x00,0x00 ; ~
10845 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00 ; _
10846 ; HDRAW command
10847 HDRAW tst HRMODE ; grahics mode?
10848 lbeq SE6EF ; brif not
10849 lbrn 0
10850 ldx #0 ; set empty string for "end of DRAW"
10851 ldb #1
10852 pshs x,b
10853 stb SETFLG ; set up for "set" mode
10854 stx VD5 ; clear update and draw flags
10855 jsr SE731 ; set up color byte
10856 jsr LB156 ; evaluate command string
10857 SF3B8 jsr LB654 ; fetch command string details
10858 bra SF3C5 ; interpret command string
10859 SF3BD jsr SF591 ; fetch command character
10860 jmp SF5A7 ; evaluate number
10861 SF3C3 puls b,x ; get "caller" command string details
10862 SF3C5 stb VD8 ; save string pointer
10863 beq SF3C3 ; brif end of string - try another
10864 stx VD9 ; set string data pointer
10865 lbeq SF4D0 ; brif we hit the top of the stack
10866 SF3CF tst VD8 ; is there anything left?
10867 beq SF3C3 ; brif not
10868 jsr SF591 ; get command character
10869 cmpa #'; ; separator?
10870 beq SF3CF ; brif so - ignore it
10871 cmpa #'' ; '?
10872 beq SF3CF ; brif so - ignore that too
10873 cmpa #'N ; update toggle?
10874 bne SF3E6 ; brif not
10875 com VD5 ; toggle the "update" flag (if set, return to original position after)
10876 bra SF3CF ; process more
10877 SF3E6 cmpa #'B ; blank modifier?
10878 bne SF3EE ; brif not
10879 com VD6 ; toggle "draw" flag - 0 = draw, nonzero = don't draw
10880 bra SF3CF ; process more
10881 SF3EE cmpa #'X ; substring call?
10882 lbeq SF4A1 ; brif so - process it
10883 cmpa #'M ; M (move)?
10884 lbeq SF54C ; brif so - process "move"
10885 pshs a ; save command character
10886 ldb #1 ; default count if no number follows
10887 clr VD3 ; clear MS byte of count
10888 stb VD4 ; save LS byte of count
10889 tst VD8 ; is there anything left?
10890 beq SF417 ; brif not
10891 jsr SF591 ; get command character
10892 jsr LB3A2 ; set C if not alpha
10893 pshs cc ; save alpha flag
10894 jsr SF5F2 ; back up command pointer
10895 puls cc ; get back alpha flag
10896 bcc SF417 ; brif command is alpha
10897 bsr SF3BD ; evaluate decimal string
10898 SF417 puls a ; get command back
10899 cmpa #'C ; C (colour)?
10900 beq SF445 ; brif so
10901 cmpa #'A ; A (angle)?
10902 beq SF451 ; brif so
10903 cmpa #'S ; S (scale)?
10904 beq SF45C ; brif so
10905 cmpa #'U ; U (up)?
10906 beq SF496 ; brif so
10907 cmpa #'D ; D (down)?
10908 beq SF492 ; brif so
10909 cmpa #'L ; L (left)?
10910 beq SF48C ; brif so
10911 cmpa #'R ; R (right)?
10912 beq SF485 ; brif so
10913 suba #'E ; shift E,F,G,H to be 0-3
10914 beq SF473 ; brif E (UR)
10915 deca ; F (DR)
10916 beq SF46D ; brif so
10917 deca ; G (DL)
10918 beq SF47D ; brif so
10919 deca ; H (UL)
10920 beq SF467 ; brif so
10921 jmp LB44A ; raise error if unrecognized command
10922 SF445 jsr SE711 ; adjust colour code for graphics mode
10923 stb H.FCOLOR ; set new foreground
10924 jsr SE731 ; set up colour byte
10925 lbra SF3CF ; handle another command
10926 SF451 cmpb #4 ; only 4 angles valid
10927 lbhs LB44A ; brif invalid angle
10928 stb ANGLE ; save draw angle
10929 lbra SF3CF ; go handle another command
10930 SF45C cmpb #63 ; only 0-62 are valid scale factors
10931 lbhs LB44A ; brif invalid scale
10932 stb SCALE ; set scale factor
10933 lbra SF3CF ; process another command
10934 SF467 lda VD3 ; get count MSB
10935 bsr NEGACCD ; negate horizontal difference (go left)
10936 bra SF46F ; go the same distance up
10937 SF46D lda VD3 ; get count MSB
10938 SF46F tfr d,x ; go same distance right as down
10939 bra SF4D4 ; go handle movement/drawing
10940 SF473 lda VD3 ; get MSB of count
10941 tfr d,x ; going same distance on both axes
10942 bsr NEGACCD ; negate the vertical distance
10943 exg d,x ; put vertical in X, horizontal in D
10944 bra SF4D4 ; go handle drawing and moving
10945 SF47D lda VD3 ; get MSB of count
10946 tfr d,x ; go same distance on both axes
10947 bsr NEGACCD ; go left horizontally (and down vertically)
10948 bra SF4D4 ; go handle drawing and moving
10949 SF485 lda VD3 ; get MSB of difference (going right)
10950 SF487 ldx #0 ; no vertical movement
10951 bra SF4D4 ; handle drawing/moving
10952 SF48C lda VD3 ; get MSB of count
10953 bsr NEGACCD ; negate because going left
10954 bra SF487 ; set no vertical difference, handle drawing/moving
10955 SF492 lda VD3 ; get MSB of count
10956 bra SF49A ; go make horizontal difference 0, use positive distance for down
10957 SF496 lda VD3 ; get MSB of count
10958 bsr NEGACCD ; use negative distance for up
10959 SF49A ldx #0 ; use 0 horizontal distance
10960 exg x,d ; put horizontal and vertical in the right places
10961 bra SF4D4 ; go move/draw
10962 SF4A1 jsr SF611 ; interpret command as a variable
10963 ldb #2 ; see if we're about to run out of memory
10964 jsr LAC33
10965 ldb VD8 ; get remaining characters in current command string
10966 ldx VD9 ; get current command string pointer
10967 pshs x,b ; save the stack frame
10968 jmp SF3B8 ; go evaluate the string
10969 SF4B2 ldb SCALE ; get scaling factor
10970 beq SF4D1 ; brif none - use full scale
10971 clra ; zero extend scale
10972 exg d,x ; put distance in D, save scale factor
10973 sta ,-s ; save MSB of distance and set flags on sign
10974 bpl SF4BF ; brif positive distance
10975 bsr NEGACCD ; make it positive if negative
10976 SF4BF jsr SEBCB ; multiply D and X
10977 tfr U,D ; save LSW in D
10978 lsra ; divide by 4
10979 rorb
10980 lsra
10981 rorb
10982 tst ,s+ ; was original positive?
10983 bpl SF4D0 ; brif so
10984 NEGACCD nega ; negate D
10985 negb
10986 sbca #0
10987 SF4D0 rts
10988 SF4D1 tfr x,d ; keep unmodified distance
10989 rts
10990 SF4D4 pshs d ; save horizontal distance
10991 bsr SF4B2 ; apply scale factor to vertical distance
10992 puls x ; get back horizontal distance
10993 pshs d ; save scaled vertical distance
10994 bsr SF4B2 ; apply scale to horizontal distance
10995 puls x ; get back the vertical distance
10996 ldy ANGLE ; get draw angle (using Y to avoid clobbering D)
10997 pshs y ; save it
10998 SF4E5 tst ,s ; check angle
10999 beq SF4F1 ; brif no angle
11000 exg x,d ;* swap horizontal and vertical distances then negate new horizontal
11001 bsr NEGACCD ;* distance, which rotates 90° counterclockwise
11002 dec ,s ; count down the angle
11003 bra SF4E5 ; see if we have rotated enough times
11004 SF4F1 puls y ; clean up stack
11005 ldu #0 ; default end position to 0
11006 addd HORDEF ; add distance to current draw position
11007 bmi SF4FC ; brif we went negative - use minimal 0
11008 tfr d,u ; use calculated draw coordinate
11009 SF4FC tfr x,d ; fetch vertical distance for calculation
11010 ldx #0 ; default end position to 0
11011 addd VERDEF ; add distance to draw position
11012 bmi SF507 ; brif we went negative - use minimal 0
11013 tfr d,x ; use calculated coordinate
11014 SF507 cmpu #640 ; is it out of range completely?
11015 blo SF510 ; brif not
11016 ldu #639 ; maximize to right edge of screen
11017 SF510 lda HRMODE ; get graphics mode
11018 cmpa #2 ; is it a 320 mode?
11019 bgt SF51F ; brif not
11020 cmpu #320 ; out of range for 320 mode?
11021 blo SF51F ; brif not
11022 ldu #319 ; maximize to right edge of screen
11023 SF51F cmpx #192 ; out of range vertically?
11024 blo SF527 ; brif not
11025 ldx #191 ; maximize to bottom of screen
11026 SF527 ldd HORDEF ; set start position to current draw position
11027 std HORBEG
11028 ldd VERDEF
11029 std VERBEG
11030 stx VEREND ; set calculated position as end position
11031 stu HOREND
11032 tst VD5 ; are we going to update draw position?
11033 bne SF53B ; brif not
11034 stx VERDEF ; set new draw position
11035 stu HORDEF
11036 SF53B jsr SEA0D ; "normalize" coordinates
11037 tst VD6 ; are we doing to draw a line?
11038 bne SF545 ; brif not
11039 jsr SE94E ; draw a line
11040 SF545 clr VD5 ; reset the "update" flag
11041 clr VD6 ; reset the "draw" flag
11042 jmp SF3CF ; go handle another command
11043 SF54C jsr SF591 ; get input character
11044 pshs a ; save it
11045 jsr SF578 ; evaluate horizontal distance
11046 pshs d ; save it
11047 jsr SF591 ; get a character
11048 cmpa #', ; is it a comma separator?
11049 lbne LB44A ; brif not - raise error
11050 jsr SF575 ; evaluate the vertical distance
11051 tfr d,x ; save vertical distance
11052 puls u ; get horizontal distance
11053 puls a ; get first command character
11054 cmpa #'+ ; +?
11055 beq SF570 ; treat coordinates as relative displacements
11056 cmpa #'- ; -?
11057 bne SF507 ; brif neither + or -; treat as absolute coordinates
11058 SF570 tfr u,d ; put horizontal distance in D
11059 jmp SF4D4 ; treat distances as offsets
11060 SF575 jsr SF591 ; get character
11061 SF578 cmpa #'+ ; +?
11062 beq SF583 ; brif so - do positive
11063 cmpa #'- ; -?
11064 beq SF584 ; brif so - do negative
11065 jsr SF5F2 ; back up input pointer
11066 SF583 clra ; flag positive
11067 SF584 pshs a ; save sign flag
11068 jsr SF3BD ; evaluate decimal number
11069 tst ,s+ ; is it positive?
11070 beq SF590 ; brif so
11071 negb ; negate the value - BUG: should be JSR NEGACCD; this code sequence doesn't work
11072 sbca #0
11073 SF590 rts
11074 SF591 pshs x ; save register
11075 SF593 tst VD8 ; is there anything to fetch?
11076 lbeq LB44A ; brif not - raise error
11077 ldx VD9 ; get command pointer
11078 lda ,x+ ; get command character
11079 stx VD9 ; save updated pointer
11080 dec VD8 ; account for character consumed
11081 cmpa #0x20 ; space?
11082 beq SF593 ; brif so - skip it
11083 puls x,pc ; restore register and return
11084 SF5A7 cmpa #'= ; is it variable equate?
11085 bne SF5B6 ; brif not
11086 pshs u,y ; save registers
11087 bsr SF611 ; interpret variable in command string
11088 jsr LB3E9 ; convert to integer in D
11089 std VD3 ; save as count
11090 puls y,u,pc ; restore registers and return
11091 SF5B6 jsr SF608 ; clear carry if numeric
11092 lbcs LB44A ; bail if not numeric
11093 clr VD3 ; initialize count to 0
11094 clr VD4
11095 SF5C1 suba #'0 ; remove ASCII bias
11096 sta VD7 ; save digit value
11097 ldd VD3 ; get accumulated value
11098 bsr SF5FD ; multiply by 10
11099 addb VD7 ; add digit value
11100 adca #0 ; propagate carry
11101 std VD3 ; save accumulated count value
11102 lda HRMODE ; get graphics mode
11103 cmpa #2 ; is it a 640 mode?
11104 bgt SF5DA ; brif so
11105 ldd #319 ; get max for 320 mode
11106 bra SF5DD
11107 SF5DA ldd #639 ; get max for 640 mode
11108 SF5DD cmpd VD3 ; is the value in range for a horizontal coordinate?
11109 lblt LB44A ; brif not
11110 ldd VD3 ; get accumulated value
11111 tst VD8 ; is there anything more to parse?
11112 beq SF5FA ; brif not
11113 jsr SF591 ; get a character
11114 jsr SF608 ; set C if not digit
11115 bcc SF5C1 ; brif digit - add to accumulated value
11116 SF5F2 inc VD8 ; account for character being unfetched
11117 ldx VD9 ; move command pointer back
11118 leax -1,x
11119 stx VD9
11120 SF5FA ldd VD3 ; get accumulated value
11121 rts
11122 SF5FD aslb ; times 2
11123 rola
11124 pshs d ; save 2D
11125 aslb ; times 4
11126 rola
11127 aslb ; times 8
11128 rola
11129 addd ,s++ ; 8D+2D=10D
11130 rts
11131 SF608 cmpa #'0 ; is it less than ASCII 0?
11132 blo SF610 ; brif so - sets C
11133 suba #'9+1 ; set C if > ASCII 9
11134 suba #-('9+1)
11135 SF610 rts
11136 SF611 ldx VD9 ; get command pointer
11137 pshs x ; save it
11138 jsr SF591 ; get command character
11139 jsr LB3A2 ; set C if not alpha
11140 lbcs LB44A ; brif not variable name
11141 SF61F jsr SF591 ; get command character
11142 cmpa #'; ; is it end of variable string?
11143 bne SF61F ; brif not
11144 puls x ; get back start of variable
11145 ldu CHARAD ; save interpreter input pointer
11146 pshs u
11147 stx CHARAD ; save command string pointer as interpeter input
11148 jsr LB284 ; evaluate variable
11149 puls x ; restore interpreter input pointer
11150 stx CHARAD
11151 rts
11152 ; WIDTH command
11153 WIDTH clr HRMODE ; turn off graphics
11154 lbrn 0
11155 cmpa #0 ; end of line? (BUG: should do a BEQ before the CLR above)
11156 beq SF64F ; brif so - raise error if no argument (won't trigger on :)
11157 jsr EVALEXPB ; evaluate width argument
11158 cmpb #32 ; 32 columns?
11159 beq COL32 ; brif so
11160 cmpb #40 ; 40 columns?
11161 beq COL40 ; brif so
11162 cmpb #80 ; 80 columns?
11163 beq COL80 ; brif so
11164 SF64F jmp LB44A ; raise FC error
11165 COL32 clra ; set text mode to 32 columns
11166 sta HRWIDTH
11167 jsr LA928 ; clear screen
11168 lbsr SETTEXT ; set up display for 32 column screen
11169 rts
11170 COL40 lda #1 ; mode number for 40 columns
11171 sta HRWIDTH ; set text screen mode
11172 lbsr SF772 ; map text screen
11173 lda #40 ; set up scren size in character cells
11174 ldb #ROWMAX
11175 std H.COLUMN
11176 ldd #HRESSCRN+40*ROWMAX*2 ; set end address of screen
11177 SF66D std H.DISPEN ; save end address
11178 bsr SF68C ; clear the screen
11179 lbsr SF778 ; unmap text screen
11180 lbsr SETTEXT ; set up display for the text screen
11181 rts
11182 COL80 lda #2 ; mode number for 80 columns
11183 sta HRWIDTH ; set text screen mode
11184 lbsr SF772 ; map the screen
11185 lda #80 ; set up screen size in character cells
11186 ldb #ROWMAX
11187 std H.COLUMN
11188 ldd #HRESSCRN+80*ROWMAX*2 ; set end address of screen
11189 bra SF66D ; set up rest of parameters
11190 SF68C ldx #HRESSCRN ; set cursor address to top left corner
11191 lbrn 0
11192 stx H.CRSLOC
11193 lda #0x20 ; use space to clear screen
11194 ldb H.CRSATT ; get current attributes
11195 SF69B std ,x++ ; blank a character cell
11196 cmpx H.DISPEN ; end of screen?
11197 blo SF69B ; brif not
11198 ldx #HRESSCRN ; reset to top of screen
11199 clra ; reset cursor coordinates to 0,0
11200 sta H.CURSX
11201 sta H.CURSY
11202 rts
11203 ; CLS patch entered from the other patch in the ECB area
11204 ALINK23 puls cc ; restore zero flag
11205 lbrn 0
11206 beq SF6E0 ; brif no arguments
11207 jsr EVALEXPB ; get colour number
11208 tstb ; 0?
11209 beq SF6E0 ; brif so - treat as no arguments
11210 cmpb #8 ; valid colour?
11211 bhi SF6E7 ; brif not - do the easter egg or the other easter egg
11212 decb ; zero-base the colour
11213 leay IM.PALET,pcr ; point to current palette settings
11214 lda b,y ; get the real colour
11215 sta V.BORDER ; set border colour
11216 lbsr SF766 ; set border colour in GIME initializers
11217 stb H.CRSATT ; set attributes to foreground 0, background as selected, no blink or underline
11218 lda #0x20 ; get space character
11219 lbsr SF772 ; map screen
11220 ldx #HRESSCRN ; get address of start of screen
11221 stx H.CRSLOC ; put cursor there
11222 bsr SF69B ; clear screen
11223 SF6DC lbsr SF778 ; unmap screen
11224 rts
11225 SF6E0 lbsr SF772 ; map screen
11226 bsr SF68C ; clear screen
11227 bra SF6DC ; ummap screen and return
11228 SF6E7 clr H.CRSATT ; reset attributes to colours 0,0, no blink or underline
11229 lda IM.PALET ; get colour in register 0
11230 sta V.BORDER ; set border colour
11231 bsr SF766 ; reset border colour in GIME initializers
11232 cmpb #100 ; is it CLS 100?
11233 SF6F4 beq SF730 ; brif so - do the easter egg
11234 bsr SF772 ; map the screen
11235 bsr SF68C ; clear screen
11236 bsr SF778 ; unmap screen
11237 ldx #MICROMS-1 ; point to Microware commercial
11238 jmp STRINOUT ; display it
11239 MICROMS fcc 'Microware Systems Corp.'
11240 fcb 0x0d,0x00
11241 AUTHORMS fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; the ROM/RAM copy sets this to the actual easter egg text
11242 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
11243 fcb 0x00,0x00,0x00,0x00,0x00
11244 SF730 bsr SF772 ; map the screen
11245 lbsr SF68C ; clear it
11246 bsr SF778 ; unmap the screen
11247 ldx #AUTHORMS-1 ; point to the easter egg
11248 jsr STRINOUT ; display it
11249 pshs x ; save X for some reason
11250 leax >SF6F4,pcr ; point to start of easter egg code
11251 lda #0x12 ; NOP opcode
11252 sta ,x+ ; blank out the branch that brings us here
11253 sta ,x
11254 leax >AUTHORMS,pcr ; point to author message
11255 SF74D sta ,x+ ; blank out character in string or this code
11256 cmpx #SF74D ; end of string or display code?
11257 blo SF74D ; brif not
11258 puls x ; restore X
11259 rts
11260 ; Line input routine patch for handling CLEAR
11261 ALINK27 tst HRWIDTH ; is it 40/80 column screen?
11262 bne SF761 ; brif so
11263 jsr LA928 ; clear 32 column screen
11264 SF75E jmp LA390 ; go make to mainline
11265 SF761 lbsr SF6E0 ; clear the screen
11266 bra SF75E ; return to mainline
11267 SF766 pshs y ; save register
11268 leay SE03B,pcr ; point to text initializers
11269 sta 3,y ; set border in 40 column initializer
11270 sta 12,y ; set border in 80 column initializer
11271 puls y,pc ; restore registers and return
11272 SF772 orcc #0x50 ; clobber interrupts
11273 lbsr SELTEXT ; map the text screen (by setting *all 16* MMU registers)
11274 rts
11275 SF778 lbsr SETMMU ; unmap text screen (by setting *all 16* MMU registers)
11276 andcc #0xaf ; restart interrupts
11277 rts
11278 ; The driver for putting characters on the 40 and 80 column screen is here, modulo the WIDTH command and clear
11279 ; screen routines above.
11280 ;
11281 ; There are several major problems with this driver:
11282 ;
11283 ; * Cursor handling is overly complicated. Instead of doing what Color Basic does and only show the cursor
11284 ; when waiting for input in the generic input routine, this driver displays it almost all of the time and, thus,
11285 ; has all manner of code for managing the cursor that would not be needed otherwise.
11286 ; * The system goes out of its way to set up the screen height and width values. Then, it doesn't bother using
11287 ; them consistently, especially during the screen scrolling routine. Indeed, the screen scrolling routine could
11288 ; be made completely general purpose by using two pointers, say U for the destination and X for the source. Then
11289 ; the column count could be used to decide the line width (to calculate the offset betwen U and X) and then the
11290 ; row count could be used to set the row number after the scrolling is done. This would remove any hard coded
11291 ; offsets or screen size assumptions.
11292 ; * The routines for mapping and unmapping the text screen are inexcusably slow. Only one MMU register needs to
11293 ; be changed in either routine. However, instead of doing that, the routines use an inefficient routine that
11294 ; sets *all 16* MMU registers (both tasks!). This reduces screen output speed so much that a fast reader can
11295 ; actually keep up with the output going full speed. Simply replacing these two routines with simpler ones that
11296 ; do not do that dumbassery gets performance on par with the 32 column VDG screen.
11297 ;
11298 ; Along with the above, some of the code is far more convoluted than it needs to be, but that is relatively
11299 ; benign compared to everything else.
11300 ;
11301 ; Blink cursor patch
11302 ALINK24 bsr SF787 ; blink the cursor
11303 jsr KEYIN ; get keypress
11304 beq ALINK24 ; brif no key pressed
11305 puls b,x,pc ; return to caller
11306 SF787 dec BLKCNT ; time to blink cursor?
11307 bne SF7A8 ; brif not
11308 ldb #11 ; reset blink counter
11309 stb BLKCNT
11310 bsr SF772 ; map screen
11311 ldx H.CRSLOC ; get cursor pointer
11312 lda 1,x ; get current attributes
11313 bita #0x40 ; is underline on?
11314 beq SF79F ; brif not - enable it
11315 lda H.CRSATT ; use current attributes if it is
11316 bra SF7A4
11317 SF79F lda H.CRSATT ; get current attributes
11318 ora #0x40 ; turn on underline
11319 SF7A4 sta 1,x ; save new attributes
11320 bsr SF778 ; unmap screen
11321 SF7A8 ldx #DEBDEL ; do a delay
11322 jmp LA7D3
11323 ; Put character on screen patch
11324 ALINK22 bsr SF772 ; map the screen
11325 lbrn 0
11326 ldx H.CRSLOC ; get cursor location
11327 cmpa #0x08 ; backspace?
11328 bne SF7C4 ; brif not
11329 cmpx #HRESSCRN ; at start of screen?
11330 beq SF7DE ; brif so - do nothing
11331 bsr SF7E2 ; do a backspace
11332 bra SF7DE ; finish up
11333 SF7C4 cmpa #0x0d ; carriage return?
11334 bne SF7CC ; brif not
11335 bsr SF827 ; do a carriage return
11336 bra SF7D7 ; finish up with scroll check
11337 SF7CC cmpa #0x20 ; is it a control code?
11338 blo SF7DE ; brif so - do nothing
11339 ldb H.CRSATT ; get current attributes
11340 std ,x ; put character on screen
11341 bsr SF807 ; move cursor forward
11342 SF7D7 cmpx H.DISPEN ; end of screen?
11343 blo SF7DE ; brif not
11344 bsr SF854 ; scroll screen
11345 SF7DE bsr SF778 ; unmap the screen
11346 puls a,b,x,pc ; restore registers and return
11347 SF7E2 pshs b,a ; save registers
11348 lda #0x20 ; space character
11349 ldb H.CRSATT ; get attributes
11350 std ,x ; turns off cursor at this position and blanks it
11351 orb #0x40 ; turn on underline (we'll put a cursor in the previous position)
11352 std -2,x ; put blank and cursor back one
11353 leax -2,x ; move pointer back
11354 stx H.CRSLOC ; save new cursor pointer
11355 ldd H.CURSX ; get coordinates
11356 deca ; move horizontal back
11357 bpl SF802 ; brif we didn't wrap
11358 decb ; move vertical back
11359 stb H.CURSY ; save it
11360 lda H.COLUMN ; get screen width
11361 deca ; coordinates are zero-based so now we have the max horizontal coord
11362 SF802 sta H.CURSX ; save new horizontal position
11363 puls a,b,pc ; restore registers and return
11364 SF807 pshs a,b ; save registers
11365 lda #0x20 ; we'll blank a character for the cursor
11366 ldb H.CRSATT ; get attributes
11367 orb #0x40 ; force underline for cursor
11368 leax 2,x ; move pointer forward
11369 std ,x ; put blank and cursor on screen
11370 stx H.CRSLOC ; save new cursor position
11371 ldd H.CURSX ; get coordinates
11372 inca ; move right
11373 cmpa H.COLUMN ; did we hit the edge?
11374 blo SF802 ; brif not - save new horizontal coordinate and return
11375 incb ; bump line
11376 stb H.CURSY ; save new line
11377 clra ; reset to left side of screen
11378 bra SF802 ; save new horizontal coordinate and return
11379 SF827 pshs a,b ; save registers
11380 lda #0x20 ; get space character
11381 ldb H.CRSATT ; get attributes
11382 SF82E std ,x++ ; blank a character
11383 pshs a ; save character
11384 lda H.CURSX ; get horizontal position
11385 inca ; bump it
11386 sta H.CURSX ; save new position
11387 cmpa H.COLUMN ; edge of screen?
11388 puls a ; restore character
11389 blo SF82E ; brif not end of line yet
11390 stx H.CRSLOC ; save cursor location
11391 clr H.CURSX ; reset to left edge
11392 inc H.CURSY ; bump row
11393 lda #0x20 ; space character
11394 ldb H.CRSATT ; get attributes
11395 orb #0x40 ; turn on underline
11396 std ,x ; put a cursor on screen
11397 puls a,b,pc ; restore registers and return
11398 SF854 pshs a,b ; save registers
11399 ldx #HRESSCRN ; point to start of screen
11400 lda H.COLUMN ; get screen width
11401 cmpa #40 ; is it 40 columns?
11402 bne SF86E ; brif not - do 80 column scroll
11403 SF860 ldd 2*40,x ; get character cell from one line down
11404 std ,x++ ; move it here
11405 cmpx #HRESSCRN+(ROWMAX-1)*40*2 ; at start of last row?
11406 blo SF860 ; brif not
11407 SF86A bsr SF87B ; fill last row with spaces
11408 puls a,b,pc ; restore registers and return
11409 SF86E ldd 80*2,x ; get a character cell from next row
11410 std ,x++ ; put it here
11411 cmpx #HRESSCRN+(ROWMAX-1)*80*2 ; at start of last row?
11412 blo SF86E ; brif not
11413 bra SF86A ; blank out last row and finish up
11414 SF87B clr H.CURSX ; reset column to 0
11415 lda #ROWMAX-1 ; reset row number to bottom of screen
11416 sta H.CURSY
11417 lda #0x20 ; get space character
11418 ldb H.CRSATT ; get attributes
11419 pshs x ; save pointer to start of row
11420 SF88A std ,x++ ; blank a character
11421 cmpx H.DISPEN ; at end of screen?
11422 bne SF88A ; brif not
11423 clr H.CURSX ; reset horizontal position to margin
11424 puls x ; get start of line pointer
11425 lda #0x20 ; space haracter
11426 ldb H.CRSATT ; get attributes
11427 orb #0x40 ; turn on underline
11428 std ,x ; put a bleeping cursor at start of line
11429 stx H.CRSLOC ; set cursor position
11430 rts
11431 ; Conditional newline patch. Note that this maps and unmaps the text screen in 40/80 column mode
11432 ; but that is completely unneeded to just test the X coordinate.
11433 ALINK26 tst DEVNUM ; is it screen?
11434 bne SF8AB ; brif not
11435 tst HRWIDTH ; VDG screen?
11436 bne SF8B1 ; brif not
11437 SF8AB jsr LA35F ; set up print parameters
11438 jmp LB95F ; re-enter mainline code
11439 SF8B1 lbsr SF772 ; map screen
11440 tst H.CURSX ; at left margin?
11441 pshs cc ; save Z flag
11442 lbsr SF778 ; unmap screen
11443 puls cc ; get back Z flag
11444 lbne LB958 ; brif not at left margine - do CR
11445 rts
11446 ; PRINT @ patch
11447 ALINK25 tst HRWIDTH ; VDG screen?
11448 bne SF8CD ; brif not - raise error
11449 jsr LA554 ; move cursor to specified position
11450 jmp LB905 ; return to mainline code
11451 SF8CD ldb #39*2 ; code for HP error
11452 jmp LAC46 ; raise error
11453 ; LOCATE command
11454 ; The parameter checking here could simply use the H.COLUMN and H.ROW variables and it would
11455 ; be loads simpler. Also, if the dumbassery with the cursor wasn't a thing, this routine wouldn't
11456 ; need to mess with mapping the screen or screwing around with the cursor.
11457 LOCATE ldb HRWIDTH ; is it 40/80 column screen?
11458 lbrn 0
11459 beq SF8CD ; brif not - raise error
11460 pshs b ; save screen mode
11461 jsr SE7B2 ; evaluate coordinates
11462 lda BINVAL+1 ; get X coordinate
11463 puls b ; get back screen mode
11464 cmpb #1 ; is it 40 column screen?
11465 bne SF8EB ; brif not
11466 cmpa #40 ; in range for 40 columns?
11467 bra SF8ED
11468 SF8EB cmpa #80 ; in range for 80 columns?
11469 SF8ED lbhs LB44A ; brif not - raise error
11470 ldb VERBEG+1 ; get Y coordinate
11471 cmpb #ROWMAX ; is it in range?
11472 bhs SF8ED ; brif not - raise error
11473 pshs d ; save new coordinates
11474 lbsr SF772 ; map screen
11475 std H.CURSX ; set screen coordinates
11476 ldx H.CRSLOC ; get pointer to old position
11477 lda H.CRSATT ; replace attributes with current ones
11478 sta 1,x
11479 lda H.COLUMN ; get number of columns (why not use this above?)
11480 asla ; two bytes per character cell
11481 mul ; now D is offset to start of row
11482 ldx #HRESSCRN ; get start of screen
11483 leax d,x ; now X points to the start of the line
11484 puls a,b ; get back column and row numbers
11485 asla ; two bytes per character cell
11486 tfr a,b ; need this in B since we'll overflow singed 8 bits
11487 abx ; offset to correct cursor position
11488 lda H.CRSATT ; get attributes
11489 ora #0x40 ; enable underline
11490 sta 1,x ; enable cursor
11491 stx H.CRSLOC ; save new cursor pointer
11492 lbsr SF778 ; unmap screen
11493 rts
11494 ; HSTAT command
11495 HSTAT tst HRWIDTH ; is it 40/80 column screen?
11496 lbrn 0
11497 beq SF8CD ; brif not - raise error
11498 lbsr SF772 ; map the screen
11499 ldx H.CRSLOC ; get cursor pointer
11500 ldd ,x ; get character and attributes
11501 std VCB ; save them
11502 ldd H.CURSX ; get screen coordinates
11503 std VCD ; save them
11504 lbsr SF778 ; unmap screen
11505 jsr LB357 ; evaluate variable for character
11506 stx VARDES ; saveit
11507 jsr SYNCOMMA ; insist on a comma
11508 ldb #1 ; make a single character string
11509 jsr LB56D
11510 lda VCB ; get character on screen
11511 jsr LB511 ; get string details
11512 sta ,x ; save character in string
11513 jsr LB54C ; put string on string stack
11514 ldx VARDES ; point to variable descriptor
11515 tst -1,x ; is it a string? (should have checked after evaluating instead)
11516 lbpl LB151 ; do type mismatch if number
11517 ldy FPA0+2 ; point to destination string descriptor
11518 ldb #5 ; copy 5 bytes from newly created string into variable
11519 SF963 lda ,y+ ; copy byte
11520 sta ,x+
11521 decb ; done all?
11522 bne SF963 ; brif not
11523 LDX TEMPPT ; point to new string descriptor
11524 leax -5,x ; BUG: should just call LB675 to remove string from string stack
11525 stx TEMPPT
11526 jsr LB357 ; evaluate a variable (for X coord)
11527 stx VARDES ; save pointer to it
11528 jsr SYNCOMMA ; insist on a comma after it
11529 clra ; zero extend attributes
11530 ldb VCB+1 ; get attribute byte
11531 jsr GIVABF ; convert to float
11532 ldx VARDES ; point to variable
11533 tst -1,x ; test if numeric (should have tested VALTYP above)
11534 lbmi LB151 ; TM error if not number
11535 jsr LBC35 ; pack FPA0 to variable
11536 jsr LB357 ; evaluate another variable
11537 stx VARDES ; save it
11538 jsr SYNCOMMA ; insist on a comma
11539 clra ; zero extend the X coordinate
11540 ldb VCD ; get X coordinate
11541 jsr GIVABF ; turn into a FP number
11542 ldx VARDES ; get variable
11543 tst -1,x ; is it a number (should have tested VALTYP above)
11544 LBMI LB151 ; brif not - TM error
11545 jsr LBC35 ; pack FPA0 to variable
11546 jsr LB357 ; evaluate another variable
11547 stx VARDES ; save it
11548 clra ; zero extend Y coordinate
11549 ldb VCD+1 ; get Y coordinate
11550 jsr GIVABF ; turn into a FP number
11551 ldx VARDES ; get variable descriptor back
11552 tst -1,x ; is it a number (should have tested VALTYP above)
11553 lbmi LB151 ; brif not - TM error
11554 jsr LBC35 ; pack FPA0 to variable
11555 rts
11556 ; ATTR command
11557 ATTR jsr EVALEXPB ; evaluate foreground colour
11558 lbrn 0
11559 cmpb #8 ; there are 8 valid colours (0-7)
11560 lbhs LB44A ; brif out of range - raise error
11561 aslb ; shift over to bits 5,4,3
11562 aslb
11563 aslb
11564 pshs b ; save partial attribute byte
11565 jsr GETCCH ; fetch current character (useless call)
11566 jsr SYNCOMMA ; insist on comma
11567 jsr EVALEXPB ; evaluate background colour
11568 cmpb #8 ; is it valid (0-7)?
11569 lbhs LB44A ; brif not - raise error
11570 orb ,s ; merge with partial attribute byte
11571 leas 1,s ; clean up stack (could use ,s+ above)
11572 andb #0x3f ; make sure we have zeros in bit 7,6 - unneeded
11573 pshs b ; save colour attributes
11574 jsr GETCCH ; is there mode?
11575 SF9E3 beq SFA06 ; brif no more flags
11576 jsr SYNCOMMA ; insist on a comma
11577 cmpa #'B ; B (blink)?
11578 bne SF9F6 ; brif not
11579 puls b ; set blink bit in accumulated attributes
11580 orb #0x80
11581 pshs b
11582 jsr GETNCH ; eat the flag
11583 bra SF9E3 ; look for another flag
11584 SF9F6 cmpa #'U ; U (underline)?
11585 lbne LB44A ; invalid flag - raise error
11586 puls b ; get accumulated attributes and set underline bit
11587 orb #0x40
11588 pshs b
11589 jsr GETNCH ; eat the flag
11590 bra SF9E3 ; look for another flag
11591 SFA06 puls b ; get new attributes
11592 stb H.CRSATT ; set them as default
11593 rts
11594 fcb 0x00,0x00,0x00,0x00 ; unused bytes
11595 ; These are extra glyphs that should be part of the HPRINT font but aren't.
11596 fcb 0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x10 ; Ç
11597 fcb 0x44,0x00,0x44,0x44,0x44,0x4C,0x34,0x00 ; ü
11598 fcb 0x08,0x10,0x38,0x44,0x7C,0x40,0x38,0x00 ; é
11599 fcb 0x10,0x28,0x38,0x04,0x3C,0x44,0x3C,0x00 ; â
11600 fcb 0x28,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00 ; ä
11601 fcb 0x20,0x10,0x38,0x04,0x3C,0x44,0x3C,0x00 ; à
11602 fcb 0x10,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00 ; ȧ (or å maybe?)
11603 fcb 0x00,0x00,0x38,0x44,0x40,0x44,0x38,0x10 ; ç
11604 fcb 0x10,0x28,0x38,0x44,0x7C,0x40,0x38,0x00 ; ê
11605 fcb 0x28,0x00,0x38,0x44,0x7C,0x40,0x38,0x00 ; ë
11606 fcb 0x20,0x10,0x38,0x44,0x7C,0x40,0x38,0x00 ; è
11607 fcb 0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00 ; ï
11608 fcb 0x10,0x28,0x00,0x30,0x10,0x10,0x38,0x00 ; î
11609 fcb 0x00,0x18,0x24,0x38,0x24,0x24,0x38,0x40 ; ẞ
11610 fcb 0x44,0x10,0x28,0x44,0x7C,0x44,0x44,0x00 ; Ä
11611 fcb 0x10,0x10,0x28,0x44,0x7C,0x44,0x44,0x00 ; Ȧ (or Å maybe?)
11612 fcb 0x08,0x10,0x38,0x44,0x44,0x44,0x38,0x00 ; ó
11613 fcb 0x00,0x00,0x68,0x14,0x3C,0x50,0x3C,0x00 ; æ
11614 fcb 0x3C,0x50,0x50,0x78,0x50,0x50,0x5C,0x00 ; Æ
11615 fcb 0x10,0x28,0x38,0x44,0x44,0x44,0x38,0x00 ; ô
11616 fcb 0x28,0x00,0x38,0x44,0x44,0x44,0x38,0x00 ; ö
11617 fcb 0x00,0x00,0x38,0x4C,0x54,0x64,0x38,0x00 ; ø
11618 fcb 0x10,0x28,0x00,0x44,0x44,0x4C,0x34,0x00 ; û
11619 fcb 0x20,0x10,0x44,0x44,0x44,0x4C,0x34,0x00 ; ù
11620 fcb 0x38,0x4C,0x54,0x54,0x54,0x64,0x38,0x00 ; Ø
11621 fcb 0x44,0x38,0x44,0x44,0x44,0x44,0x38,0x00 ; Ö
11622 fcb 0x28,0x44,0x44,0x44,0x44,0x44,0x38,0x00 ; Ü
11623 fcb 0x38,0x40,0x38,0x44,0x38,0x04,0x38,0x00 ; §
11624 fcb 0x08,0x14,0x10,0x38,0x10,0x50,0x3C,0x00 ; £
11625 fcb 0x10,0x10,0x7C,0x10,0x10,0x00,0x7C,0x00 ; ±
11626 fcb 0x10,0x28,0x10,0x00,0x00,0x00,0x00,0x00 ; °
11627 fcb 0x08,0x14,0x10,0x38,0x10,0x10,0x20,0x40 ; ſ (long s)
11628 ; These are some extra symbol glyphs
11629 fcb 0x00,0x10,0x18,0x1C,0x1C,0x18,0x10,0x00 ; solid right pointing triangle
11630 fcb 0x00,0x08,0x18,0x38,0x38,0x18,0x08,0x00 ; solid left pointing triangle
11631 fcb 0x00,0x00,0x00,0x7E,0x3C,0x18,0x00,0x00 ; solid down pointing triangle
11632 fcb 0x00,0x00,0x18,0x3C,0x7E,0x00,0x00,0x00 ; solid up pointing triangle
11633 fcb 0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00 ; three horizontal lines with middle one double thick
11634 fcb 0x00,0x00,0x30,0x3C,0x14,0x1C,0x00,0x00 ; solid square on top left of open square
11635 fcb 0x00,0x7E,0x42,0x5A,0x5A,0x42,0x7E,0x00 ; solid box inside larger box
11636 fcb 0x00,0x7E,0x7E,0x00,0x00,0x7E,0x7E,0x00 ; thick equals sign
11637 fcb 0x00,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x00 ; solid vertical rectangle
11638 fcb 0x00,0x00,0x7E,0x7E,0x7E,0x7E,0x00,0x00 ; solid horizontal rectangle
11639 fcb 0x00,0x7E,0x24,0x18,0x18,0x24,0x7E,0x00 ; hour glass
11640 fcb 0x00,0x7F,0x00,0x7F,0x7F,0x00,0x7F,0x00 ; left end three horizontal lines with middle one double thick
11641 fcb 0x00,0xFE,0x00,0xFE,0xFE,0x00,0xFE,0x00 ; right end three horizontal lines with middle one double thick
11642 ; The above 45 glyphs are duplicated below
11643 fcb 0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x10
11644 fcb 0x44,0x00,0x44,0x44,0x44,0x4C,0x34,0x00
11645 fcb 0x08,0x10,0x38,0x44,0x7C,0x40,0x38,0x00
11646 fcb 0x10,0x28,0x38,0x04,0x3C,0x44,0x3C,0x00
11647 fcb 0x28,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00
11648 fcb 0x20,0x10,0x38,0x04,0x3C,0x44,0x3C,0x00
11649 fcb 0x10,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00
11650 fcb 0x00,0x00,0x38,0x44,0x40,0x44,0x38,0x10
11651 fcb 0x10,0x28,0x38,0x44,0x7C,0x40,0x38,0x00
11652 fcb 0x28,0x00,0x38,0x44,0x7C,0x40,0x38,0x00
11653 fcb 0x20,0x10,0x38,0x44,0x7C,0x40,0x38,0x00
11654 fcb 0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00
11655 fcb 0x10,0x28,0x00,0x30,0x10,0x10,0x38,0x00
11656 fcb 0x00,0x18,0x24,0x38,0x24,0x24,0x38,0x40
11657 fcb 0x44,0x10,0x28,0x44,0x7C,0x44,0x44,0x00
11658 fcb 0x10,0x10,0x28,0x44,0x7C,0x44,0x44,0x00
11659 fcb 0x08,0x10,0x38,0x44,0x44,0x44,0x38,0x00
11660 fcb 0x00,0x00,0x68,0x14,0x3C,0x50,0x3C,0x00
11661 fcb 0x3C,0x50,0x50,0x78,0x50,0x50,0x5C,0x00
11662 fcb 0x10,0x28,0x38,0x44,0x44,0x44,0x38,0x00
11663 fcb 0x28,0x00,0x38,0x44,0x44,0x44,0x38,0x00
11664 fcb 0x00,0x00,0x38,0x4C,0x54,0x64,0x38,0x00
11665 fcb 0x10,0x28,0x00,0x44,0x44,0x4C,0x34,0x00
11666 fcb 0x20,0x10,0x44,0x44,0x44,0x4C,0x34,0x00
11667 fcb 0x38,0x4C,0x54,0x54,0x54,0x64,0x38,0x00
11668 fcb 0x44,0x38,0x44,0x44,0x44,0x44,0x38,0x00
11669 fcb 0x28,0x44,0x44,0x44,0x44,0x44,0x38,0x00
11670 fcb 0x38,0x40,0x38,0x44,0x38,0x04,0x38,0x00
11671 fcb 0x08,0x14,0x10,0x38,0x10,0x50,0x3C,0x00
11672 fcb 0x10,0x10,0x7C,0x10,0x10,0x00,0x7C,0x00
11673 fcb 0x10,0x28,0x10,0x00,0x00,0x00,0x00,0x00
11674 fcb 0x08,0x14,0x10,0x38,0x10,0x10,0x20,0x40
11675 fcb 0x00,0x10,0x18,0x1C,0x1C,0x18,0x10,0x00
11676 fcb 0x00,0x08,0x18,0x38,0x38,0x18,0x08,0x00
11677 fcb 0x00,0x00,0x00,0x7E,0x3C,0x18,0x00,0x00
11678 fcb 0x00,0x00,0x18,0x3C,0x7E,0x00,0x00,0x00
11679 fcb 0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00
11680 fcb 0x00,0x00,0x30,0x3C,0x14,0x1C,0x00,0x00
11681 fcb 0x00,0x7E,0x42,0x5A,0x5A,0x42,0x7E,0x00
11682 fcb 0x00,0x7E,0x7E,0x00,0x00,0x7E,0x7E,0x00
11683 fcb 0x00,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x00
11684 fcb 0x00,0x00,0x7E,0x7E,0x7E,0x7E,0x00,0x00
11685 fcb 0x00,0x7E,0x24,0x18,0x18,0x24,0x7E,0x00
11686 fcb 0x00,0x7F,0x00,0x7F,0x7F,0x00,0x7F,0x00
11687 fcb 0x00,0xFE,0x00,0xFE,0xFE,0x00,0xFE,0x00
11688 ; The glyphs above repeat one more time here but the set is incomplete
11689 fcb 0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x10
11690 fcb 0x44,0x00,0x44,0x44,0x44,0x4C,0x34,0x00
11691 fcb 0x08,0x10,0x38,0x44,0x7C,0x40,0x38,0x00
11692 fcb 0x10,0x28,0x38,0x04,0x3C,0x44,0x3C,0x00
11693 fcb 0x28,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00
11694 fcb 0x20,0x10,0x38,0x04,0x3C,0x44,0x3C,0x00
11695 fcb 0x10,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00
11696 fcb 0x00,0x00,0x38,0x44,0x40,0x44,0x38,0x10
11697 fcb 0x10,0x28,0x38,0x44,0x7C,0x40,0x38,0x00
11698 fcb 0x28,0x00,0x38,0x44,0x7C,0x40,0x38,0x00
11699 fcb 0x20,0x10,0x38,0x44,0x7C,0x40,0x38,0x00
11700 fcb 0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00
11701 fcb 0x10,0x28,0x00,0x30,0x10,0x10,0x38,0x00
11702 fcb 0x00,0x18,0x24,0x38,0x24,0x24,0x38,0x40
11703 fcb 0x44,0x10,0x28,0x44,0x7C,0x44,0x44,0x00
11704 fcb 0x10,0x10,0x28,0x44,0x7C,0x44,0x44,0x00
11705 fcb 0x08,0x10,0x38,0x44,0x44,0x44,0x38,0x00
11706 fcb 0x00,0x00,0x68,0x14,0x3C,0x50,0x3C,0x00
11707 fcb 0x3C,0x50,0x50,0x78,0x50,0x50,0x5C,0x00
11708 fcb 0x10,0x28,0x38,0x44,0x44,0x44,0x38,0x00
11709 fcb 0x28,0x00,0x38,0x44,0x44,0x44,0x38,0x00
11710 fcb 0x00,0x00,0x38,0x4C,0x54,0x64,0x38,0x00
11711 fcb 0x10,0x28,0x00,0x44,0x44,0x4C,0x34,0x00
11712 fcb 0x20,0x10,0x44,0x44,0x44,0x4C,0x34,0x00
11713 fcb 0x38,0x4C,0x54,0x54,0x54,0x64,0x38,0x00
11714 fcb 0x44,0x38,0x44,0x44,0x44,0x44,0x38,0x00
11715 fcb 0x28,0x44,0x44,0x44,0x44,0x44,0x38,0x00
11716 fcb 0x38,0x40,0x38,0x44,0x38,0x04,0x38,0x00
11717 fcb 0x08,0x14,0x10,0x38,0x10,0x50,0x3C,0x00
11718 fcb 0x10,0x10,0x7C,0x10,0x10,0x00,0x7C,0x00
11719 fcb 0x10,0x28,0x10,0x00,0x00,0x00,0x00,0x00
11720 fcb 0x08,0x14,0x10,0x38,0x10,0x10,0x20,0x40
11721 fcb 0x00,0x10,0x18,0x1C,0x1C,0x18,0x10,0x00
11722 fcb 0x00,0x08,0x18,0x38,0x38,0x18,0x08,0x00 ; final duplicated glyph: left pointing solid triangle
11723 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; junk unused (or blank space)
11724 fcb 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ; junk unused (or solid block)
11725 ; This is where the constant page (FExx) would start. It's just garbage in the ROM.
11726 fill 0xff,8
11727 fill 0x00,8
11728 fill 0xff,8
11729 fill 0x00,8
11730 fill 0xff,8
11731 fill 0x00,8
11732 fill 0xff,8
11733 fill 0x00,8
11734 fill 0xff,8
11735 fill 0x00,8
11736 fill 0xff,8
11737 fill 0x00,8
11738 fill 0xff,8
11739 fill 0x00,8
11740 fill 0xff,8
11741 fill 0x00,8
11742 fill 0xff,8
11743 fill 0x00,8
11744 fill 0xff,8
11745 fill 0x00,8
11746 fill 0xff,8
11747 fill 0x00,8
11748 fill 0xff,8
11749 fill 0x00,8
11750 fill 0xff,8
11751 fill 0x00,8
11752 fill 0xff,8
11753 fill 0x00,8
11754 fill 0xff,8
11755 fill 0x00,8
11756 fill 0xff,8
11757 fill 0x00,8
11758 ; This is where the I/O page would start. It's just garbage in the ROM until the interrupt vectors.
11759 fill 0x00,8
11760 fill 0xff,8
11761 fill 0x00,8
11762 fill 0xff,8
11763 fill 0x00,8
11764 fill 0xff,8
11765 fill 0x00,8
11766 fill 0xff,8
11767 fill 0x00,8
11768 fill 0xff,8
11769 fill 0x00,8
11770 fill 0xff,8
11771 fill 0x00,8
11772 fill 0xff,8
11773 fill 0x00,8
11774 fill 0xff,8
11775 fill 0x00,8
11776 fill 0xff,8
11777 fill 0x00,8
11778 fill 0xff,8
11779 fill 0x00,8
11780 fill 0xff,8
11781 fill 0x00,8
11782 fill 0xff,8
11783 fill 0x00,8
11784 fill 0xff,8
11785 fill 0x00,8
11786 fill 0xff,8
11787 fill 0x00,8
11788 fill 0xff,8
11789 ; These are the actual CPU interrupt vectors
11790 fdb 0x0000 ; would be the 6309 illegal instruction trap
11791 fdb INT.SWI3 ; SWI3 bounce vector address
11792 fdb INT.SWI2 ; SWI2 bounce vector address
11793 fdb INT.FIRQ ; FIRQ bounce vector address
11794 fdb INT.IRQ ; IRQ bounce vector address
11795 fdb INT.SWI ; SWI bounce vector address
11796 fdb INT.NMI ; NMI bounce vector address
11797 fdb L8C1B ; this is where execution starts on RESET or power on