comparison disk.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 ; Various references to Color Basic and Extended Color Basic which are listed here to allow this ROM to be built independently.
4 XBWMST equ 0x80c0
5 L813C equ 0x813c
6 L8168 equ 0x8168
7 XVEC3 equ 0x8273
8 XVEC8 equ 0x8286
9 XVEC18 equ 0x829c
10 L8311 equ 0x8311
11 L8316 equ 0x8316
12 L836C equ 0x836c
13 L8748 equ 0x8748
14 L880E equ 0x880e
15 XVEC15 equ 0x8846
16 XVEC17 equ 0x88f0
17 L8955 equ 0x8955
18 L8C1B equ 0x8c1b
19 XVEC4 equ 0x8cf1
20 XVEC9 equ 0x8e90
21 L95AC equ 0x95ac
22 L962E equ 0x962e
23 L9650 equ 0x9650
24 L96CB equ 0x96cb
25 L96EC equ 0x96ec
26 L975F equ 0x975f
27 L9FB5 equ 0x9fb5
28 LA0E2 equ 0xa0e2
29 BAWMST equ 0xa0e8
30 LA171 equ 0xa171
31 LA176 equ 0xa176
32 PUTCHR equ 0xa282
33 LA35F equ 0xa35f
34 LA37C equ 0xa37c
35 LA3ED equ 0xa3ed
36 LA3FB equ 0xa3fb
37 LA406 equ 0xa406
38 LA426 equ 0xa426
39 LA429 equ 0xa429
40 LA42D equ 0xa42d
41 LA549 equ 0xa549
42 LA59A equ 0xa59a
43 LA5A2 equ 0xa5a2
44 LA5A5 equ 0xa5a5
45 LA5AE equ 0xa5ae
46 LA5C7 equ 0xa5c7
47 LA5DA equ 0xa5da
48 LA5E4 equ 0xa5e4
49 LA603 equ 0xa603
50 LA616 equ 0xa616
51 LA61C equ 0xa61c
52 LA61F equ 0xa61f
53 LA928 equ 0xa928
54 LA951 equ 0xa951
55 LA7D1 equ 0xa7d1
56 LA7E9 equ 0xa7e9
57 LA974 equ 0xa974
58 LAC37 equ 0xac37
59 LAC44 equ 0xac44
60 LAC46 equ 0xac46
61 LAC60 equ 0xac60
62 LAC73 equ 0xac73
63 LAC7C equ 0xac7c
64 LACEF equ 0xacef
65 LAD19 equ 0xad19
66 LAD21 equ 0xad21
67 LAD33 equ 0xad33
68 LAD9E equ 0xad9e
69 LADC6 equ 0xadc6
70 LADD4 equ 0xadd4
71 LADEB equ 0xadeb
72 LAE15 equ 0xae15
73 LAF9A equ 0xaf9a
74 LAFA4 equ 0xafa4
75 LAFB1 equ 0xafb1
76 LB00C equ 0xb00c
77 LB01E equ 0xb01e
78 LB069 equ 0xb069
79 LB143 equ 0xb143
80 LB146 equ 0xb146
81 LB148 equ 0xb148
82 LB156 equ 0xb156
83 LB244 equ 0xb244
84 LB262 equ 0xb262
85 LB166 equ 0xb166
86 SYNCOMMA equ 0xb26d
87 LB26F equ 0xb26f
88 LB277 equ 0xb277
89 LB2CE equ 0xb2ce
90 LB357 equ 0xb357
91 LB3E6 equ 0xb3e6
92 LB44A equ 0xb44a
93 LB4F3 equ 0xb4f3
94 GIVABF equ 0xb4f4
95 LB50F equ 0xb50f
96 LB516 equ 0xb516
97 LB654 equ 0xb654
98 LB657 equ 0xb657
99 LB659 equ 0xb659
100 LB69B equ 0xb69b
101 LB6A4 equ 0xb6a4
102 EVALEXPB equ 0xb70b
103 LB70E equ 0xb70e
104 LB738 equ 0xb738
105 LB73D equ 0xb73d
106 LIST equ 0xb764
107 LB958 equ 0xb958
108 LB95C equ 0xb95c
109 STRINOUT equ 0xb99c
110 LB99F equ 0xb99f
111 LB9A2 equ 0xb9a2
112 LB9AC equ 0xb9ac
113 LB9AF equ 0xb9af
114 LB9C5 equ 0xb9c5
115 LBB91 equ 0xbb91
116 LBC14 equ 0xbc14
117 LBC33 equ 0xbc33
118 LBC35 equ 0xbc35
119 LBC5F equ 0xbc5f
120 INT equ 0xbcee
121 LBDCC equ 0xbdcc
122 LBDD9 equ 0xbdd9
123 pragma noexpandcond
124 *pragma list
125 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
126 ; DISK EXTENDED COLOR BASIC
127 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
128 ifeq DISKVER
129 DHITOK equ 0xe0 ; highest command token
130 CYEAR equ '1 ; ones digit of copyright year
131 MINORVER equ '0
132 else
133 DHITOK equ 0xe1 ; highest command token
134 CYEAR equ '2 ; ones digit for copyright year
135 MINORVER equ '1
136 endc
137 org DOSBAS
138 fcc 'DK' ; magic number Extended Basic uses to identify the presence of a Disk ROM
139 LC002 bra LC00C ; entry point - jump around vector table
140 DCNVEC fdb DSKCON ; DSKCON indirect entry point
141 DSKVAR fdb DCOPC ; address of DSKCON parameter block
142 ifeq DISKVER-1
143 DSINIT fdb DOSINI ; vector to an initialization routine, the utility of which is unclear
144 DOSVEC fdb DOSCOM ; pointer to the actual location of the DOS command
145 endc
146 LC00C ldx #DBUF0 ; point to start of Disk Basic memory
147 LC00F clr ,x+ ; clear a byte
148 cmpx #DFLBUF ; at end of statically allocated Disk Basic memory?
149 bne LC00F ; brif not
150 ldx #LC109 ; point to initializer for the command interpretation table
151 ldu #COMVEC+20 ; point to command interpretation table location for Disk Basic
152 ldb #10 ; ten bytes in each table entry
153 jsr LA59A ; initialize interpretation table
154 ldd #LB277 ; syntax error address
155 std 3,u ; set command handler for "user" table to error
156 std 8,u ; set function handler for "user" table to error
157 clr ,u ; mark user table with 0 command keywords
158 clr 5,u ; mark user table with 0 function keywords
159 ldd #DXCVEC ; intercept Extended Basic's command handler
160 std COMVEC+13
161 ldd #DXIVEC ; intercept Extended Basic's function handler
162 std COMVEC+18
163 ldu #RVEC0 ; point to first RAM vector
164 LC03B lda #0x7e ; op code of JMP extended
165 sta RVEC22 ; set first byte of GET/PUT vector to JMP
166 sta ,u+ ; set this vector to be a JMP instruction
167 ldd ,x++ ; get vector destination
168 std ,u++ ; set the vector destination
169 cmpx #LC139 ; done the whole list?
170 bne LC03B ; brif not
171 ldx #DVEC22 ; install handler for GET/PUT vector
172 stx RVEC22+1
173 ifeq DISKVER-1
174 ldx #DVEC20 ; install replacement interpretation loop handler
175 stx RVEC20+1
176 endc
177 ldx #DUSRVC ; relocate USR vector table
178 stx USRADR
179 ldu #LB44A ; default USR address is illegal function call
180 ldb #10 ; there are 10 vectors
181 LC061 stu ,x++ ; set a vector
182 decb ; done all?
183 bne LC061 ; brif not
184 ldx #DNMISV ; install NMI handler
185 stx NMIVEC+1
186 lda #0x7e ; make it a JMP
187 sta NMIVEC
188 ldx #DIRQSV ; install IRQ handler (ECB and CB already made it a JMP)
189 stx IRQVEC+1
190 lda #19 ; initialze the number of changes needed to trigger a FAT write
191 sta WFATVL
192 clr FATBL0 ; mark all four FAT images as having no open files
193 clr FATBL1
194 clr FATBL2
195 clr FATBL3
196 ldx #DFLBUF ; point to the start of the disk "heap"
197 stx RNBFAD ; set start of random file buffers as the end of the allocated space
198 leax 0x100,x ; allocate 256 bytes for random file buffers by default
199 stx FCBADR ; save start of FCBs (and end of random file buffers)
200 leax 1,x ; leave an empty byte before FCBs (why?)
201 stx FCBV1 ; set address of FCB 1
202 clr <<FCBTYP,x ; mark it closed
203 leax FCBLEN,x ; set address of FCB 2 (2 user FCBs allocated at startup)
204 stx FCBV1+2
205 clr <<FCBTYP,x ; mark it closed
206 leax FCBLEN,x ; set address of FCB 3 (system FCB)
207 stx FCBV1+4
208 clr <<FCBTYP,x ; mark it closed
209 lda #2 ; set 2 active FCBs
210 sta FCBACT
211 leax FCBLEN,x ; point to end of active FCBs
212 tfr x,d ; put it in D so we can do stuff with it
213 tstb ; is it a partial memory page?
214 ifeq DISKVER
215 beq LC0C2 ; brif not
216 else
217 beq LC0BD ; brif not
218 endc
219 inca ; round up
220 ifeq DISKVER-1
221 LC0BD bita #1 ; is it even (multiple of 512)?
222 beq LC0C2 ; brif so
223 inca ; round up to even 512 byte boundary
224 endc
225 LC0C2 tfr a,b ; save start of graphics memory
226 addb #24 ; reserve 4 graphics pages
227 stb TXTTAB ; set start of program there
228 jsr L96EC ; do graphics initialization (A is the start of grahpics memory)
229 lda BEGGRP ; get start of current grahpics page
230 adda #6 ; make one page used
231 sta ENDGRP
232 ifeq DISKVER-1
233 jsr [DSINIT] ; do the pointless initialization routine
234 endc
235 bsr LC0F0 ; initialize FDC stuff and interrupt any action underway
236 andcc #0xaf ; enable interrupts
237 ldx #LC139-1 ; point to sign on message
238 jsr STRINOUT ; show sign on
239 ldx #DKWMST ; install warm start handler
240 stx RSTVEC
241 jmp LA0E2 ; jump into mainline Color Basic
242 DKWMST nop ; flag warm start routine as valid
243 bsr LC0F0 ; initialize FDC variables and interrupt any action underway
244 jsr LD2D2 ; close files and do some other stuff
245 jmp XBWMST ; transfer control to ECB's warm start
246 LC0F0 clr NMIFLG ; reset the NMI handler vector
247 clr RDYTMR ; disable the drive timeout counter
248 clr DRGRAM ; turn off all drive selects and motors (RAM copy)
249 clr DSKREG ; turn off all drive selects and motors (real hardware)
250 lda #0xd0 ; send "force interrupt" to controller
251 sta FDCREG
252 exg a,a ; wait for status to stabilize
253 exg a,a
254 lda FDCREG ; clear the status indicator (no error handling - nothing useful to do anyway)
255 rts
256 ifeq DISKVER
257 LC109 fcb 19 ; number of keywords (commands)
258 else
259 LC109 fcb 20 ; number of keywords (commands)
260 endc
261 fdb LC192 ; keyword table (commands)
262 fdb LC238 ; handler (commands)
263 fcb 6 ; number of keywords (functions)
264 fdb LC219 ; keyboard table (functions)
265 fdb LC24E ; handler (functions)
266 LC113 fdb DVEC0,DVEC1,DVEC2 ; RAM hook handler addresses
267 fdb DVEC3,DVEC4,DVEC5
268 fdb DVEC6,DVEC7,DVEC8
269 fdb XVEC9,DVEC10,DVEC11
270 fdb DVEC12,DVEC13,DVEC14
271 fdb DVEC15,DVEC12,DVEC17
272 fdb DVEC18
273 ; Sign on message
274 LC139 fcc 'DISK EXTENDED COLOR BASIC 1.'
275 fcb MINORVER
276 fcb 0x0d
277 fcc 'COPYRIGHT (C) 198'
278 fcb CYEAR
279 fcc ' BY TANDY'
280 fcb 0x0d
281 fcc 'UNDER LICENSE FROM MICROSOFT'
282 fcb 0x0d,0x0d,0x00
283 ; Keyword list (commands)
284 LC192 fcs 'DIR' ; 0xce
285 fcs 'DRIVE' ; 0xcf
286 fcs 'FIELD' ; 0xd0
287 fcs 'FILES' ; 0xd1
288 fcs 'KILL' ; 0xd2
289 fcs 'LOAD' ; 0xd3
290 fcs 'LSET' ; 0xd4
291 fcs 'MERGE' ; 0xd5
292 fcs 'RENAME' ; 0xd6
293 fcs 'RSET' ; 0xd7
294 fcs 'SAVE' ; 0xd8
295 fcs 'WRITE' ; 0xd9
296 fcs 'VERIFY' ; 0xda
297 fcs 'UNLOAD' ; 0xdb
298 fcs 'DSKINI' ; 0xdc
299 fcs 'BACKUP' ; 0xdd
300 fcs 'COPY' ; 0xde
301 fcs 'DSKI$' ; 0xdf
302 fcs 'DSKO$' ; 0xe0
303 ifeq DISKVER-1
304 fcs 'DOS' ; 0xe1
305 endc
306 ; Jump table (commands)
307 LC1F1 fdb DIR ; 0xce DIR
308 fdb DRIVE ; 0xcf DRIVE
309 fdb FIELD ; 0xd0 FIELD
310 fdb FILES ; 0xd1 FILES
311 fdb KILL ; 0xd2 KILL
312 fdb LOAD ; 0xd3 LOAD
313 fdb LSET ; 0xd4 LSET
314 fdb MERGE ; 0xd5 MERGE
315 fdb RENAME ; 0xd6 RENAME
316 fdb RSET ; 0xd7 RSET
317 fdb SAVE ; 0xd8 SAVE
318 fdb WRITE ; 0xd9 WRITE
319 fdb VERIFY ; 0xda VERIFY
320 fdb UNLOAD ; 0xdb UNLOAD
321 fdb DSKINI ; 0xdc DSKINI
322 fdb BACKUP ; 0xdd BACKUP
323 fdb COPY ; 0xde COPY
324 fdb DSKI ; 0xdf DSKI$
325 fdb DSKO ; 0xe0 DSKO$
326 ifeq DISKVER-1
327 fdb DOS ; 0xe1 DOS
328 endc
329 ; Keyword list (functions)
330 LC219 fcs 'CVN' ; 0xa2
331 fcs 'FREE' ; 0xa3
332 fcs 'LOC' ; 0xa4
333 fcs 'LOF' ; 0xa5
334 fcs 'MKN$' ; 0xa6
335 fcs 'AS' ; 0xa7 (here to avoid conflict with ASC)
336 ; Jump table (functions)
337 LC22C fdb CVN ; 0xa2 CVN
338 fdb FREE ; 0xa3 FREE
339 fdb LOC ; 0xa4 LOC
340 fdb LOF ; 0xa5 LOF
341 fdb MKN ; 0xa6 MKN$
342 fdb LB277 ; 0xa7 AS (not actually a function)
343 ; Command handler
344 LC238 cmpa #DHITOK ; is it a Disk Basic valid command?
345 bhi LC244 ; brif not
346 ldx #LC1F1 ; point to jump table
347 suba #0xce ; normalize Disk Basic tokens to 0
348 jmp LADD4 ; return to mainline to execute command
349 ; The next two instructions are completely pointless. If we get here, the comparison has already
350 ; been done and the branch condition is the exact opposite of what brought us here.
351 LC244 cmpa #DHITOK ; is it a Disk Basic token?
352 lbls LB277 ; brif not
353 jmp [COMVEC+33] ; transfer control to user command handler
354 ; Function handler
355 LC24E cmpb #(0xa7-0x80)*2 ; is it a Disk Basic function token?
356 bls LC256 ; brif so
357 jmp [COMVEC+38] ; transfer control to user handler if not
358 LC256 subb #(0xa2-0x80)*2 ; normalize Disk Basic tokens to 0
359 pshs b ; save jump table offset
360 jsr LB262 ; evaluate parenthetical expression
361 puls b ; get back jump table offset
362 ldx #LC22C ; point to jump table
363 jmp LB2CE ; rejoin mainline code to transfer control
364 ; Error handler
365 DVEC17 puls y ; get back original caller
366 jsr LAD33 ; reset some stuff like CONT
367 jsr LD2D2 ; clean up some Disk Basic stuff
368 pshs y,b ; put return address back and save error code
369 jsr DVEC7 ; close all files
370 puls b ; get back error code
371 cmpb #2*27 ; is it a Disk Basic error code?
372 lblo XVEC17 ; brif not - pass it to Extended Basic
373 leas 2,s ; dump the return address
374 jsr LA7E9 ; stop tape
375 jsr LA974 ; stop sound
376 clr DEVNUM ; reset output to screen
377 jsr LB95C ; do a newline
378 jsr LB9AF ; do a ?
379 ldx #LC290-2*27 ; point to error message table
380 jmp LAC60 ; rejoin mainline error handler
381 ; Error strings (note that NE error is provided by Extended Basic)
382 LC290 fcc 'BR' ; 27 Bad record
383 fcc 'DF' ; 28 Disk full
384 fcc 'OB' ; 29 Out of buffer space
385 fcc 'WP' ; 30 Write protected
386 fcc 'FN' ; 31 Bad file name
387 fcc 'FS' ; 32 Bad file structure
388 fcc 'AE' ; 33 File already exists
389 fcc 'FO' ; 34 Field overflow
390 fcc 'SE' ; 35 Set to non-fielded string
391 fcc 'VF' ; 36 Verify error
392 fcc 'ER' ; 37 Input or write past end of record
393 BASEXT fcc 'BAS' ; default Basic program file extension
394 DEFEXT fcc ' ' ; default blank extension (three spaces)
395 DATEXT fcc 'DAT' ; default extension for data files
396 BINEXT fcc 'BIN' ; default extension for binary files
397 ; "CLS" vector handler. Extended Basic also chose to use this vector as a way to hook into
398 ; the GET/PUT commands, the RENUM token check, and the Extended Basic "functions as commands"
399 ; interpretation scheme. Only the GET/PUT hook is used. Checking the caller address is hacky
400 ; but unavoidable here.
401 DVEC22 pshs x,cc ; save scratch register and flags
402 ldx 3,s ; get caller address
403 cmpx #L975F ; is it coming from GET/PUT?
404 bne LC2BF ; brif not
405 cmpa #'# ; is it GET # or PUT # (disk file operations)?
406 beq LC2C1 ; brif so - don't return to mainline
407 LC2BF puls cc,x,pc ; restore scratch register, flags, and return to mainline
408 ; GET/PUT handler for random file access
409 LC2C1 leas 5,s ; remove saved state from above and don't return to mainline
410 jsr LC82E ; evaluate device number and get FCB pointer
411 stx FCBTMP ; save the FCB pointer
412 clr FCBGET,x ; reset the get data pointer
413 clr FCBGET+1,x
414 clr FCBPUT,x ; reset the put data pointer
415 clr FCBPUT+1,x
416 clr FCBPOS,x ; reset print position
417 lda FCBDRV,x ; get drive number for the file
418 sta DCDRV ; set it as the DSKCON drive number
419 jsr GETCCH ; end of statement?
420 beq LC2EA ; brif so - use current record
421 jsr SYNCOMMA ; insist on a comma
422 ifeq DISKVER
423 jsr LB3E6 ; evaluate expression to D
424 else
425 jsr LB73D ; get unsigned 16 bit number to X
426 tfr x,d ; stash it in D so we can use X as a pointer
427 endc
428 LC2E6 ldx FCBTMP ; get back FCB pointer
429 std FCBREC,x ; set the current record number
430 ifeq DISKVER
431 LC2EA jsr LC685 ; bump record number
432 else
433 LC2EA ldd FCBREC,x ; get desired record number
434 beq LC30B ; brif 0 - records start at 1
435 jsr LC685 ; bump record number
436 endc
437 ldd FCBRLN,x ; get record length
438 ldx FCBBUF,x ; point to FCB data buffer
439 pshs x,b,a ; save them
440 leax -2,u ; point to record number (but zero based)
441 jsr L9FB5 ; do unsigned multiply of record length and record number
442 pshs u,y ; save product (this is the file offset to the record)
443 lda ,s+ ; is MSB 0?
444 bne LC30B ; brif not - record number too big
445 puls x ; middle two bytes are sector number in file - retrieve it
446 puls b ; LSB is offset into the sector - retrieve it
447 LC306 cmpx #(35-1)*18 ; is it more than the maximum number of sectors a file can have?
448 blo LC310 ; brif so
449 LC30B ldb #2*27 ; code for bad record
450 jmp LAC46 ; raise error
451 LC310 ldu FCBTMP ; get pointer to FCB
452 cmpx FCBSOF,u ; is it the same sector we're already handling?
453 lbeq LC3CF ; brif so
454 pshs x,b ; save sector number and sector offset
455 lda FCBFLG,u ; were we doing get or put?
456 beq LC324 ; brif we were doing get
457 clr FCBFLG,u ; flag doing get
458 ldb #3 ; write operation code for DSKCON
459 bsr LC357 ; write the sector data
460 LC324 ldd 1,s ; get sector number
461 jsr LC784 ; convert to a granule offset
462 pshs b ; save granule offset
463 jsr LC779 ; calculate starting sector of granule number
464 negb ; make negative
465 addb 3,s ; add LS byte of sector number
466 incb ; add one - sectors in FCB start at 1
467 stb FCBSEC,u ; set sector
468 ldb FCBFGR,u ; get first granule in file
469 jsr LC755 ; fetch FAT pointer
470 leau FATCON,x ; point to actual granule table
471 lda ,s ; get number of granules offset to the record
472 inca ; bump it (compensate for deca below)
473 LC33E leax ,u ; point X to entry for this granule
474 abx
475 deca ; are we at the correct one?
476 beq LC37B ; bif not
477 stb ,s ; save granule offset on stack
478 ldb ,x ; get next granule in file
479 cmpb #0xc0 ; is it "end of file" flag?
480 blo LC33E ; brif not
481 ldb ,s ; get offset to previous granule
482 tst VD8 ; get or put?
483 bne LC366 ; brif put
484 LC352 ldb #2*23 ; code for input past end of file
485 jmp LAC46 ; raise error
486 LC357 leax FCBCON,u ; point to data buffer for FCB
487 LC35A stb DCOPC ; set operation code for DSKCON
488 stx DCBPT ; set buffer pointer for DSKCON
489 leax ,u ; point to FCB
490 jsr LC763 ; convert FCB track and sector to DSKCON parameters
491 jmp LD6F2 ; read or write the sector
492 LC366 pshs x,a ; save granule counter and pointer to last used granule
493 jsr LC7BF ; find a free granule
494 tfr a,b ; save allocated granule
495 puls a,u ; get last granule pointer and counter off stack
496 stb ,u ; add it to the file's granule chain
497 deca ; do we have enough of them?
498 bne LC366 ; brif not - allocate another
499 pshs x,b ; save alocated granule and pointer
500 jsr LC71E ; write the FAT out
501 puls b,x ; get back allocated granule and pointer
502 LC37B leas 1,s ; remove granule number
503 ldu FCBTMP ; point to FCB
504 stb FCBCGR,u ; save current granule
505 lda #0xff ; set to illegal sector offset to force sector data to be read
506 sta FCBSOF,u
507 lda ,x ; get next granule pointer
508 cmpa #0xc0 ; last granule?
509 blo LC3B2 ; brif not
510 anda #0x3f ; get only the number of sectors used
511 cmpa FCBSEC,u ; compare calculated sector to current sector
512 bhs LC3B2 ; brif sector is <= last one in file
513 lda VD8 ; GET or PUT?
514 beq LC352 ; brif GET - do IE error
515 lda FCBSEC,u ; get sector number from FCB
516 ora #0xc0 ; add "last granule" flag bits
517 sta ,x ; update FAT
518 jsr LC5A9 ; write FAT if needed
519 ldx FCBRLN,u ; get record length
520 cmpx #SECLEN ; exactly one sector?
521 bne LC3AD ; brif not
522 cmpx FCBLST,u ; is number of bytes in last sector a full sector?
523 beq LC3B2 ; brif so
524 lda #0x81 ; set "presaved" flag and force number of bytes to be 256
525 skip1 ; skip next byte ("BRN")
526 LC3AD clra ; set number of bytes in last sector to 0
527 clrb ; clear LS byte of D
528 std FCBLST,u ; set number of bytes used in last sector
529 LC3B2 ldb #2 ; DSKCON read operation
530 ldx FCBRLN,u ; get record length
531 cmpx #SECLEN ; exactly one sector?
532 bne LC3C8 ; brif not exactly
533 leas 7,s ; clean up stack
534 ldx FCBBUF,u ; point to start of random file buffer
535 lda VD8 ; is it GET or PUT?
536 beq LC3C5 ; brif GET
537 ldb #3 ; DSKCON write opreation
538 LC3C5 jmp LC35A ; go read or write a sector
539 LC3C8 jsr LC357 ; read a sector into data buffer
540 puls b,x ; get back byte offset to record
541 stx FCBSOF,u ; save sector offset
542 LC3CF pshs b ; save sector byte offset
543 jsr LC755 ; point to FAT
544 leax FATCON,x ; point to FAT data
545 ldb FCBCGR,u ; get current granulenumber
546 abx ; point to granule data
547 lda ,x ; get this granule's next pointer
548 cmpa #0xc0 ; end of file flag?
549 blo LC40A ; brif not
550 anda #0x3f ; convert to number of sectors in final granule
551 cmpa FCBSEC,u ; are we asking for the last sector?
552 bne LC40A ; brif not
553 ldd FCBLST,u ; get number of bytes in last sector
554 anda #0x7f ; lose pre-saved flag
555 pshs d ; save number of bytes in last sector
556 clra ; zero extend byte offset
557 ldb 2,s ; get byte offset
558 addd 3,s ; add in record length
559 cmpd ,s++ ; is it more than last sector?
560 bls LC40A ; brif the whole record fits
561 tst VD8 ; is it GET?
562 lbeq LC352 ; brif so - IE error if file doesn't have a whole record available
563 ifeq DISKVER
564 anda #1 ; keep only bit 0 of byte count
565 ora #0x80 ; set pre-saved flag bit
566 else
567 cmpd #SECLEN ; is it a whole sector we need?
568 bls LC405 ; brif not
569 ldd #SECLEN ; force one sector length
570 LC405 ora #0x80 ; set pre-saved flag bit
571 endc
572 std FCBLST,u ; save number of bytes in last sector
573 LC40A puls b ; get byte offset
574 leax FCBCON,u ; point to data buffer
575 abx ; offset into data buffer
576 ldu 2,s ; point to position in random file buffer
577 pshs b ; save byte offset
578 lda #-1 ; convert D into a negative 2 byte number representing unused bytes in sector
579 addd 1,s
580 bhs LC421 ; brif there are enough bytes to finish record
581 std 1,s ; save new temporary record length counter
582 puls b ; restore byte counter
583 negb ; negate it (B is number of bytes available to a record in this sector)
584 bra LC429 ; move the data
585 LC421 ldb 2,s ; get remaining record length
586 clr 1,s ; clear the temporary record length counter
587 clr 2,s
588 leas 1,s ; we no longer need byte offset
589 LC429 lda VD8 ; GET?
590 beq LC42F ; brif so
591 exg x,u ; swap pointers so we write to data buffer
592 LC42F jsr LA59A ; copy data
593 stu 2,s ; save new record pointer
594 ldu FCBTMP ; get pointer to FCB
595 lda VD8 ; GET?
596 beq LC43E ; brif so
597 sta FCBFLG,u ; flag as PUT
598 stx 2,s ; save buffer pointer
599 LC43E ldx FCBSOF,u ; get sector offset count
600 leax 1,x ; bump it
601 clrb ; byte offset in this new sector is 0
602 ldu ,s ; get length of record needed
603 lbne LC306 ; brif not already completed ar ecord
604 puls a,b,x,pc ; clean up stack and return
605 ; OPEN handler
606 DVEC0 leas 2,s ; don't return mainline
607 jsr LB156 ; evaluate mode expression
608 jsr LB6A4 ; get first character in the mode string
609 pshs b ; save it
610 jsr LA5A2 ; parse device number
611 tstb ; disk file?
612 lble LA603 ; return mainline if not disk file
613 puls a ; get mode
614 pshs a,b ; save mode and file number
615 clr DEVNUM ; reset device to screen
616 jsr SYNCOMMA ; insist on a comma
617 ldx #DATEXT ; point to "DAT" extension as default for data file
618 jsr LC938 ; parse file name
619 ldd #0x01ff ; file type is "data" (1) and ASCII
620 std DFLTYP ; save file type
621 ldx #SECLEN ; default record length - one whole sector
622 jsr GETCCH ; is there a record length specifier?
623 beq LC481 ; brif not
624 jsr SYNCOMMA ; insist on comma
625 jsr LB3E6 ; evaluate record length
626 ldx FPA0+2 ; get evaluated length
627 LC481 stx DFFLEN
628 lbeq LB44A ; record length of 0 makes no sense of error if so
629 jsr LA5C7 ; raise error if more stuff
630 puls a,b ; get mode and fil enumber
631 LC48D pshs a ; save mode
632 jsr LC749 ; point to FCB for this file
633 lbne LA61C ; brif the file is already open
634 stx FCBTMP ; save FCB pointer
635 jsr LC79D ; make sure FAT is valid
636 jsr LC68C ; search for requested file
637 puls b ; get mode
638 lda #INPFIL ; input file flag
639 pshs a ; save it
640 cmpb #'I ; input mode?
641 bne LC4C7 ; brif not
642 jsr LC6E5 ; see if match was found
643 jsr LC807 ; check if it's already open
644 ldx V974 ; point to directory data
645 ldd DIRTYP,x ; get file type and ASCII flag
646 std DFLTYP ; save it
647 bsr LC52D ; initialize FCB
648 jsr LC627 ; go read first sector from file
649 LC4BB jsr LC755 ; point to FAT
650 inc <<FAT0,x ; bump number of open files on this disk
651 ldx FCBTMP ; get back FCB pointer
652 puls a ; get file type
653 sta <<FCBTYP,x ; save file type
654 rts
655 LC4C7 asl ,s ; set type to output
656 cmpb #'O ; output requested?
657 bne LC4E8 ; brif not
658 tst V973 ; did file exist?
659 beq LC4E1 ; brif not
660 jsr LC6FC ; kill the old file
661 lda V973 ; get directory sector number of old file
662 sta V977 ; save as first free directory entry
663 ldx V974 ; get directory image of old file
664 stx V978 ; asve it as first free entry
665 ifeq DISKVER
666 LC4E1 bsr LC567 ; set up new directory entry on disk
667 else
668 LC4E1 jsr LC567 ; set up new directory entry on disk
669 endc
670 bsr LC538 ; initialize the file buffer
671 bra LC4BB ; finish setting up FCB
672 LC4E8 cmpb #'R ; random file?
673 beq LC4F2 ; brif so
674 cmpb #'D ; direct file?
675 lbne LA616 ; brif not - bad file mode
676 LC4F2 asl ,s ; set file type to random
677 ldd RNBFAD ; get address of random file buffer area
678 pshs d ; save it
679 addd DFFLEN ; add in record length
680 bcs LC504 ; brif we overflowed memory
681 cmpd FCBADR ; is it more than FCB data area?
682 bls LC509 ; brif not
683 LC504 ldb #2*29 ; code for out of buffer space
684 jmp LAC46 ; raise error
685 LC509 pshs d ; save new end of buffer area
686 tst V973 ; did the file exist?
687 bne LC514 ; brif so
688 bsr LC567 ; set up directory
689 ifeq DISKVER
690 LC514 bsr LC52D ; inistialize FCB
691 else
692 bra LC519 ; initialize FCB
693 LC514 lda #0xff ; set file type match = 0xff (all types)
694 jsr LC807 ; see if any open file matches and AO error if so
695 LC519 bsr LC52D ; initialize FCB
696 endc
697 com FCBSOF,x ; set FCBSOF to 0xff (illegal offset) to force new sector to be read
698 inc FCBREC+1,x ; set record number to 1
699 puls a,b,u ; D = end of buffer, U = start of buffer
700 std RNBFAD ; save start of free buffer space
701 stu FCBBUF,x ; save buffer pointer in FCB
702 ldu DFFLEN ; get record length
703 stu FCBRLN,x ; save in FCB
704 bra LC4BB ; finish setting things up
705 LC52D bsr LC538 ; initialize FCB
706 ldu V974 ; get directory image
707 ldu DIRLST,u ; get number of bytes in last sector
708 stu FCBLST,x ; save it
709 rts
710 LC538 ldx FCBTMP ; get FCB pointer
711 ldb #FCBCON ; number of control bytes
712 LC53C clr ,x+ ; clear a control byte
713 decb ; done all?
714 bne LC53C ; brif not
715 ldx FCBTMP ; get back FCB pointer
716 lda DCDRV ; set drive number
717 sta FCBDRV,x
718 lda V976 ; get first granule
719 sta FCBFGR,x ; save it in FCB
720 sta FCBCGR,x ; also set as current granule
721 ldb V973 ; get directory sector offset
722 subb #3 ; directory sectors start at 3
723 aslb ; 8 directory entries per sector
724 aslb
725 aslb
726 pshs b ; save sector offset
727 ldd V974 ; get directory pointer
728 subd #DBUF0 ; calculate offset in sector buffer
729 lda #8 ; 8 directory entries per sector
730 mul ; now A contains 0 to 7
731 adda ,s+ ; add to directory sector offset
732 sta FCBDIR,x ; save directory entry number in FCB
733 rts
734 LC567 ldb #28*2 ; code for disk full
735 lda V977 ; get sector number of first empty entry
736 lbeq LAC46 ; brif none found
737 sta V973 ; save sector number of first entry
738 sta DSEC ; set DSKCON sector parameter
739 ldb #2 ; DSKCON read operation
740 stb DCOPC
741 jsr LD6F2 ; read sector
742 ldx V978 ; get address of RAM image of unused directory
743 stx V974 ; save as current entry
744 leau ,x ; point to directory image
745 ldb #DIRLEN ; set counter to clear the entry
746 LC586 clr ,x+ ; clear a byte
747 decb ; done all?
748 bne LC586 ; brif not
749 ldx #DNAMBF ; point to file name
750 ldb #11 ; 8.3 total number of characters
751 jsr LA59A ; copy file name into directory
752 ldd DFLTYP ; get file type and ASCII flag
753 std <<0,u ; save in directory
754 ldb #33 ; first granule to check
755 jsr LC7BF ; find first gree granule
756 sta V976 ; save granule found
757 sta 2,u ; save as first granule in file
758 ldb #3 ; DSKCON write operation
759 stb DCOPC
760 jsr LD6F2 ; write out directory entry
761 LC5A9 pshs u,x,b,a ; save registers
762 jsr LC755 ; point to FAT
763 inc FAT1,x ; mark FAT as changed
764 lda FAT1,x ; have enough things changed?
765 cmpa WFATVL
766 blo LC5BA ; brif not
767 jsr LC71E ; write FAT out
768 LC5BA puls a,b,x,u,pc ; restore registers and return
769 ; Generic input handler
770 DVEC4 lda DEVNUM ; get device number
771 lble XVEC4 ; brif not disk file
772 leas 2,s ; don't return mainline if disk
773 LC5C4 pshs x,b ; save registers
774 clr CINBFL ; clear EOF flag
775 ldx #FCBV1-2 ; point to input file buffer table (-2 here to avoid decrementing device)
776 ldb DEVNUM ; get device number
777 aslb ; two bytes per pointer
778 ldx b,x ; get pointer to FCB
779 ldb FCBTYP,x ; get type of file
780 cmpb #RANFIL ; random file?
781 bne LC5EC ; brif not
782 ldd FCBGET,x ; get record counter
783 cmpd FCBRLN,x ; compare to size of record
784 bhs LC5FE ; brif pointer is after end of record - handle empty buffer
785 addd #1 ; move pointer forward
786 std FCBGET,x ; save new read pointer
787 ldx FCBBUF,x ; point to data buffer
788 leax d,x ; offset to buffer location
789 lda -1,x ; get the character (before the increment)
790 puls b,x,pc ; return the character from the record
791 LC5EC ldb FCBCFL,x ; has a character been "ungot"?
792 beq LC5F9 ; brif not
793 lda FCBCDT,x ; get ungot character
794 clr FCBCFL,x ; clear ungot flag
795 puls b,x,pc ; restore registers and return
796 LC5F9 ldb FCBDFL,x ; is there any data left to read?
797 beq LC602 ; brif so
798 LC5FE com CINBFL ; flag EOF
799 puls b,x,pc ; restore registers and return
800 LC602 ldb FCBCPT,x ; get character pointer
801 inc FCBCPT,x ; bump saved pointer
802 dec FCBLFT,x ; anything left?
803 beq LC611 ; brif buffer is empty
804 abx ; add offset into buffer
805 lda FCBCON,x ; get actual character (offset over the FCB control structure)
806 puls b,x,pc ; restore registers and return
807 LC611 pshs u,y ; save register
808 clra ; zero extend offset
809 leau d,x ; now U has buffer offset
810 lda FCBCON,u ; get character to return (offset over FCB control structure)
811 pshs a ; save return value
812 clr FCBCPT,x ; reset character pointer
813 lda FCBDRV,x ; set DSKCON to the correct drive
814 sta DCDRV
815 bsr LC627 ; read a sector
816 puls a,y,u ; restore registers and get back return value
817 puls b,x,pc ; restore registers and return
818 LC627 lda FCBSEC,x ; get current sector number
819 LC629 inca ; bump sector counter
820 pshs a ; save sector counter for later
821 cmpa #9 ; end of granule?
822 bls LC631 ; brif not
823 clra ; reset granule sector offset
824 LC631 sta FCBSEC,x ; save sector offset
825 ldb FCBCGR,x ; get granule number
826 leau ,x ; save FCB pointer
827 jsr LC755 ; point to correct FAT image
828 abx ; now X points to granule data
829 ldb FATCON,x ; get next granule pointer (offset past control data structure)
830 leax ,u ; reset FCB pointer
831 cmpb #0xc0 ; is the current granule the last one?
832 bhs LC64D ; brif so
833 puls a ; get sector number
834 suba #10 ; did it overflow the granule?
835 bne LC65E ; brif not
836 stb FCBCGR,x ; save new granule number
837 bra LC629 ; set variables for new granule
838 LC64D andb #0x3f ; get number of sectors in the granule
839 cmpb #9 ; is it more than a granule has?
840 bls LC658 ; brif not
841 LC653 ldb #2*32 ; code for bad file structure
842 jmp LAC46 ; raise error
843 LC658 subb ,s+ ; subtract current sector number and also clean stack
844 bcs LC67D ; brif past last sector
845 tfr b,a
846 LC65E pshs a ; save sector number difference
847 bsr LC685 ; bump record number
848 lda #2 ; set up for read
849 sta DCOPC
850 jsr LC763 ; set DSKCON variables for correct track and sector
851 leau FCBCON,x ; point past control structure to actual buffer
852 stu DCBPT ; set read destination
853 jsr LD6F2 ; go ahead and read the sector
854 clr FCBLFT,x ; set buffer left to full sector
855 ldb ,s+ ; get sector number back
856 bne LC684 ; brif not last sector
857 ldd FCBLST,x ; get bytes in last sector
858 bne LC681 ; brif bytes in last sector is nonzero
859 LC67D clrb ; set remaining bytes to 256
860 com FCBDFL,x ; flag buffer empty
861 LC681 stb FCBLFT,x ; save number of bytes in buffer
862 LC684 rts
863 LC685 ldu FCBREC,x ; get current record number
864 leau 1,u ; bump it
865 stu FCBREC,x ; save new record number
866 rts
867 ; Scan directory for file name; return sector number in V973, granule in V976,
868 ; and pointer to directory data in V974. If disk is full, pointer in V978,
869 ; and first unused sector in V977 (and V973 is 0)
870 LC68C clr V973 ; clear sector number (for not found)
871 clr V977 ; clear temp sector number
872 ldd #0x1102 ; set up to read track 17
873 sta DCTRK
874 stb DCOPC
875 ldb #3 ; start with sector 3
876 LC69B stb DSEC ; set DSKCON sector
877 ldu #DBUF0 ; read to global buffer
878 stu DCBPT
879 jsr LD6F2 ; read directory sector
880 LC6A5 stu V974 ; set pointer to directory entry data
881 leay ,u ; save start of directory entry
882 lda ,u ; NUL (for a deleted entry)?
883 bne LC6D6 ; brif not
884 bsr LC6D9 ; set unused pointers
885 LC6B0 ldx #DNAMBF ; point to desired file name
886 LC6B3 lda ,x+ ; does a character match?
887 cmpa ,u+
888 bne LC6C7 ; brif not
889 cmpx #DNAMBF+11 ; end of file name?
890 bne LC6B3 ; brif not
891 stb V973 ; save sector number for match
892 lda FCBFGR,u ; set first granule in file
893 sta V976
894 rts
895 LC6C7 leau DIRLEN,y ; point to next directory entry
896 cmpu #DBUF0+SECLEN ; end of sector?
897 bne LC6A5 ; brif not - search another
898 incb ; move to next sector
899 cmpb #11 ; 11 sectors in directory - checked all of them?
900 bls LC69B ; brif more sectors
901 rts
902 LC6D6 coma ; is first byte of file name 0xff?
903 bne LC6B0 ; brif not - actually do a search
904 LC6D9 lda V977 ; have we already found an unused entry?
905 bne DVEC12 ; brif so
906 stb V977 ; save sector number for unused entry
907 stu V978 ; save pointer to unused entry
908 DVEC12 rts ; NOTE: this is used as a dummy do-nothing RAM hook handler
909 LC6E5 ldb #2*26 ; code for NE error
910 tst V973 ; was entry found?
911 bne DVEC12 ; brif so
912 jmp LAC46 ; raise error
913 ; KILL command
914 KILL jsr LC935 ; parse file name
915 jsr LA5C7 ; brif something after file name
916 jsr LC79D ; load FAT data
917 bsr LC68C ; look up file
918 bsr LC6E5 ; raise error if not found
919 LC6FC lda #0xff ; file type to match (all types)
920 jsr LC807 ; find any file that matches type
921 ldx V974 ; get directory entry pointer
922 clr ,x ; mark it as unused
923 ldb #3 ; set up to write
924 stb DCOPC
925 jsr LD6F2 ; write out the updated directory sector
926 ldb DIRGRN,x ; get starting granule of file
927 LC70F bsr LC755 ; point to correct FAT
928 leax FATCON,x ; skip control structure
929 abx ; now X points to next granule
930 ldb ,x ; get next granule pointer
931 lda #0xff ; mark granule free
932 sta ,x
933 cmpb #0xc0 ; was it last one?
934 blo LC70F ; brif not
935 ; Write FAT to drive
936 LC71E ldu #DBUF0 ; point to global sector buffer
937 stu DCBPT ; point DSKCON there
938 ldd #0x1103 ; set up to write track 17
939 sta DCTRK
940 stb DCOPC
941 ldb #2 ; FAT is in sector 2
942 stb DSEC
943 bsr LC755 ; point to proper FAT entry
944 clr FAT1,x ; mark FAT as having no outstanding changes
945 leax FATCON,x ; move past control structure
946 ldb #GRANMX ; get total granule count in a FAT
947 jsr LA59A ; copy the FAT data to buffer
948 ifeq DISKVER
949 LC739 clr ,x+ ; clear a byte
950 cmpx #DBUF0+SECLEN ; end of sector?
951 else
952 LC739 clr ,u+ ; clear out the rest of the sector (to avoid junk going into it)
953 cmpu #DBUF0+SECLEN ; end of sector?
954 endc
955 ifeq DISKVER-1
956 bne LC739 ; brif not
957 endc
958 jmp LD6F2 ; go write the FAT sector out
959 ; Point X to the correct FCB based on DEVNUM (or B if entering at LC749)
960 LC744 pshs b ; save register
961 ldb DEVNUM ; get device number
962 skip2
963 LC749 pshs b ; save register
964 lslb ; two bytes per pointer
965 ldx #FCBV1-2 ; point to FCB table (-2 to adjust for 1-based file numbers)
966 ldx b,x ; get pointer
967 ldb <<FCBTYP,x ; set flags for file type
968 puls b,pc ; restore register and return
969 ; Point X to FAT image for the selected drive
970 LC755 pshs b,a ; save registers
971 lda DCDRV ; get drive number
972 ldb #FATLEN ; get size of FAT mirror
973 mul ; calculate offset from first FAT image
974 ldx #FATBL0 ; point to first FAT image
975 leax d,x ; offset to correct one
976 puls a,b,pc ; restore registers and return
977 ; Set up DSKCON variables to point to the correct sector and track for the current file position
978 LC763 ldb FCBCGR,x ; get granule number
979 lsrb ; two granules per track
980 stb DCTRK ; save track
981 cmpb #17 ; is it below the directory?
982 blo LC76E ; brif so
983 inc DCTRK ; skip directory track if not
984 LC76E aslb ; double track number
985 negb ; subtract from actual granule number: -(TRK*2)+CGR
986 addb FCBCGR,x
987 bsr LC779 ; set B=9 for odd granule, B=0 for even
988 addb FCBSEC,x ; add granule sector offset
989 stb DSEC ; set DSKCON sector
990 rts
991 LC779 pshs b,a ; temp store original
992 aslb ; times 2
993 rola
994 aslb ; times 4
995 rola
996 aslb ; times 8
997 rola
998 addd ,s++ ; times 9
999 rts
1000 ; Convert sector offset in D to a granule offset (0-67) in B (lose fractional part)
1001 LC784 clr ,-s ; make a temporary counter
1002 LC786 inc ,s ; bump division counter
1003 subd #90 ; does 90 go?
1004 bpl LC786 ; brif so
1005 lda ,s ; get quotient (+1)
1006 stb ,s ; save remainder (negative)
1007 ldb #10 ; multiply result by 10 (we divided by 90)
1008 mul
1009 puls a ; get back remainder
1010 LC796 decb ; decrement granule count
1011 adda #9 ; have we used up the remainder?
1012 bmi LC796 ; brif not
1013 clra ; zero extend result
1014 LC79C rts
1015 ; Make sure FAT data is valid
1016 LC79D bsr LC755 ; point to correct FAT
1017 tst <<FAT0,x ; any open files?
1018 bne LC79C ; brif so
1019 clr FAT1,x ; reset change count
1020 leau FATCON,x ; point past control structure
1021 ldx #DBUF0 ; point DSKCON to sector buffer
1022 stx DCBPT
1023 ldd #0x1102 ; read track 17
1024 sta DCTRK
1025 stb DCOPC
1026 ldb #2 ; read sector 2 (FAT)
1027 stb DSEC
1028 jsr LD6F2 ; go read FAT
1029 ldb #GRANMX ; get total FAT data size
1030 jmp LA59A ; copy FAT data from sector buffer to FAT image
1031 ; Find free granule; enter with B containing the start location; mark granule with 0xc0 in the
1032 ; FAT to indicate last granule in file. Return granule number in A
1033 LC7BF bsr LC755 ; get pointer to FAT
1034 leax FATCON,x ; move past controls structure
1035 clra ; reset granule counter
1036 andb #0xfe ; start at first granule on track
1037 clr ,-s ; initialize direction counter to down
1038 LC7C8 com b,x ; is this granule free
1039 beq LC7FD ; brif so
1040 com b,x ; restore granule data
1041 inca ; bump counter
1042 cmpa #GRANMX ; searched whole FAT?
1043 bhs LC7F8 ; brif so - disk full
1044 incb ; bump granule counter
1045 bitb #1 ; odd?
1046 bne LC7C8 ; brif so
1047 pshs b,a ; save granule counter and current granule
1048 subb #2 ; move back one track
1049 com 2,s ; flip direction
1050 bne LC7EC ; brif we're switching to "up"
1051 subb ,s+ ; subtract out granule counter (moves other side of start)
1052 bpl LC7E8 ; brif below lower bound
1053 ldb ,s ; get original granule number
1054 LC7E6 com 1,s ; restore direction flag
1055 LC7E8 leas 1,s ; remove saved granule number
1056 bra LC7C8 ; see if we found a free granule yet
1057 LC7EC addb ,s+ ; move to the top side of starting position
1058 cmpb #GRANMX ; did we overflow upward?
1059 blo LC7E8 ; brif not
1060 ldb ,s ; get original granule number
1061 subb #4 ; move an extra track in the other direction if overflowed up
1062 bra LC7E6 ; go see if we found a free one yet
1063 LC7F8 ldb #2*28 ; code for disk full
1064 jmp LAC46 ; raise error
1065 LC7FD leas 1,s ; clean up direction flag
1066 tfr b,a ; put granule number in A
1067 abx ; point X to granule data
1068 ldb #0xc0 ; set granule to "used 0, last of file"
1069 stb ,x
1070 LC806 rts
1071 ; Check active files to see if a file is already open; drive number and granule number
1072 ; AO will not be generated if the current status matches *exactly* the requested type in A.
1073 LC807 pshs a ; save desired file type
1074 ldb FCBACT ; get number of active FCBs
1075 incb ; include the system FCB in the check
1076 LC80D jsr LC749 ; point to FCB
1077 beq LC829 ; brif not open at all
1078 lda DCDRV ; get desired drive
1079 cmpa FCBDRV,x ; match?
1080 bne LC829 ; brif not
1081 ldu V974 ; get directory entry pointer
1082 lda DIRGRN,u ; get first granule in file
1083 cmpa FCBFGR,x ; does it match?
1084 bne LC829 ; brif not
1085 lda <<FCBTYP,x ; get file type
1086 cmpa ,s ; does it match the type we want?
1087 lbne LA61C ; brif not - raise AO error
1088 LC829 decb ; checked all FCBs?
1089 bne LC80D ; brif not
1090 puls a,pc ; clean stack and return
1091 ; Parse device number and make sure it's open in random mode
1092 LC82E jsr LA5A5 ; evaluate device number
1093 clr DEVNUM ; reset device number to screen
1094 tstb ; set flags on device number
1095 lble LB44A ; brif not a disk file
1096 jsr LC749 ; fetch FCB pointer
1097 lda <<FCBTYP,x ; is file open?
1098 lbeq LA3FB ; brif not
1099 cmpa #RANFIL ; random file?
1100 beq LC806 ; brif so
1101 LC845 jmp LA616 ; raise bad file mode
1102 ; Input device number check handler
1103 DVEC5 lda #INPFIL ; set to check for input file
1104 skip2
1105 ; Output device number check handler
1106 DVEC6 lda #OUTFIL ; set to check for output file
1107 tst DEVNUM ; set flags on device number
1108 ble LC806 ; brif not a disk file (return)
1109 stx ,s ; save X and lose return address
1110 jsr LC744 ; point to FCB
1111 ifeq DISKVER
1112 pshs a ; save file type requested
1113 else
1114 pshs d ; save b and file type requested
1115 endc
1116 lda <<FCBTYP,x ; get file type
1117 lbeq LA3FB ; brif not open
1118 cmpa #RANFIL ; random file?
1119 ifeq DISKVER
1120 beq LC866 ; brif so - it's good (both input and output)
1121 else
1122 beq LC868 ; brif so - it's good (both input and output)
1123 endc
1124 cmpa ,s ; is it the right type?
1125 bne LC845 ; brif not - bad file mode
1126 ifeq DISKVER
1127 LC866 puls a,x,pc ; restore registers and return
1128 else
1129 LC866 puls a,b,x,pc ; clean up stack, restore registers, and return to caller
1130 ; This code is required to work around the dumbosity in the INPUT command which outputs the
1131 ; prompt string uncondionally so it would cause the prompt string to end up being output to
1132 ; a random file.
1133 LC868 ldx 4,s ; are we coming from INPUT?
1134 cmpx #LB00C
1135 bne LC866 ; brif not
1136 jsr SYNCOMMA ; make sure there's a comma after device
1137 cmpa #'" ; is there a prompt string?
1138 bne LC881 ; brif not
1139 jsr LB244 ; parse prompt string
1140 jsr LB657 ; fetch string details (and discard them)
1141 ldb #'; ; make sure there's a semicolon after the prompt string
1142 jsr LB26F
1143 LC881 ldx #LB01E ; return after the prompt string check
1144 stx 4,s
1145 puls a,b,x,pc ; return to mainline flow
1146 endc
1147 ; Device number validity check handler
1148 ifeq DISKVER
1149 DVEC1 ble LC806 ; brif not a disk file
1150 else
1151 DVEC1 ble LC8AF ; brif not a disk file
1152 endc
1153 cmpb FCBACT ; is it in range for open files?
1154 lbhi LA61F ; brif not - device number error
1155 puls x,pc ; purge RAM hook call return and return to original caller
1156 ; Set print parameters handler
1157 DVEC2 tst DEVNUM ; is it disk file?
1158 ifeq DISKVER
1159 ble LC806 ; brif not
1160 else
1161 ble LC8AF ; brif not
1162 endc
1163 leas 2,s ; don't return to mainline code
1164 pshs x,b,a ; save registers
1165 clr PRTDEV ; set print device to "display"
1166 jsr LC744 ; point to correct FCB
1167 ldb FCBPOS,x ; get print position
1168 clra ; line width (256)
1169 ldx #0x1000 ; tab width of 16, no last tab position
1170 jmp LA37C ; go save print parameters
1171 ; LIST break check handler
1172 DVEC11 tst DEVNUM ; is it disk file?
1173 ble LC8AF ; brif not
1174 leas 2,s ; purge return - don't do break check if disk file
1175 LC8AF rts
1176 ifeq DISKVER-1
1177 ; Command interpreation handler
1178 ; This code replaces the main command interpretation loop completely. It includes a check
1179 ; to see if any keys are down before doing a break check. This is unneeded with Color Basic
1180 ; 1.2, but earlier versions of Color Basic benefit from it. This is the only change compared
1181 ; to plain ECB.
1182 DVEC20 leas 2,s ; don't return to mainline code
1183 LC8B2 andcc #0xaf ; enable interrupts
1184 clr PIA0+2 ; strobe all keyboard columns
1185 lda PIA0 ; get row data
1186 coma ; invert bits so 1 means pressed
1187 anda #0x7f ; lose the comparator input
1188 beq LC8C2 ; brif no keys down - don't check for BREAK
1189 jsr LADEB ; do a break check
1190 LC8C2 ldx CHARAD ; get input pointer
1191 stx TINPTR ; save it so things can find the start of this statement
1192 lda ,x+ ; get current character
1193 beq LC8D1 ; brif end of line
1194 cmpa #': ; is it end of statement?
1195 beq LC8F3 ; brif so
1196 jmp LB277 ; raise syntax error if not end of statement
1197 LC8D1 lda ,x++ ; get MSB of next line address
1198 sta ENDFLG ; this sets ENDFLG to "END" (unless program code is above 0x7FFF)
1199 bne LC8DA ; brif not end of program
1200 jmp LAE15 ; go do "END" If we fell off the end of the program
1201 LC8DA ldd ,x+ ; get line number for this line (and leave pointer one before line text)
1202 std CURLIN ; set current line number
1203 stx CHARAD ; set input pointer to start of line text
1204 lda TRCFLG ; are we doing "TRON"?
1205 beq LC8F3 ; brif not
1206 lda #'[ ; show [
1207 jsr PUTCHR
1208 lda CURLIN ; restore MSB of line number
1209 jsr LBDCC ; show line number
1210 lda #'] ; show ]
1211 jsr PUTCHR
1212 LC8F3 jsr GETNCH ; get starting character of next statement
1213 tfr cc,b ; save flags
1214 cmpa #0x98 ; CSAVE?
1215 bne LC8FE ; brif not
1216 jmp L8316 ; go handle ECB's CSAVE extensions (CSAVEM)
1217 LC8FE cmpa #0x97 ; CLOAD?
1218 bne LC905 ; brif not
1219 jmp L8311 ; go handle ECB's CLOAD extensions (multi-origin binaries)
1220 LC905 tfr b,cc ; restore flags for input byte
1221 jsr LADC6 ; go interpret command token
1222 bra LC8B2 ; process next statement
1223 endc
1224 ; EOF handler
1225 DVEC14 leas 2,s ; dont return to mainline code
1226 lda DEVNUM ; get device number
1227 pshs a ; save it
1228 jsr LA5AE ; evaluate device number
1229 jsr LA3ED ; make sure it's open for input
1230 tst DEVNUM ; set flags on device
1231 lble LA5DA ; brif not disk file - go to mainline code
1232 jsr LC744 ; point to correct FCB
1233 ldb <<FCBTYP,x ; get file type
1234 cmpb #RANFIL ; is it random file? (have to check since random is valid for input)
1235 ifeq DISKVER
1236 beq LC845 ; bad file mode if so
1237 else
1238 lbeq LA616 ; bad file mode if so
1239 endc
1240 clrb ; set flag to not EOF (false)
1241 lda FCBCFL,x ; is there an "ungot" character?
1242 bne LC932 ; brif so
1243 ldb FCBDFL,x ; is there anything in the buffer? Will be 0xff if not
1244 LC932 jmp LA5E4 ; return status
1245 ; Parse a disk file name. Enter at LC938 with a pointer to the default extension in X.
1246 ; Valid file name patterns are:
1247 ; N:FILENAME[.EXT]
1248 ; N:FILENAME[/EXT]
1249 ; FILENAME[.EXT][:N]
1250 ; FILENAME[/EXT][:N]
1251 ; where N is a drive number.
1252 LC935 ldx #DEFEXT ; point to blank default extension
1253 LC938 clr ,-s ; set a flag for whether drive number was seen
1254 lda DEFDRV ; set drive number to default (as set by DRIVE)
1255 sta DCDRV
1256 ldu #DNAMBF ; point to file name buffer
1257 ldd #0x2008 ; space character and 8 characters to set
1258 LC945 sta ,u+ ; blank a character
1259 decb ; done all?
1260 bne LC945 ; brif not
1261 ldb #3 ; three characters in extension
1262 jsr LA59A ; set default extension
1263 jsr L8748 ; evaluate file name string
1264 leau ,x ; point to start of the string
1265 cmpb #2 ; is string less than 2 characters?
1266 blo LC96A ; brif so - can't be N:FILENAME.EXT pattern
1267 lda 1,u ; get second character
1268 cmpa #': ; is it colon?
1269 bne LC96A ; brif not - no leading drive number
1270 lda ,u ; get leading character
1271 cmpa #'0 ; is it below ASCII 0?
1272 blo LC96A ; brif so - not a drive number
1273 cmpa #'3 ; is it above ASCII 3?
1274 bhi LC96A ; brif so - not a drive number
1275 bsr LC99D ; get drive number
1276 LC96A ldx #DNAMBF ; point to start of file name buffer
1277 incb ; compensate for DECB below
1278 LC96E decb ; end of string?
1279 bne LC97D ; brif so
1280 leas 1,s ; clean up drive number seen flag
1281 LC973 cmpx #DNAMBF ; was there a file name?
1282 bne LC9DF ; brif not
1283 LC978 ldb #2*31 ; bad file name error code
1284 jmp LAC46 ; raise error
1285 LC97D lda ,u+ ; get character from string
1286 cmpa #'. ; is it extension?
1287 beq LC9B0 ; brif so
1288 cmpa #'/ ; is it other extension introducer?
1289 beq LC9B0 ; brif so
1290 cmpa #': ; drive number introducer?
1291 beq LC994 ; brif so
1292 cmpx #DEXTBF ; are we at the end of the file name buffer?
1293 beq LC978 ; brif so - name too long
1294 bsr LC9D0 ; put character in file name
1295 bra LC96E ; process another
1296 LC994 bsr LC973 ; bad file name if no name yet
1297 bsr LC99D ; parse drive number
1298 tstb ; is there anything left?
1299 bne LC978 ; brif so
1300 LC99B puls a,pc ; clean up strack and return
1301 LC99D com 2,s ; toggle drive number seen flag
1302 beq LC978 ; brif we've seen drive number already
1303 lda ,u++ ; get drive number and skip trailing : if leading
1304 subb #2 ; take two characters from string
1305 suba #'0 ; remove ASCII bias
1306 blo LC978 ; brif not a digit
1307 cmpa #3 ; is it in range?
1308 bhi LC978 ; brif not
1309 sta DCDRV ; save drive number
1310 rts
1311 LC9B0 bsr LC973 ; error if no file name yet
1312 ldx #DFLTYP ; point to end of extension buffer
1313 lda #0x20 ; space (for padding extension)
1314 LC9B7 sta ,-x ; insert padding character
1315 cmpx #DEXTBF ; done yet?
1316 bne LC9B7 ; brif not
1317 LC9BE decb ; are we at the end of the string?
1318 beq LC99B ; brif so
1319 lda ,u+ ; get character
1320 cmpa #': ; drive number?
1321 beq LC994 ; brif so
1322 cmpx #DFLTYP ; is extension full?
1323 beq LC978 ; brif so - bad fil ename
1324 bsr LC9D0 ; put character in buffer
1325 bra LC9BE ; process another character
1326 LC9D0 sta ,x+ ; put character in buffer
1327 beq LC978 ; brif NUL - don't allow it (first character NUL is deleted file)
1328 cmpa #'. ; dot?
1329 beq LC978 ; brif not - don't allow extension separator
1330 cmpa #'/ ; ditto for slash
1331 beq LC978
1332 inca ; is if 0xff?
1333 beq LC978 ; brif so - first character 0xff means never used entry
1334 LC9DF rts
1335 ; SAVE command
1336 SAVE cmpa #'M ; is it SAVEM?
1337 lbeq LCF68 ; brif so
1338 bsr LCA33 ; parse file name
1339 ldx ZERO ; set to BASIC program and binary
1340 stx DFLTYP
1341 jsr GETCCH ; is there something after the file name?
1342 beq LCA12 ; brif not
1343 jsr SYNCOMMA ; make sure we have a comma
1344 ldb #'A ; only valid flag is "A" for ASCII
1345 jsr LB26F
1346 bne LC9DF ; brif more stuff follows - error
1347 com DASCFL ; set to ASCII type
1348 bsr LCA04 ; open sequential file for output
1349 clra ; set Z to cause whole program to be listed
1350 jmp LIST ; let LIST do the heavy lifting
1351 LCA04 lda #'O ; output file type
1352 skip2
1353 LCA07 lda #'I ; iput file type
1354 ldb FCBACT ; get number of active FCBs
1355 incb ; bump to system FCB
1356 stb DEVNUM ; use the system FCB
1357 jmp LC48D ; open file and initialize FCB
1358 LCA12 bsr LCA04 ; open file for output
1359 lda #0xff ; send basic file flag
1360 jsr LCC24
1361 ldd VARTAB ; get end of program address
1362 subd TXTTAB ; now we have length of program
1363 jsr LCC24 ; output length MS byte
1364 tfr b,a ; output length LS byte
1365 jsr LCC24
1366 ldx TXTTAB ; point to start of program text
1367 LCA27 lda ,x+ ; output byte from program
1368 jsr LCC24
1369 cmpx VARTAB ; end of program?
1370 bne LCA27 ; brif not
1371 jmp LA42D ; close the file
1372 LCA33 ldx #BASEXT ; point to BAS extension (for basic programs)
1373 jmp LC938 ; parse file name
1374 ; MERGE command
1375 MERGE clra ; run flag: 0 = don't run
1376 ldb #0xff ; merge flag: 0xff = merge
1377 bra LCA50
1378 ; RUN handler
1379 DVEC18 cmpa #'" ; do we have a file name?
1380 lbne XVEC18 ; brif not
1381 lda #2 ; RUN flag - run after loading
1382 bra LCA4F ; load file
1383 ; LOAD command
1384 LOAD cmpa #'M ; is it LOADM?
1385 lbeq LCFC1 ; brif so
1386 clra ; set not to RUN
1387 LCA4F clrb ; set not to MERGE
1388 LCA50 sta DRUNFL ; save RUN flag
1389 stb DMRGFL ; save MERGE flag
1390 bsr LCA33 ; parse file name
1391 jsr GETCCH ; is there anything after the file name?
1392 beq LCA6C ; brif not
1393 jsr SYNCOMMA ; make sure comma
1394 ldb #'R ; make sure the flag is "R"
1395 jsr LB26F
1396 jsr LA5C7 ; error if anything else
1397 lda #3 ; set flags to RUN and not close files
1398 sta DRUNFL
1399 LCA6C bsr LCA07 ; open file for input
1400 lda DASCFL ; is it ASCII?
1401 beq LCA7E ; brif not
1402 tst DMRGFL ; is it merge?
1403 bne LCA7B ; brif so
1404 jsr LAD19 ; do a "NEW" - erase existing program
1405 LCA7B jmp LAC7C ; let immediate mode do the heavy lifting now
1406 LCA7E lda DFLTYP ; get type
1407 ora DMRGFL ; mix with merge flag
1408 lbne LA616 ; if either of the above was nonzero, raise bad file mode
1409 jsr LAD19 ; erase existing program
1410 com DLODFL ; flag that we're loading a program
1411 jsr LCDBC ; get initial character (discard it, should be 0xff)
1412 jsr LCDBC ; get MSB of length
1413 pshs a ; save it
1414 jsr LCDBC ; get LSB of length
1415 tfr a,b ; save length in D
1416 puls a
1417 addd TXTTAB ; add to start of program text
1418 jsr LAC37 ; make sure it fits
1419 ldx TXTTAB ; point to start of program
1420 LCAA4 jsr LC5C4 ; get a character
1421 ldb CINBFL ; EOF?
1422 bne LCAAF ; brif so
1423 sta ,x+ ; save character
1424 bra LCAA4 ; process more
1425 LCAAF clr DLODFL ; clear load flag - no errors
1426 stx VARTAB ; set new end of program
1427 ldb #3 ; make sure the last three bytes were 0
1428 LCAB6 lda ,-x ; do we have a 0?
1429 bne LCABD ; brif not
1430 decb ; done all three?
1431 bne LCAB6 ; brif not
1432 LCABD ldx VARTAB ; get end of program
1433 LCABF stx VARTAB ; save new end of program
1434 clr ,x+ ; blank a byte
1435 decb ; done enough?
1436 bpl LCABF ; brif not
1437 LCAC6 jsr LA42D ; close the file
1438 jsr LAD21 ; clear variables, reset stack, etc.
1439 jsr XVEC18 ; initalize graphics stuff
1440 jsr LACEF ; recalculate line pointers
1441 asr DRUNFL ; are we supposed to close all files?
1442 bcs LCADA ; brif not
1443 jsr LA426 ; close all open files
1444 LCADA asr DRUNFL ; are we supposed to run the program/
1445 lbcs LAD9E ; brif so - launch program
1446 jmp LAC73 ; return to immediate mode
1447 ; EOF handler for main loop
1448 DVEC13 tst DEVNUM ; is it disk file?
1449 bgt LCAC6 ; brif so - run it if required
1450 rts ; return to mainline otherwise
1451 ; Close all files handler
1452 DVEC7 ldb FCBACT ; get number of reserved FCBs
1453 incb ; include system FCB
1454 LCAED pshs b ; save file count
1455 stb DEVNUM ; set device to close
1456 bsr LCB01 ; close it
1457 puls b ; get back file count
1458 decb ; move to next one
1459 bne LCAED ; brif not done all disk files
1460 LCAF8 rts
1461 ; Close one file handler
1462 DVEC8 tst DEVNUM ; is it a disk file?
1463 lble XVEC8 ; brif not
1464 leas 2,s ; don't return to mainline
1465 LCB01 jsr LC744 ; get FCB pointer
1466 clr DEVNUM ; reset device number
1467 LCB06 stx FCBTMP ; save FCB pointer
1468 lda <<FCBTYP,x ; get file type
1469 beq LCAF8 ; brif file isn't open - we don't have to do anything
1470 pshs a ; save file type
1471 clr <<FCBTYP,x ; mark file closed
1472 ldb FCBDRV,x ; tell DSKCON which drive the file is on
1473 stb DCDRV
1474 cmpa #OUTFIL ; output file?
1475 bne LCB31 ; brif not
1476 ldb FCBLFT,x ; get number of characters in output buffer
1477 lda #0x80 ; set pre-saved bit to indicate data already saved
1478 ifeq DISKVER-1
1479 ora FCBCPT,x ; merge with full sector flag
1480 endc
1481 std FCBLST,x ; save number of bytes used in last sector
1482 inc FCBSEC,x ; bump sector counter
1483 ldb FCBCGR,x ; get current granule
1484 jsr LC755 ; point to FAT
1485 sta FAT1,x ; mark FAT data invalid
1486 abx ; add granule offset to pointer
1487 inc FATCON,x ; add one to sector count for last granule (skip control bytes)
1488 ifeq DISKVER
1489 LCB2E bra LCBC3 ; update FAT and directory, write out any final data
1490 else
1491 LCB2E jmp LCBC3 ; update FAT and directory, write out any final data
1492 endc
1493 LCB31 cmpa #RANFIL ; random file?
1494 ifeq DISKVER
1495 bne LCBC3 ; brif not
1496 else
1497 bne LCB2E ; brif not - update FAT and directory for input file
1498 endc
1499 ldd FCBRLN,x ; get record length
1500 ldx FCBBUF,x ; get buffer pointer
1501 leay d,x ; point to end of random file buffer
1502 pshs y,x,b,a ; save pointers and length
1503 ifeq DISKVER-1
1504 leay ,s ; save stack pointer
1505 endc
1506 ldu VARTAB ; get start of variables
1507 LCB41 cmpu ARYTAB ; end of scalars?
1508 beq LCB54 ; brif so
1509 lda 1,u ; get second byte of variable name
1510 leau 2,u ; move past variable name
1511 bpl LCB4E ; brif numeric
1512 bsr LCB76 ; adjust string variable if in random file buffer
1513 LCB4E leau 5,u ; move to next variable entry
1514 bra LCB41 ; process next variable entry
1515 LCB52 puls u ; get address of next array
1516 LCB54 cmpu ARYEND ; end of arrays?
1517 ifeq DISKVER
1518 beq LCB91 ; brif so
1519 else
1520 beq LCB93 ; brif so
1521 endc
1522 tfr u,d ; save array start
1523 addd 2,u ; add length of array
1524 pshs d ; save address of next array
1525 lda 1,u ; is it string?
1526 bpl LCB52 ; brif not - do next array
1527 ldb 4,u ; get number of dimensions
1528 aslb ; two bytes per dimension size
1529 addb #5 ; 5 bytes constant per array header
1530 clra ; zero extend
1531 leau d,u ; point to start of array data
1532 LCB6B cmpu ,s ; end of this array?
1533 beq LCB52 ; brif so
1534 bsr LCB76 ; adjust string variable if in random file buffer
1535 leau 5,u ; move to next entry
1536 bra LCB6B ; process next entry
1537 LCB76 ldx 2,u ; get pointer to start of string
1538 cmpx RNBFAD ; is it above top of random buffer area?
1539 bhs LCB8B ; brif so
1540 ifeq DISKVER
1541 cmpx 4,s ; is it below this file's buffer area?
1542 blo LCB8C ; brif so
1543 cmpx 6,s ; is it above this file's buffer?
1544 else
1545 cmpx 2,y ; is it above start of this file's buffer area?
1546 blo LCB8B ; brif not
1547 cmpx 4,y ; is it below end of this file's buffer area?
1548 endc
1549 blo LCB8C ; brif so - we have to adjust it
1550 tfr x,d ; save pointer in D
1551 ifeq DISKVER
1552 subd 2,s ; adjust pointer down by length of buffer area for this file
1553 else
1554 subd ,y ; adjust pointer down by length of buffer area for this file
1555 endc
1556 std 2,u ; save new start of string
1557 LCB8B rts
1558 LCB8C clr ,u ; mark string empty
1559 clr 2,u ; NULL out string address
1560 clr 3,u
1561 rts
1562 ifeq DISKVER
1563 LCB91 puls a,b,x,u ; clean up stack
1564 else
1565 LCB93 ldb FCBACT ; get number of active files
1566 incb ; include system FCB
1567 LCB97 pshs b ; save files count
1568 jsr LC749 ; point to FCB number in B
1569 lda <<FCBTYP,x ; open as random file?
1570 cmpa #RANFIL
1571 bne LCBAD ; brif not
1572 ldd FCBBUF,x ; get buffer pointer
1573 cmpd 4,y ; is it above this file's buffer?
1574 blo LCBAD ; brif not
1575 subd ,y ; subtract out length for this file's buffer
1576 std FCBBUF,x ; save new buffer area pointer
1577 LCBAD puls b ; get files counter back
1578 decb ; done all?
1579 bne LCB97 ; brif not
1580 puls a,b,x,u ; get back pointers and buffer length
1581 endc
1582 LCBB4 cmpu RNBFAD ; at top of buffers?
1583 beq LCBC0 ; brif so
1584 lda ,u+ ; copy a byte down
1585 sta ,x+
1586 bra LCBB4 ; see if we're done yet
1587 LCBC0 stx RNBFAD ; save new start of free buffer area
1588 LCBC3 jsr LC755 ; point to proper FAT
1589 dec <<FAT0,x ; remove one active file
1590 tst FAT1,x ; new data in FAT image?
1591 beq LCBCF ; brif not
1592 jsr LC71E ; save modified FAT
1593 LCBCF ldx FCBTMP ; get FCB pointer back
1594 puls a ; get file type
1595 cmpa #OUTFIL ; output?
1596 beq LCBDF ; brif so
1597 cmpa #RANFIL ; random?
1598 bne LCB8B ; brif not
1599 lda FCBFLG,x ; doing GET?
1600 beq LCBE9 ; brif so
1601 LCBDF jsr LC763 ; set up track and sector parameters
1602 leau FCBCON,x ; point to data buffer
1603 stu DCBPT
1604 bsr LCC15 ; write out the sector data
1605 LCBE9 lda FCBLST,x ; data pre-saved?
1606 bpl LCB8B ; brif it has already been saved
1607 ldb FCBDIR,x ; get directory number for this file
1608 andb #7 ; 8 entries per sector
1609 lda #DIRLEN ; calculate offset into directory sector
1610 mul
1611 ldu #DBUF0 ; point to global buffer
1612 stu DCBPT ; set DSKCON buffer address
1613 leay d,u ; Y points to directory entry now
1614 ldb FCBDIR,x ; get directory entry number
1615 lsrb ; divide by 8 (gives sector number)
1616 lsrb
1617 lsrb
1618 addb #3 ; first directory sector is 3
1619 stb DSEC ; tell DSKCON
1620 ldd #0x1102 ; set up to read track 17
1621 sta DCTRK
1622 bsr LCC17 ; read directory sector
1623 ldd FCBLST,x ; get number of bytes in last sector
1624 anda #0x7f ; remove pre-saved flag
1625 std DIRLST,y ; update directory entry
1626 LCC15 ldb #3 ; write operation
1627 LCC17 stb DCOPC ; tell DSKCON what to do
1628 jmp LD6F2 ; go read or write sector
1629 ; Generic output handler
1630 DVEC3 tst DEVNUM ; disk file?
1631 lble XVEC3 ; brif not
1632 leas 2,s ; don't return to mainline
1633 LCC24 pshs x,b,a ; save registers
1634 ldx #FCBV1-2 ; point to FCB list (-2 for 1-based file numbers)
1635 ldb DEVNUM ; get device number
1636 aslb ; two bytes per pointer
1637 ldx b,x ; get FCB pointer
1638 ldb ,x ; get file type
1639 cmpb #INPFIL ; input?
1640 beq LCC6A ; brif so - bail
1641 cmpa #0x0d ; carriage return?
1642 bne LCC3A ; brif so
1643 clr FCBPOS,x ; reset print position if CR
1644 LCC3A cmpa #0x20 ; control code?
1645 blo LCC40 ; brif so
1646 inc FCBPOS,x ; bump print position if printing character
1647 LCC40 cmpb #RANFIL ; random file?
1648 bne LCC5E ; brif not
1649 ldd FCBPUT,x ; get put pointer
1650 addd #1 ; bump it
1651 cmpd FCBRLN,x ; did we overflow the record?
1652 lbhi LCDCB ; brif so - raise error
1653 std FCBPUT,x ; save updated pointer
1654 ldx FCBBUF,x ; get buffer pointer
1655 leax d,x ; add in offset
1656 puls a ; get back output character
1657 sta -1,x ; save in buffer (-1 because we already bumped pointer)
1658 puls b,x,pc ; restore registers and return
1659 LCC5E inc FCBLFT,x ; bump character count
1660 ldb FCBLFT,x ; did we max out a sector?
1661 beq LCC6C ; brif so
1662 abx ; add offset into sector
1663 sta FCBCON-1,x ; save output character in buffer, offset past control structure
1664 LCC6A puls a,b,x,pc ; restore registers and return
1665 LCC6C pshs u,y ; save registers
1666 sta SECLEN+FCBCON-1,x ; save last character in buffer
1667 ifeq DISKVER
1668 jsr LC685
1669 endc
1670 ldb FCBDRV,x ; tell DSKCON which drive
1671 stb DCDRV
1672 inc FCBSEC,x ; bump sector counter (in granule)
1673 jsr LCBDF ; write file buffer to disk
1674 leay ,x ; save FCB pointer
1675 ldb FCBCGR,x ; get granule number
1676 jsr LC755 ; get pointer to FAT
1677 abx ; offset into granule data
1678 leau FATCON,x ; now U points to granule data (offset past control structure)
1679 lda FCBSEC,y ; get current sector offset
1680 cmpa #9 ; end of granule?
1681 blo LCC99 ; brif not
1682 ifeq DISKVER-1
1683 dec FCBSEC,y ; decrement sector number and bump error flag in case error occurs
1684 inc FCBCPT,y
1685 else
1686 clr FCBSEC,y
1687 endc
1688 jsr LC7BF ; allocate granule
1689 ifeq DISKVER-1
1690 clr FCBSEC,y ; clear sector number
1691 clr FCBCPT,y ; clear error flag - disk not full
1692 endc
1693 sta FCBCGR,y ; save new granule in FCB
1694 skip2
1695 LCC99 ora #0xc0 ; mark granule as end of file
1696 sta ,u ; save in granule map
1697 ifeq DISKVER-1
1698 leax ,y ; get back FCB pointer
1699 jsr LC685 ; bump record number
1700 endc
1701 jsr LC5A9 ; update FAT
1702 puls y,u ; restore registers
1703 puls a,b,x,pc ; restore registers and return
1704 ; DIR command
1705 DIR jsr LD24F ; parse drive number
1706 jsr LC79D ; fetch FAT for drive
1707 jsr LB958 ; do a linefeed
1708 ldd #0x1102 ; set up to read track 17
1709 sta DCTRK
1710 stb DCOPC
1711 ldb #3 ; start at sector 3 for the directory
1712 LCCBB stb DSEC ; set sector to read
1713 ldx #DBUF0 ; use the global sector buffer
1714 stx DCBPT
1715 jsr LD6F2 ; read directory sector
1716 LCCC5 puls u ; do some stack games due to break check requirements
1717 jsr LA549
1718 pshs u
1719 lda ,x ; is this entry used?
1720 beq LCD08 ; brif not
1721 coma ; is it the start of never entries?
1722 beq LCD17 ; brif so - we're done
1723 pshs x ; save directory data pointer
1724 ldb #8 ; print out 8 characters for the filename
1725 jsr LB9A2 ; display file name
1726 bsr LCD1B ; put a blank
1727 ldb #3 ; show 3 characters in extension
1728 jsr LB9A2 ; display extension
1729 bsr LCD1B ; put a blank
1730 ldb <<0,x ; get file type
1731 cmpb #10 ; is it one digit?
1732 bhs LCCEB ; brif so
1733 bsr LCD1B ; put another blank
1734 LCCEB clra ; zero extend type
1735 jsr LBDCC ; show file type
1736 bsr LCD1B ; another blank
1737 ldx ,s ; get directory entry back
1738 lda #'B ; set to binary
1739 adda DIRASC,x ; add ASCII flag - will subtract 1 (to A) if ASCII
1740 bsr LCD18 ; show character and a blank
1741 ldb DIRGRN,x ; point to first granule in file
1742 bsr LCD1E ; count granules
1743 tfr a,b ; zero extend into D
1744 clra
1745 jsr LBDCC ; show granule count
1746 jsr LB958 ; do a newline
1747 puls x ; get back directory pointer
1748 LCD08 leax DIRLEN,x ; move to next entry
1749 cmpx #DBUF0+SECLEN ; end of sector?
1750 blo LCCC5 ; brif not
1751 ldb DSEC ; get sector number
1752 incb ; move to next one
1753 cmpb #SECMAX ; end of track?
1754 bls LCCBB ; brif not
1755 LCD17 rts
1756 LCD18 jsr PUTCHR ; display character
1757 LCD1B jmp LB9AC ; display a space
1758 ; Count granule chain starting at granule number in B
1759 LCD1E jsr LC755 ; get FAT pointer
1760 leau FATCON,x ; point past control structure
1761 clra ; reset count to 0
1762 LCD24 inca ; bump granule count
1763 cmpa #GRANMX ; at maximum size of disk?
1764 lbhi LC653 ; do FS error if so
1765 leax ,u ; point to base FAT data
1766 abx ; offset to granule number
1767 ldb ,x ; get next granule pointer
1768 cmpb #0xc0 ; end of file marker?
1769 blo LCD24 ; brif not
1770 rts
1771 ; INPUT handler; this whole mess is requried because the disk data format varies from that used
1772 ; by tape files.
1773 DVEC10 tst DEVNUM ; are we reading from a disk file?
1774 ble LCD97 ; brif not
1775 ldx #LB069 ; change return address to skip ? prompt
1776 stx ,s
1777 ldx #LINBUF+1 ; point to input buffer
1778 ldb #', ; set item separator to ,
1779 stb CHARAC
1780 lda VALTYP ; get type wanted
1781 bne LCD4B ; brif string
1782 ldb #0x20 ; space is the numeric delimiter
1783 LCD4B bsr LCDBC ; fetch input character
1784 cmpa #0x20 ; space?
1785 beq LCD4B ; brif so
1786 cmpa #'" ; quote?
1787 bne LCD5F ; brif not
1788 cmpb #', ; delim is ,?
1789 bne LCD5F ; brif not - numeric
1790 tfr a,b ; save quote as search character
1791 stb CHARAC
1792 bra LCD81 ; save quote as first item in buffer
1793 LCD5F cmpb #'" ; string value?
1794 beq LCD74 ; brif so
1795 cmpa #0x0d ; end of line?
1796 bne LCD74 ; brif not
1797 cmpx #LINBUF+1 ; at start of buffer?
1798 beq LCDB0 ; brif so - check for LF
1799 lda -1,x ; get back input character
1800 cmpa #0x0a ; was it LF?
1801 bne LCDB0 ; brif not
1802 lda #0x0d ; restore CR as input character
1803 LCD74 tsta ; NUL?
1804 beq LCD8E ; brif so - ignore it
1805 cmpa CHARAC ; hit a delimiter?
1806 beq LCD98 ; brif so
1807 pshs b ; does it match the other delimiter?
1808 cmpa ,s+
1809 beq LCD98 ; brif so
1810 LCD81 sta ,x+ ; save character in buffer
1811 cmpx #LINBUF+LBUFMX ; end of buffer?
1812 bne LCD8E ; brif not
1813 bsr LCDD0 ; fetch character
1814 bne LCD92 ; brif buffer empty
1815 bra LCDAC ; check for CR/CRLF
1816 LCD8E bsr LCDD0 ; get input character
1817 beq LCD5F ; brif we have something
1818 LCD92 clr ,x ; put NUL at end of buffer
1819 ldx #LINBUF ; point to input buffer
1820 LCD97 rts
1821 LCD98 cmpa #'" ; quote?
1822 beq LCDA0 ; brif so
1823 cmpa #0x20 ; space?
1824 bne LCD92 ; brif not
1825 LCDA0 bsr LCDD0 ; get character
1826 bne LCD92 ; brif end
1827 cmpa #0x20 ; space?
1828 beq LCDA0 ; brif so - skip it
1829 cmpa #', ; item separator?
1830 beq LCD92 ; brif so - done
1831 LCDAC cmpa #0x0d ; carriage return?
1832 bne LCDB8 ; brif not
1833 LCDB0 bsr LCDD0 ; fetch character
1834 bne LCD92 ; brif end
1835 cmpa #0x0a ; line feed?
1836 beq LCD92 ; brif so - skip it
1837 LCDB8 bsr LCDD6 ; unget character
1838 bra LCD92 ; handle exit
1839 LCDBC bsr LCDD0 ; fetch character
1840 beq LCDD5 ; brif not end of file
1841 jsr LC744 ; point to FCB
1842 ldb <<FCBTYP,x ; get file type
1843 cmpb #RANFIL ; random file?
1844 lbne LC352 ; brif not - do input past end of file
1845 LCDCB ldb #2*37 ; code for input past end of record
1846 jmp LAC46 ; raise error
1847 LCDD0 jsr LA176 ; read character
1848 tst CINBFL ; set Z if not EOF
1849 LCDD5 rts
1850 LCDD6 pshs x,b ; save registers
1851 jsr LC744 ; point to FCB
1852 ldb <<FCBTYP,x ; random file?
1853 cmpb #RANFIL
1854 bne LCDEC ; brif not
1855 ldd FCBGET,x ; get input pointer
1856 subd #1 ; move it back (no error check!)
1857 std FCBGET,x ; save new pointer
1858 puls b,x,pc ; restore registers and return
1859 LCDEC sta FCBCDT,x ; save unget character
1860 com FCBCFL,x ; flag that we have an ungot character
1861 puls b,x,pc ; restore registers and return
1862 ; CVN function
1863 CVN jsr LB654 ; evaluate argument string
1864 cmpb #5 ; is it at least 5 bytes (packed FP number)?
1865 lblo LB44A ; brif not - raise error
1866 clr VALTYP ; result is numeric
1867 jmp LBC14 ; unpack string into return value
1868 ; MKN$ function
1869 MKN jsr LB143 ; make sure we have a number
1870 ldb #5 ; string will be 5 bytes long
1871 jsr LB50F ; reserve space for it
1872 jsr LBC35 ; pack argument into the string
1873 jmp LB69B ; return the newly created string
1874 ; LOC function
1875 LOC bsr LCE19 ; get pointer to correct FCB
1876 ldd FCBREC,x ; get record number (random file) or sector counter
1877 ifeq DISKVER
1878 LCE14 jmp GIVABF ; return result as integer
1879 else
1880 LCE14 std FPA0+2 ; return result as an unsigned integer
1881 jmp L880E
1882 endc
1883 ; Evaluate device number, set print parameters, and point to FCB
1884 LCE19 lda DEVNUM ; save current device number
1885 pshs a
1886 jsr LB143 ; make sure we have a number
1887 jsr LA5AE ; check device and set print params
1888 tst DEVNUM ; is it a disk file?
1889 lble LB44A ; brif not
1890 jsr LC744 ; point to FCB
1891 puls a ; restore original device number
1892 sta DEVNUM
1893 tst <<FCBTYP,x ; is file open?
1894 lbeq LA3FB ; brif not, do NO error
1895 rts
1896 ; LOF function
1897 LOF bsr LCE19 ; point to FCB
1898 lda FCBDRV,x ; tell DSKCON the drive number
1899 sta DCDRV
1900 ldb FCBFGR,x ; get first granule of file
1901 pshs x ; save FCB pointer
1902 jsr LCD1E ; count granules in file
1903 deca ; subtract out last granule
1904 andb #0x3f ; get number of sectors in last granule
1905 pshs b ; save it
1906 tfr a,b ; zero extend granule number to D
1907 clra
1908 jsr LC779 ; multiply by 9 for total sector count
1909 addb ,s+ ; add in sectors in last granule
1910 adca #0
1911 puls x ; get back FCB pointer
1912 pshs a ; temp save
1913 lda <<FCBTYP,x ; is it random file?
1914 cmpa #RANFIL
1915 puls a ; restore register
1916 bne LCE14 ; brif not random file - return number of sectors
1917 pshs x ; save FCB pointer
1918 subd ZERO ; "tstd"
1919 beq LCE68 ; brif file is empty
1920 subd #1 ; don't count last sector as fully used
1921 LCE68 bsr LCE14 ; put D into FPA0
1922 ldb FP0EXP ; is it 0?
1923 beq LCE72 ; brif so
1924 addb #8 ; multiply by 256
1925 stb FP0EXP
1926 LCE72 jsr LBC5F ; save result in FPA1
1927 ldx ,s ; get back FCB pointer
1928 ldd FCBLST,x ; get number of bytes in last sector
1929 anda #0x7f ; clear out pre-save flag
1930 bsr LCE14 ; stuff that number in FPA0
1931 clr RESSGN ; result will be positive
1932 lda FP1EXP ; get exponents
1933 ldb FP0EXP
1934 jsr LB9C5 ; add number of bytes in last sector
1935 jsr LBC5F ; save total in FPA1
1936 puls x ; get FCB
1937 ldd FCBRLN,x ; get record length
1938 bsr LCE14 ; turn it into a FP number
1939 clr RESSGN ; make result positive
1940 lda FP1EXP ; get exponents
1941 ldb FP0EXP
1942 jsr LBB91 ; divide total by record size
1943 jmp INT ; return the result as an integer
1944 ; FREE function
1945 FREE jsr LB143 ; make sure we have a number
1946 jsr LB70E ; get value in B
1947 cmpb #3 ; valid drive?
1948 lbhi LA61F ; brif not
1949 stb DCDRV ; set drive
1950 jsr LC79D ; read FAT
1951 jsr LC755 ; point to FAT
1952 leax FATCON,x ; point to actual granule data
1953 clr ,-s ; initialize free count
1954 ldb #GRANMX ; total granules to check
1955 LCEB6 lda ,x+ ; get granule data
1956 coma ; is it free?
1957 bne LCEBD ; brif not
1958 inc ,s ; bump free count
1959 LCEBD decb ; checked them all?
1960 bne LCEB6 ; brif not
1961 puls b ; get free count
1962 jmp LB4F3 ; return free count
1963 ; DRIVE command
1964 DRIVE jsr EVALEXPB ; evaluate drive number to B
1965 cmpb #3 ; valid?
1966 lbhi LA61F ; brif not
1967 stb DEFDRV ; set default drive
1968 rts
1969 ; Expression evaluation handler; this is needed so we can move strings into string space
1970 ; if regular assignment to a FIELDed string is done. There really isn't a better place to
1971 ; intercept this, unfortunately.
1972 DVEC15 lda 4,s ; is it end of operation?
1973 bne LCEE9 ; brif not
1974 ldx 5,s ; are we comming from LET?
1975 cmpx #LAF9A
1976 bne LCEE9 ; brif not
1977 ldx 2,s
1978 cmpx #LB166
1979 bne LCEE9 ; and brif not again
1980 ldx #LCEEC ; install intercept for LET
1981 stx 5,s
1982 LCEE9 jmp XVEC15 ; let ECB do its thing
1983 ; LET modifier
1984 LCEEC puls a ; get variable type
1985 rora ; set C if string
1986 jsr LB148 ; make sure things match
1987 lbeq LBC33 ; brif numeric - we can go back to mainline
1988 ldx FPA0+2 ; get string descriptor
1989 ldd 2,x ; get data pointer
1990 cmpd #DFLBUF ; is it below random buffers?
1991 blo LCF07 ; brif so
1992 subd FCBADR ; is it within the random buffers?
1993 lblo LAFB1 ; brif so - move string to string space
1994 LCF07 jmp LAFA4 ; return to mainline code
1995 ; ECB interpretation handler intercept; the PMODE intercept fixes a stupid usage of a constant 6 for the
1996 ; start of graphics memory in PMODE. The DLOAD intercept fixes the problem where DLOADM couldn't be
1997 ; detected due to A being clobbered before it was checked. Both of those bugs were fixed in ECB 1.1.
1998 DXCVEC cmpa #0xca ; DLOAD?
1999 beq LCF2A ; brif so
2000 cmpa #0xc8 ; PMODE?
2001 lbne L813C ; brif not - return to ECB's handler
2002 jsr GETNCH ; get input character
2003 cmpa #', ; no PMODE argument?
2004 lbeq L9650 ; brif not - return to mainline
2005 jsr EVALEXPB ; evaluate PMODE number
2006 cmpb #4 ; valid?
2007 lbhi LB44A ; brif not
2008 lda GRPRAM ; fetch start of grahpics memory (work around usage of constant 6 in ECB 1.0)
2009 jmp L962E ; return to mainline PMODE
2010 LCF2A jsr LA429 ; close files
2011 jsr GETNCH ; fetch input character
2012 jmp L8C1B ; return to mainlnie
2013 ; ECB function interpetation handler intercept; this is needed to patch into the POS() function.
2014 DXIVEC cmpb #(0x9a-0x80)*2 ; is it POS?
2015 lbne L8168 ; brif not - return to ECB mainline
2016 jsr LB262 ; evaluate argument
2017 lda DEVNUM ; get device number
2018 pshs a ; save it
2019 jsr LA5AE ; evaluate device number
2020 jsr LA406 ; make sure it's open
2021 tst DEVNUM ; disk file?
2022 ble LCF5C ; brif not
2023 jsr LC744 ; point to FCB
2024 ldb <<FCBTYP,x ; get file type
2025 cmpb #RANFIL ; random file?
2026 bne LCF5C ; brif not
2027 puls a ; get back saved device number
2028 sta DEVNUM
2029 ldd FCBPUT,x ; get "put" position
2030 jmp GIVABF ; return that as the position
2031 LCF5C jsr LA35F ; set print parameters
2032 puls a ; restore device number
2033 sta DEVNUM
2034 ldb DEVPOS ; get print position
2035 jmp LB4F3 ; return B as unsigned
2036 ; SAVEM command (comes from SAVE command)
2037 LCF68 jsr GETNCH ; eat the "M"
2038 bsr LCFBB ; parse filename
2039 jsr L836C ; evaluate start address
2040 jsr L836C ; evaluate end address
2041 cmpx 2,s ; is start > end?
2042 lblo LB44A ; brif so - throw an error
2043 jsr L836C ; evaluate execution address
2044 jsr LA5C7 ; make sure there's nothing more
2045 ldd #0x200 ; file type 2 (M/L) and binary
2046 std DFLTYP
2047 jsr LCA04 ; open file for output
2048 clra ; write preamble header
2049 bsr LCFB5
2050 ldd 2,s ; get end address
2051 subd 4,s ; subtract start - gets length
2052 addd #1 ; length is inclusive
2053 tfr d,y ; set data counter
2054 bsr LCFB3 ; output the length of the block
2055 ldd 4,s ; output the load address
2056 bsr LCFB3
2057 ldx 4,s ; point to start of block
2058 LCF9B lda ,x+ ; grab output byte
2059 jsr LCC24 ; write it
2060 leay -1,y ; done yet?
2061 bne LCF9B ; brif not
2062 lda #0xff ; write header for postamble
2063 bsr LCFB5
2064 clra ; write dummy 16 bits (would be block length)
2065 clrb
2066 bsr LCFB3
2067 puls d,x,y ; get back execution address and clean stack
2068 bsr LCFB3 ; write out execution address
2069 jmp LA42D ; close file
2070 LCFB3 bsr LCFB5 ; write MSB of word; fall through for LSB
2071 LCFB5 jsr LCC24 ; write byte out
2072 exg a,b ; swap bytes in word
2073 rts
2074 LCFBB ldx #BINEXT ; set default extension to "BIN"
2075 jmp LC938 ; parse filename
2076 ; LOADM command (comes from LOAD command)
2077 LCFC1 jsr GETNCH ; eat the "M"
2078 bsr LCFBB ; parse filename
2079 jsr LCA07 ; open file for input
2080 ldd DFLTYP ; get type of file
2081 subd #0x200 ; is it M/L and binary?
2082 lbne LA616 ; bad file mode if not
2083 ldx ZERO ; set default offset value
2084 jsr GETCCH ; is there a load offset?
2085 beq LCFDE ; brif not
2086 jsr SYNCOMMA ; insist on a comma
2087 jsr LB73D ; evaluate offset to X
2088 LCFDE stx VD3 ; save offset
2089 jsr LA5C7 ; insist on end of statement
2090 LCFE3 jsr LCDBC ; read "amble" header
2091 pshs a ; save "amble" type
2092 bsr LD013 ; read block length
2093 tfr d,y ; save it (in counter)
2094 bsr LD013 ; read block address
2095 addd VD3 ; add load offset
2096 std EXECJP ; set execution address
2097 tfr d,x ; put it also in a pointer
2098 lda ,s+ ; set flags on "amble" type
2099 lbne LA42D ; brif postamble - stop reading
2100 LCFFA jsr LC5C4 ; read a byte
2101 ldb CINBFL ; EOF?
2102 beq LD004 ; brif not
2103 jmp LC352 ; raise "IE" error
2104 LD004 sta ,x ; save byte in memory
2105 cmpa ,x+ ; does the byte match?
2106 beq LD00D ; brif so
2107 jmp LD709 ; bad store - throw I/O error
2108 LD00D leay -1,y ; done whole block?
2109 bne LCFFA ; brif not
2110 bra LCFE3 ; process another "amble"
2111 LD013 bsr LD015 ; read MSB then fall through for LSB
2112 LD015 jsr LCDBC ; read a byte from the file
2113 exg a,b ; swap bytes in word
2114 rts
2115 ; RENAME command
2116 RENAME ldx CHARAD ; get input pointer
2117 pshs x ; save it
2118 bsr LD056 ; evaluate source file name
2119 lda DCDRV ; save drive for first file
2120 pshs a
2121 bsr LD051 ; evaluate TO and destination file
2122 puls a ; get back original drive number
2123 cmpa DCDRV ; does it match?
2124 lbne LB44A ; brif not - we can't rename across drives
2125 bsr LD059 ; make sure new file does not already exist
2126 puls x ; get back input pointer
2127 stx CHARAD
2128 bsr LD056 ; re-evaluate source file
2129 jsr LC68C ; find the source file
2130 jsr LC6E5 ; throw error if not found
2131 bsr LD051 ; evaluate destination file name
2132 ldx #DNAMBF ; point to destinatoin file name
2133 ldu V974 ; point to directory entry
2134 ldb #11 ; 8 characters file name and 3 characters extension
2135 jsr LA59A ; replace file name
2136 ldb #3 ; operation code for write
2137 stb DCOPC
2138 jmp LD6F2 ; write updated directory sector
2139 LD051 ldb #0xa5 ; insist on "TO"
2140 jsr LB26F
2141 LD056 jmp LC935 ; evaluate file name with default blank extension
2142 LD059 jsr LC68C ; find file
2143 ldb #33*2 ; code for already exists
2144 tst V973 ; does it exist?
2145 lbne LAC46 ; brif so - raise error
2146 rts
2147 ; WRITE command
2148 WRITE lbeq LB958 ; do CR if end of statement
2149 bsr LD06F ; write an item list
2150 clr DEVNUM ; reset device to screen
2151 LD06E rts
2152 LD06F cmpa #'# ; device number?
2153 bne LD082 ; brif not
2154 jsr LA5A5 ; evaluate device number
2155 jsr LA406 ; check for output
2156 jsr GETCCH ; end of statement?
2157 lbeq LB958 ; brif so - do newline
2158 LD07F jsr SYNCOMMA ; need a comma after device
2159 LD082 jsr LB156 ; evaluate expression
2160 lda VALTYP ; number or string?
2161 bne LD0A7 ; brif string
2162 jsr LBDD9 ; convert number to strng
2163 jsr LB516 ; stash it as the current value
2164 jsr LB99F ; output the string
2165 LD092 jsr GETCCH ; is there more?
2166 lbeq LB958 ; brif not - do newline
2167 lda #', ; comma for non-tape separator
2168 jsr LA35F ; set print parameters
2169 tst PRTDEV ; tape?
2170 beq LD0A3 ; brif not
2171 lda #0x0d ; carriage return for tape separator
2172 LD0A3 bsr LD0B9 ; send separator
2173 bra LD07F ; process another item
2174 LD0A7 bsr LD0B0 ; print leading string delimiter
2175 jsr LB99F ; print string
2176 bsr LD0B0 ; print ending string delimiter
2177 bra LD092 ; handle separator or next item
2178 LD0B0 jsr LA35F ; set print parameters
2179 tst PRTDEV ; tape?
2180 bne LD06E ; brif so
2181 lda #'" ; string delimiter
2182 LD0B9 jmp PUTCHR ; send character out
2183 ; FIELD command
2184 FIELD jsr LC82E ; evaluate device number and make sure it's a random file
2185 clra ; clear total field length counter
2186 clrb
2187 pshs x,b,a ; save field length and FCB pointer
2188 LD0C3 jsr GETCCH ; are we at the end of the statement?
2189 bne LD0C9 ; brif not
2190 puls a,b,x,pc ; clean up stack and return
2191 LD0C9 jsr LB738 ; evaluate comma and expression
2192 pshs x,b ; save field length (B) and make a hole for a temp
2193 clra ; zero extend length
2194 addd 3,s ; add in current accumulated size
2195 bcs LD0DA ; brif we overflowed
2196 ldx 5,s ; point to FCB
2197 cmpd FCBRLN,x ; have we overflowed the record?
2198 bls LD0DF ; brif not
2199 LD0DA ldb #34*2 ; code for field overflow
2200 jmp LAC46 ; raise error
2201 LD0DF ldu 3,s ; get old accumulated length
2202 std 3,s ; save new accumulated length
2203 ldd FCBBUF,x ; get start of random buffer
2204 leau d,u ; now U is the start of the field in the buffer
2205 stu 1,s ; save it so we can set string descriptor
2206 ldb #0xff ; insist on two byte "AS" token
2207 jsr LB26F
2208 ldb #0xa7
2209 jsr LB26F
2210 jsr LB357 ; evaluate variable
2211 jsr LB146 ; error if it's a number
2212 puls b,u ; get back field length and buffer address
2213 stb ,x ; put those in the string descriptor
2214 stu 2,x
2215 bra LD0C3 ; look for another entry
2216 ; RSET command
2217 RSET skip1lda ; set nonzero for right justify and fall through
2218 ; LSET command
2219 LSET clra ; set zero to flag left justify
2220 pshs a ; save justification type
2221 jsr LB357 ; evaluate variable
2222 jsr LB146 ; make sure it's a string
2223 pshs x ; save descriptor address
2224 ldx 2,x ; get address of string data
2225 cmpx #DFLBUF ; is it below random buffer area?
2226 blo LD119 ; brif below - throw error
2227 cmpx FCBADR ; is it above the random buffer area?
2228 blo LD11E ; brif not - it's good
2229 LD119 ldb #2*35 ; code for "set to non-fielded string"
2230 jmp LAC46 ; raise error
2231 LD11E ldb #0xb3 ; insist on =
2232 jsr LB26F
2233 jsr L8748 ; evaluate string expression; return details
2234 puls y ; get back destination descriptor pointer
2235 lda ,y ; get length of field string
2236 beq LD15A ; brif empty destination
2237 pshs b ; save length of new string
2238 ldb #0x20 ; pad characteris space
2239 ldu 2,y ; point to destination string
2240 LD132 stb ,u+ ; blank out string
2241 deca ; done yet?
2242 bne LD132 ; brif not
2243 ldb ,s+ ; get length of data string
2244 beq LD15A ; brif that one is NULL
2245 cmpb ,y ; is data string smaller than destination?
2246 blo LD143 ; brif not
2247 ldb ,y ; get length of destination string as the copy length
2248 clr ,s ; we'll do left justify if string is longer
2249 LD143 ldu 2,y ; get address of the destination
2250 tst ,s+ ; left or right justify?
2251 beq LD157 ; brif left set
2252 pshs b ; save number of bytes to move into field string
2253 clra ; get negation of that in D (do -DLEN+FLEN)
2254 negb
2255 sbca #0
2256 addb ,y ; then add string length of destination to it
2257 adca #0
2258 leau d,u ; now U points to destination offset
2259 puls b ; get back destination size
2260 LD157 jmp LA59A ; copy data and return
2261 LD15A puls a,pc ; clean up stack and return
2262 ; FILES command
2263 FILES jsr L95AC ; reset video display
2264 ldd FCBADR ; get current size of buffer space
2265 subd #DFLBUF
2266 pshs d ; save it as the default size
2267 ldb FCBACT ; get number of available disk files
2268 pshs b ; save it as the default number
2269 jsr GETCCH ; get input character
2270 cmpa #', ; is numer of files specified?
2271 beq LD181 ; brif not
2272 jsr EVALEXPB ; evaluate the number of files wanted
2273 cmpb #15 ; we only allow 15
2274 lbhi LB44A ; raise error if too many
2275 stb ,s ; save number of FCBs to allocate
2276 jsr GETCCH ; see what's after the number
2277 beq LD189 ; brif no buffer size specified
2278 LD181 jsr SYNCOMMA ; insist on a comma
2279 jsr LB3E6 ; evaluate buffer size
2280 ifeq DISKVER
2281 addd #1
2282 endc
2283 std 1,s ; save buffer size
2284 LD189 jsr DVEC7 ; close all disk files
2285 ldb ,s ; get number of files
2286 pshs b ; initialize the file number count
2287 ldd #DFLBUF ; point to start of random buffers
2288 addd 2,s ; add in size requested for buffer space
2289 bcs LD208 ; raise error if we carry
2290 std 2,s ; save start of FCBs
2291 LD199 addd #FCBLEN ; add size of one FCB
2292 bcs LD208 ; brif we overflowed
2293 dec ,s ; added on for all files?
2294 bpl LD199 ; brif not yet (BPL so we set up the system one as well)
2295 tstb ; are we at an even page boundary?
2296 ifeq DISKVER
2297 beq LD1AF ; brif so
2298 else
2299 beq LD1A8 ; brif so
2300 endc
2301 inca ; round up
2302 beq LD208 ; brif we overflowed
2303 ifeq DISKVER-1
2304 LD1A8 bita #1 ; on an even 512 byte boundary?
2305 beq LD1AF ; brif so
2306 inca ; round up
2307 beq LD208 ; brif we overflowed
2308 endc
2309 LD1AF sta ,s ; save MSB of graphics memory
2310 ldd VARTAB ; get end of program
2311 suba GRPRAM ; subtract out start of graphics (D is now size of program and graphics)
2312 adda ,s ; add in the new start of graphics
2313 bcs LD208 ; brif overflow
2314 tfr d,x ; save new top of program
2315 inca ; add some extra room for the stack
2316 beq LD208 ; brif overflow
2317 cmpd FRETOP ; does it fit in memory?
2318 bhs LD208 ; brif not
2319 deca ; restore actual top of program
2320 subd VARTAB ; get difference compared to the original top of program
2321 addd TXTTAB ; add that to the program start
2322 tfr d,y ; now Y is the new start of the program
2323 lda ,s ; get back start of graphics memory
2324 suba GRPRAM ; this gives difference between old graphics start and new grahpics start
2325 tfr a,b ; we need this twice
2326 adda BEGGRP ; set new start of active page
2327 sta BEGGRP
2328 addb ENDGRP ; set new end of active page
2329 stb ENDGRP
2330 puls a,b,u ; get back graphics start, number of files, and start of buffers
2331 sta GRPRAM ; set graphics memory start
2332 stb FCBACT ; set number of active FCBs
2333 stu FCBADR ; set start of FCBs
2334 ifeq DISKVER-1
2335 lda CURLIN ; in immediate mode?
2336 inca
2337 beq LD1EF ; brif so
2338 tfr y,d ; calculate how much the program is moving
2339 subd TXTTAB
2340 addd CHARAD ; adjust input pointer for the change
2341 std CHARAD
2342 endc
2343 LD1EF ldu VARTAB ; get old end of program
2344 stx VARTAB ; save new end of program
2345 cmpu VARTAB ; which way did it move?
2346 bhi LD20B ; brif it moved up
2347 LD1F8 lda ,-u ; move a byte down
2348 sta ,-x
2349 cmpu TXTTAB ; at start?
2350 bne LD1F8 ; brif not
2351 sty TXTTAB ; set new start of program
2352 clr -1,y ; make sure there's a NUL before the program
2353 bra LD21B ; clean up
2354 LD208 jmp LAC44 ; raise OM error
2355 LD20B ldu TXTTAB ; get old start of program
2356 sty TXTTAB ; save new start of program
2357 clr -1,y ; make sure there's a NUL before the program
2358 LD212 lda ,u+ ; move a byte up
2359 sta ,y+
2360 cmpy VARTAB ; at end yet?
2361 bne LD212 ; brif not
2362 LD21B ldu #FCBV1 ; point to FCB pointers
2363 ldx FCBADR ; point to start of FCBs
2364 clrb ; file counter
2365 LD222 stx ,u++ ; set FCB pointer
2366 clr <<FCBTYP,x ; mark FCB as closed
2367 leax FCBLEN,x ; point to next FCB
2368 incb ; bump file counter
2369 cmpb FCBACT ; do we have enough of them yet?
2370 bls LD222 ; brif not (BLS so we include system FCB)
2371 jmp L96CB ; fix up line pointers, etc.
2372 ; UNLOAD command
2373 UNLOAD bsr LD24F ; get drive number
2374 clrb ; clear file counter
2375 LD236 incb ; bump file counter
2376 jsr LC749 ; point to FCB
2377 beq LD249 ; brif file not open
2378 lda FCBDRV,x ; is it on the right drive?
2379 cmpa DCDRV
2380 bne LD249 ; brif not
2381 pshs b ; save file counter
2382 jsr LCB06 ; close the file
2383 puls b ; restore file counter
2384 LD249 cmpb FCBACT ; done all files?
2385 bls LD236 ; brif not (includes system FCB)
2386 rts
2387 ; Parse drive number; use default if none given
2388 LD24F ldb DEFDRV ; set default drive
2389 jsr GETCCH ; is there something there?
2390 beq LD25F ; brif not
2391 LD256 jsr EVALEXPB ; evaluate drive number
2392 cmpb #3 ; valid?
2393 lbhi LA61F ; brif not
2394 LD25F stb DCDRV ; set drive number
2395 rts
2396 ; BACKUP command
2397 BACKUP lbeq LA61F ; raise error if no drive numbers
2398 jsr L95AC ; reset display
2399 jsr LD256 ; get source drive number
2400 stb DBUF0+255 ; save it (we're going to put our stack in DBUF0)
2401 jsr GETCCH ; is there something else?
2402 beq LD27B ; brif not
2403 ldb #0xa5 ; insist on TO
2404 jsr LB26F
2405 jsr LD256 ; fetch destination drive
2406 LD27B lds #DBUF0+255 ; put the stack somewhere safe (source drive number already there)
2407 pshs b ; save destination drive number
2408 jsr LA5C7 ; bail of there's more
2409 jsr DVEC7 ; close files
2410 clr ,-s ; initialize track counter
2411 ldx #DFLBUF-1 ; point to start of the heap
2412 LD28C inc ,s ; bump track counter
2413 leax SECMAX*SECLEN,x ; add a whole track to the count
2414 cmpx MEMSIZ ; does it fit in memory?
2415 bls LD28C ; brif so
2416 dec ,s ; decrement track counter
2417 lbeq LAC44 ; error if less than one track memory available
2418 lda #TRKMAX ; get maximum number of tracks
2419 clrb ; set tracks copied to 0
2420 pshs a,b ; save track counters
2421 com DRESFL ; force a "reset" of the disk system
2422 LD2A4 clrb ; initialize write counter
2423 LD2A5 incb ; add one to track counter
2424 dec ,s ; whole disk done?
2425 beq LD2AE ; brif not
2426 cmpb 2,s ; will it fit in memory?
2427 bne LD2A5 ; brif so
2428 LD2AE stb TMPLOC ; save number of tracks to copy
2429 ldb 4,s ; get source drive number
2430 bsr LD2FC ; read TMPLOC tracks
2431 lda #0xff ; set source/dest flag to dest
2432 jsr LD322 ; show prompt if needed
2433 ldb 3,s ; get destination drive
2434 bsr LD2FF ; write TMPLOC tracks
2435 tst ,s ; is there anything left?
2436 beq LD2CD ; brif not - we're done
2437 clra ; set source/desetination to source
2438 jsr LD322 ; show prompt
2439 ldb 1,s ; get tracks written
2440 addb TMPLOC ; account for the ones we just wrote
2441 stb 1,s ; save new written counter
2442 bra LD2A4 ; go copy some more tracks
2443 LD2CD bsr LD2D2 ; check for re-init
2444 jmp LAC73 ; return to immediate mode
2445 LD2D2 puls u ; get return address (we might be resetting the stack)
2446 lda DRESFL ; reset desired?
2447 beq LD2EF ; brif not
2448 ldx #FCBV1 ; point to FCB addresses
2449 clra ; set file counter to 0
2450 LD2DD clr [,x++] ; mark FCB as closed
2451 inca ; bump file counter
2452 cmpa FCBACT ; end of allocated FCBs?
2453 bls LD2DD ; brif not
2454 ldx TXTTAB ; get start of program
2455 clr -1,x ; make sure there's a NUL there
2456 jsr LAD19 ; do a "NEW"
2457 clr DRESFL ; mark reset as not needed
2458 LD2EF lda DLODFL ; were we loading something?
2459 beq LD2FA ; brif not
2460 clr DLODFL ; clear out the loading state
2461 jsr LAD19 ; empty out the program
2462 LD2FA jmp ,u ; return to caller
2463 LD2FC lda #2 ; opcode for read
2464 skip2
2465 LD2FF lda #3 ; opcode for write
2466 std DCOPC ; save operation and drive number
2467 lda 3,s ; get number of the first track to write
2468 sta DCTRK ; tell DSKCON
2469 ldx #DFLBUF ; put track buffer at the start of the heap
2470 stx DCBPT
2471 lda TMPLOC ; get track counter
2472 LD30E ldb #1 ; start at sector 1
2473 LD310 stb DSEC ; set sector
2474 jsr LD6F2 ; read or write a sector
2475 inc DCBPT ; bump buffer pointer
2476 incb ; bump sector number
2477 cmpb #SECMAX ; end of track?
2478 bls LD310 ; brif not
2479 inc DCTRK ; bump track
2480 deca ; done all the tracks?
2481 bne LD30E ; brif not
2482 rts
2483 LD322 ldb 5,s ; get destination drive number
2484 cmpb 6,s ; compare to source
2485 LD326 bne LD35E ; brif no prompt needed
2486 clr RDYTMR ; reset drive motor
2487 clr DSKREG
2488 clr DRGRAM
2489 pshs a ; save source/dest flag
2490 jsr LA928 ; clear screen
2491 ldx #LD35F ; point to "source"
2492 ldb #13 ; 13 bytes
2493 lda ,s+ ; set flags on source/dest flag
2494 beq LD344 ; brif source
2495 ldx #LD36C ; point to "dest"
2496 ldb #18 ; 18 bytes
2497 LD344 jsr LB9A2 ; display message
2498 ldx #LD37E ; point to remainder of message
2499 ldb #27 ; 27 bytes
2500 jsr LB9A2 ; display it
2501 ldd #0x6405 ; set up SOUND parameters
2502 sta SNDTON
2503 jsr LA951 ; do a beep
2504 LD357 jsr LA171 ; read generic input (shows cursor)
2505 cmpa #0x0d ; carriage return?
2506 bne LD357 ; bri fnot
2507 LD35E rts
2508 LD35F fcc 'INSERT SOURCE'
2509 LD36C fcc 'INSERT DESTINATION'
2510 LD37E fcc ' DISKETTE AND'
2511 fcb 0x0d
2512 fcc "PRESS 'ENTER'"
2513 ; Save file name and extension on stack, and also the current drive number
2514 LD399 puls y ; get return address
2515 ldb #11 ; 11 characters for both name and extension
2516 ldx #DNAMBF+11 ; point to end of buffer
2517 LD3A0 lda ,-x ; fetch a file name character
2518 pshs a ; stuff it on the stack
2519 decb ; done yet?
2520 bne LD3A0 ; brif not
2521 lda DCDRV ; save drive number
2522 pshs a
2523 jmp ,y ; return to caller
2524 ; Copy drive, filename, and extension from X to state
2525 LD3AD lda ,x+ ; set drive number
2526 sta DCDRV
2527 ldb #11 ; 11 characters in file name and extension
2528 ldu #DNAMBF ; point to disk file name buffer
2529 jmp LA59A ; copy the file name
2530 ; COPY command
2531 ; NOTE: an error during COPY will cause the system to hang due to the FCB's buffer pointer
2532 ; being moved out of normal buffer space.
2533 COPY jsr LC935 ; get source file name
2534 bsr LD399 ; save it on the stack
2535 clr ,-s ; set flag for "single disk" copy
2536 jsr GETCCH ; is there a destination?
2537 beq LD3CE ; brif not - single disk (swapping)
2538 com ,s ; set to "two parameter" copy
2539 ldb #0xa5 ; insist on TO
2540 jsr LB26F
2541 jsr LC935 ; parse the destination file name
2542 LD3CE bsr LD399 ; save destination file name
2543 jsr LA5C7 ; bail if more stuff
2544 jsr DVEC7 ; close everything
2545 clr ,-s ; clear sector counter
2546 ifeq DISKVER
2547 leax -100,s ; leave a buffer below the stack
2548 else
2549 leax -SECLEN,s ; point one sector below the stack
2550 endc
2551 LD3DC inc ,s ; bump sector counter
2552 leax -SECLEN,x ; move back a sector
2553 cmpx ARYEND ; did we hit the top of variables?
2554 bhs LD3DC ; brif not
2555 dec ,s ; decrement off the last one that didn't fit
2556 lbeq LAC44 ; brif not at least one sector free memory
2557 leax 14,s ; set up for source file name/drive
2558 bsr LD3AD
2559 jsr LC68C ; find file
2560 jsr LC6E5 ; error if not found
2561 ldx V974 ; get directory data pointer
2562 ldu DIRLST,x ; get file type and last sector data
2563 ldx DIRTYP,x
2564 pshs u,x ; save them
2565 jsr LC79D ; read FAT data
2566 ldb V976 ; get first granule in file
2567 jsr LCD1E ; count granules in chain
2568 pshs a ; save number of granules in file
2569 deca ; subtract off last granule (may be partial)
2570 andb #0x3f ; get number of sectors in last granule
2571 pshs b ; save sectors in last granule
2572 tfr a,b ; zero extend to granule count to D
2573 clra
2574 jsr LC779 ; get number of sectors in complete granules
2575 addb ,s ; add in partial sector count
2576 adca #0
2577 ldx #1 ; initialize record counter to 1
2578 pshs x,b,a ; save record counter and sector counter
2579 LD41E clrb ; set sector counter to 0
2580 ldx ,s ; get number of sectors remaining in the file
2581 beq LD42C ; brif none left
2582 LD423 incb ; add a sector to counter
2583 leax -1,x ; at bottom of file?
2584 beq LD42C ; brif so
2585 cmpb 10,s ; at maximum memory space?
2586 bne LD423 ; brif not
2587 LD42C stx ,s ; save number of sectors that will be left after this iteration
2588 stb 4,s ; save number of sectors to be copied this time
2589 bsr LD482 ; get sectors to buffer
2590 lda #0xff ; show swap message for dest
2591 bsr LD476
2592 tst 5,s ; do we need to test for enough free space?
2593 beq LD45F ; brif not
2594 leax 11,s ; retrieve destination file parameters
2595 jsr LD3AD
2596 jsr LD059 ; find the file, AE error if it exists
2597 jsr LC79D ; get FAT data
2598 jsr LC755 ; point to FAT
2599 leax FATCON,x ; point to granuledata
2600 lda 5,s ; get number of granules in file
2601 ldb #GRANMX ; maximum granules to check
2602 LD44E com ,x ; is granule free?
2603 bne LD455 ; brif not
2604 deca ; found enough?
2605 beq LD45D ; brif not
2606 LD455 com ,x+ ; restore FAT data
2607 decb ; run through whole fat?
2608 bne LD44E ; brif not
2609 jmp LC7F8 ; do "disk full"
2610 LD45D com ,x ; restore FAT data
2611 LD45F bsr LD47C ; put data from memory to destination file
2612 ldx ,s ; get number of sectors left
2613 beq LD472 ; brif none - we're done
2614 ldd 2,s ; get current recordcounter
2615 addb 4,s ; add in number of sectors
2616 adca #0
2617 std 2,s ; save new record counter
2618 clra ; show source message if needed
2619 bsr LD476
2620 bra LD41E ; copy some more stuff
2621 LD472 leas 36,s ; clean up stack
2622 rts
2623 LD476 tst 25,s ; doing a "single disk" copy?
2624 jmp LD326 ; show message if needed
2625 ; put or get data for copy
2626 LD47C lda #0xff ; put flag
2627 leax 13,s ; point to destination file
2628 bra LD486 ; go do the write
2629 LD482 clra ; get flag
2630 leax 26,s ; point to source file
2631 LD486 sta VD8 ; save get/put flag
2632 jsr LD3AD ; fetch file parameters from stack
2633 ldx 8,s ; get file type and ASCII flag
2634 stx DFLTYP ; save it
2635 ldx #SECLEN ; set record length to one sector
2636 stx DFFLEN
2637 lda #'R ; set type to "random"
2638 ldb FCBACT ; point to system FCB
2639 incb
2640 jsr LC48D
2641 ldx FCBTMP ; get FCB pointer
2642 ldd #SECLEN ; set number of bytes in last sector to one sector
2643 std FCBLST,x
2644 ldb 6,s ; get number of sectors to read/write
2645 beq LD4D4 ; brif none
2646 ldb VD8 ; get or put?
2647 andb 7,s ; is it first time on put?
2648 beq LD4BA ; brif not
2649 ldd 2,s ; get number of sectors remaining
2650 addb 6,s ; add to number copied this time
2651 adca #0
2652 jsr LC2E6 ; put the last record in the file (this allocates the file)
2653 LD4BA ldx FCBTMP ; point to FCB
2654 ldu 4,s ; get current record number
2655 stu FCBREC,x ; save in FCB
2656 ldb 6,s ; get number of sectors to move
2657 ldu ARYEND ; point to start of free memory
2658 LD4C4 pshs u,b ; save buffer pointer and counter
2659 ldx FCBTMP ; fetch FCB pointer
2660 stu FCBBUF,x ; set buffer to free memory (will cause hang on error)
2661 jsr LC2EA ; do get or put
2662 inc 1,s ; bump buffer pointer
2663 puls b,u ; get back buffer pointer and sector count
2664 decb ; done all yet?
2665 bne LD4C4 ; brif not
2666 LD4D4 ldx FCBTMP ; get FCB pointer
2667 ldu #DFLBUF ; reset buffer pointer to bottom of buffer area
2668 stu FCBBUF,x
2669 ldb VD8 ; first time through on PUT?
2670 andb 7,s
2671 beq LD4EA ; brif not
2672 clr 7,s ; reset the "first time" flag
2673 ldd 10,s ; get bytes in last sector
2674 ora #0x80 ; set "pre-save" flag
2675 std FCBLST,x ; set correct last sector size
2676 LD4EA jmp LCB06 ; close the file
2677 ; DSKI$ command
2678 DSKI bsr LD527 ; get drive, track, and sector
2679 bsr LD51C ; evaluate frist string sand save descriptor address
2680 pshs x
2681 bsr LD51C ; evaluate second string and save descriptor address
2682 pshs x
2683 ldb #2 ; read operation
2684 jsr LD58F ; read sector
2685 ldu #DBUF0+128 ; point to second half
2686 puls x ; get descriptor for second string
2687 bsr LD508 ; stow second string
2688 ldu #DBUF0 ; point to first half
2689 puls x ; get descriptor for first string
2690 LD508 pshs u,x ; save source data and descriptor
2691 ldb #128 ; do 128 bytes exactly
2692 jsr LB50F ; reserve space
2693 leau ,x ; point to reserved space
2694 puls x ; get string descriptor address
2695 stb ,x ; save length in descriptor
2696 stu 2,x ; save data pointer
2697 puls x ; get buffer pointer
2698 LD519 jmp LA59A ; copy bytes to string
2699 LD51C jsr SYNCOMMA ; make sure there's a comma
2700 ldx #LB357 ; point to variable evaluation routine
2701 bsr LD553 ; evaluate variable
2702 LD524 jmp LB146 ; make sure we have a string
2703 LD527 jsr EVALEXPB ; evaluate 8 bit expression
2704 cmpb #3 ; valid drive?
2705 bhi LD54A ; brif not
2706 pshs b ; save it
2707 jsr LB738 ; evaluate track expression (after a comma)
2708 cmpb #TRKMAX-1 ; valid track?
2709 bhi LD54A ; brif not
2710 pshs b ; save track number
2711 jsr LB738 ; evaluate comma followed by sector number
2712 stb DSEC ; set DSKCON variable
2713 decb ; zero-base it
2714 cmpb #SECMAX-1 ; is it a valid sector?
2715 bhi LD54A ; brif not
2716 puls a,b ; get drive and track
2717 sta DCTRK ; set DSKCON
2718 stb DCDRV
2719 rts
2720 LD54A jmp LB44A ; raise FC error
2721 LD54D jsr SYNCOMMA ; insist on a comma
2722 ldx #LB156 ; evaluate expression pointer
2723 LD553 ldb DCDRV ; save drive, track, and sector values
2724 ldu DCTRK
2725 pshs u,b ; save them
2726 jsr ,x ; evaluate variable or expression
2727 puls b,u ; restore DSKCON
2728 stb DCDRV
2729 stu DCTRK
2730 rts
2731 ; DSKO$ command
2732 DSKO bsr LD527 ; evaluate drive, track, and sector
2733 bsr LD54D ; evaluate string 1
2734 bsr LD524 ; make sure it's a string
2735 ldx FPA0+2 ; get descriptor address
2736 pshs x ; save it
2737 bsr LD54D ; evaluate string 2
2738 jsr LB654 ; get string details
2739 pshs x,b ; save them
2740 clrb ; clear full sector (so junk doesn't get in if strings are short)
2741 ldx #DBUF0 ; point to sector buffer
2742 LD577 clr ,x+ ; clear a byte
2743 decb ; done whole sector?
2744 bne LD577 ; brif not
2745 puls b,x ; get string data
2746 ldu #DBUF0+128 ; point to second half of sector
2747 bsr LD519 ; copy string data (anything over 128 will go in second I/O buffer so harmless)
2748 puls x ; get first string
2749 jsr LB659 ; fetch string details
2750 ldu #DBUF0 ; point to start of sector buffer
2751 bsr LD519 ; copy string data (this will overwrite up to 255 bytes!)
2752 ldb #3 ; write operation
2753 LD58F ldx #DBUF0 ; point to sector buffer
2754 stx DCBPT
2755 stb DCOPC ; set read/write
2756 jmp LD6F2 ; go read/write sector
2757 ; DSKINI command
2758 DSKINI lbeq LA61F ; error if no drive number specified
2759 jsr LD256 ; parse driven umber
2760 ldb #4 ; default skip factor is 4
2761 jsr GETCCH ; is there a skip factor?
2762 beq LD5B2 ; brif not
2763 jsr LB738 ; evaluate comma followed by skip factor
2764 cmpb #17 ; max value is 16
2765 lbhs LB44A ; brif too high
2766 jsr LA5C7 ; carp if there's anything else
2767 LD5B2 pshs b ; save skip factor
2768 ldx #DBUF1+SECMAX ; poitn to end of sector number scratch area
2769 ldb #SECMAX ; get the maximum sector number
2770 LD5B9 clr ,-x ; mark sector number unset
2771 decb ; done all of them?
2772 bne LD5B9 ; brif not
2773 clra ; reset sector counter
2774 bra LD5CE ; start assigning sector numbers
2775 LD5C1 addb ,s ; add in skip factor
2776 LD5C3 incb ; bump sector number
2777 LD5C4 subb #SECMAX ; remove a whole track worth
2778 bhs LD5C4 ; brif we can still do more
2779 addb #SECMAX ; undo extra subtraction
2780 tst b,x ; has this sector been numbered?
2781 bne LD5C3 ; brif so - try again on next one
2782 LD5CE inca ; bump sector number
2783 sta b,x ; set actual sector number
2784 cmpa #SECMAX ; done all?
2785 blo LD5C1 ; brif not
2786 leas 1,s ; remove skip factor - we don't need it
2787 ldx #DFLBUF+0x1888-2 ; point to top of memory used by DSKINI (for track image)
2788 cmpx MEMSIZ ; does it fit?
2789 lbhi LAC44 ; brif not
2790 jsr DVEC7 ; close files
2791 com DRESFL ; cause reset of things
2792 lds #DBUF1+SECLEN ; put stack somewhere safe
2793 jsr L95AC ; reset display
2794 lda #0 ; restore head to track 0
2795 sta DCOPC
2796 ifeq DISKVER-1
2797 clr DCTRK ; set track number to 0 (used as a track counter for the format)
2798 endc
2799 jsr LD6F2 ; restorehead to track 0
2800 clr RDYTMR ; don't allow motor to turn off
2801 lda #0xc0 ; FDC read address code
2802 sta FDCREG ; instruct FDC
2803 jsr LD7D1 ; wait until drive ready
2804 ifeq DISKVER
2805 lbne LD688 ; brif drive not ready
2806 clr DCTRK ; reset track counter
2807 bra LD620 ; go format tracks
2808 else
2809 beq LD620 ; brif drive ready
2810 jmp LD688 ; raise error if not ready
2811 endc
2812 LD606 cmpa #22 ; precomp?
2813 blo LD612 ; brif not
2814 lda DRGRAM ; enable precomp
2815 ora #0x10
2816 sta DSKREG
2817 LD612 lda #0x53 ; "step in"
2818 sta FDCREG ; go do a step
2819 exg a,a ; wait for FDC status to stabilize
2820 exg a,a
2821 jsr LD7D1 ; wait for ready
2822 bne LD688 ; bri fnot ready - raise error
2823 LD620 jsr LD7F0 ; wait for a bit
2824 bsr LD691 ; build formatted track
2825 ldy #FDCREG+3 ; point to data register
2826 orcc #0x50 ; disable interrupts
2827 ldx #LD64F ; where to return to
2828 stx DNMIVC ; set up NMI escaper
2829 ldx #DFLBUF ; point to track image
2830 lda FDCREG ; reset status of FDC
2831 lda #0xff ; enable NMI escaper
2832 sta NMIFLG
2833 ldb #0xf4 ; write track command
2834 stb FDCREG ; instruct FDC
2835 lda DRGRAM ; enable HALT
2836 ora #0x80
2837 sta DSKREG
2838 LD649 ldb ,x+ ; fetch track byte
2839 stb ,y ; stuff it out to FDC
2840 bra LD649 ; do another ASAP (HALT will clock this)
2841 LD64F lda FDCREG ; fetch status
2842 andcc #0xaf ; restore interrupts
2843 anda #0x44 ; keep only write protect and lost data
2844 sta DCSTA ; save status
2845 bne LD688 ; brif error
2846 inc DCTRK ; bump track number
2847 lda DCTRK ; done all tracks?
2848 cmpa #TRKMAX
2849 bne LD606 ; brif not
2850 lda #2 ; DSKCON read operation
2851 sta DCOPC
2852 ldx #DBUF0 ; point to disk buffer
2853 stx DCBPT
2854 ldu #DBUF1 ; point to sector numbers
2855 clra ; reset track counter
2856 LD66F sta DCTRK ; set track
2857 clrb ; reset sector counter
2858 LD672 lda b,u ; get real sector number
2859 sta DSEC ; tell DSKCON
2860 jsr LD6F2 ; read a sector
2861 incb ; bump sector counter
2862 cmpb #SECMAX ; done whole track?
2863 blo LD672 ; brif not
2864 lda DCTRK ; get track number
2865 inca ; bump it
2866 cmpa #TRKMAX ; done all?
2867 blo LD66F ; brif not
2868 jmp LD2CD ; do the reset thing if needed
2869 LD688 clr DRGRAM ; stop drive motors and selects
2870 clr DSKREG
2871 jmp LD701 ; wait for ready signal
2872 LD691 ldx #DFLBUF ; point to track buffer
2873 ldd #0x204e ; write out 32 * 0x4e
2874 bsr LD6C2
2875 clrb ; reset sector counter
2876 LD69A pshs b ; save sector counter
2877 ldu #DBUF1 ; point to sector numbers
2878 ldb b,u ; get real sector number
2879 stb DSEC ; save it
2880 ldu #LD6D4 ; point to format table for a sector
2881 ldb #3 ; process three blocks
2882 bsr LD6C8
2883 lda DCTRK ; save track number
2884 sta ,x+
2885 clr ,x+ ; set side number to 0
2886 lda DSEC ; set sector number
2887 sta ,x+
2888 ldb #9 ; process 9 blocks
2889 bsr LD6C8
2890 puls b ; get sector counter
2891 incb ; bump it
2892 cmpb #SECMAX ; done all?
2893 blo LD69A ; brif not - do another sector
2894 ldd #0xc84e ; write 200 times 0x4e for track trailer
2895 LD6C2 stb ,x+ ; stow a byte
2896 deca ; done enough?
2897 bne LD6C2 ; brif not
2898 rts
2899 LD6C8 pshs b ; save item counter
2900 ldd ,u++ ; get count and data byte
2901 bsr LD6C2 ; process it
2902 puls b ; get item count back
2903 decb ; done all?
2904 bne LD6C8 ; brif not
2905 rts
2906 LD6D4 fcb 8,0 ; SYNC field
2907 fcb 3,0xf5
2908 fcb 1,0xfe ; address mark
2909 ; track, side, sector here
2910 fcb 1,1 ; sector size flag
2911 fcb 1,0xf7 ; CRC request
2912 fcb 22,0x4e ; post-ID gap
2913 fcb 12,0 ; sync field
2914 fcb 3,0xf5
2915 fcb 1,0xfb ; data address mark
2916 fcb 0,0xff ; default track data
2917 fcb 1,0xf7 ; CRC request
2918 fcb 24,0x4e ; post data gap
2919 ifeq DISKVER-1
2920 ; DOS command
2921 DOS bne LD742 ; brif argument given
2922 jmp [DOSVEC] ; transfer control to DOS command
2923 endc
2924 ; General sector read/write routine; this implements VERIFY on write and does several retries
2925 LD6F2 pshs b ; save register
2926 ldb #5 ; we'll try 5 times on VERIFY failure
2927 stb ATTCTR
2928 puls b ; restore register
2929 LD6FB bsr DSKCON ; execute command
2930 tst DCSTA ; success?
2931 beq LD70E ; brif so
2932 LD701 lda DCSTA ; get status
2933 ldb #2*30 ; code for write protect
2934 bita #0x40 ; was it write protected?
2935 bne LD70B ; brif so
2936 LD709 ldb #2*20 ; I/O error code
2937 LD70B jmp LAC46 ; raise error
2938 LD70E pshs a ; save A
2939 lda DCOPC ; was it write?
2940 cmpa #3
2941 puls a ; restore register
2942 bne LD742 ; brif not
2943 tst DVERFL ; verify?
2944 beq LD742 ; brif not
2945 pshs u,x,b,a ; save registers
2946 lda #2 ; set for read
2947 sta DCOPC
2948 ldu DCBPT ; get original buffer pointer
2949 ldx #DBUF1 ; point to secondary buffer
2950 stx DCBPT
2951 bsr DSKCON ; read the sector
2952 stu DCBPT ; restore buffer pointer
2953 lda #3 ; restore write operation
2954 sta DCOPC
2955 lda DCSTA ; did we have a problem?
2956 bne LD743 ; brif so
2957 clrb ; check 256 bytes
2958 LD737 lda ,x+ ; compare two bytes
2959 cmpa ,u+
2960 bne LD743 ; brif no match - error
2961 decb ; done all?
2962 bne LD737 ; brif not
2963 puls a,b,x,u ; restore registers
2964 LD742 rts
2965 LD743 puls a,b,x,u ; restore registers
2966 dec ATTCTR ; tried enough times?
2967 bne LD6FB ; brif not - try again
2968 ldb #2*36 ; code for verify error
2969 bra LD70B ; raise error
2970 ; VERIFY command
2971 VERIFY clrb ; off flag
2972 cmpa #0xaa ; OFF?
2973 beq LD75A ; brif so
2974 comb ; set to on flag
2975 cmpa #0x88 ; ON?
2976 lbne LB277 ; brif not - raise error
2977 LD75A stb DVERFL ; set verify state
2978 jmp GETNCH ; eat the ON/OFF and return
2979 ; DSKCON - the main disk I/O driver
2980 DSKCON pshs u,y,x,b,a ; save registers
2981 lda #5 ; retry 5 times
2982 pshs a ; save retry counter
2983 LD765 clr RDYTMR ; reset drive timeout (so drive won't turn off if it's already on)
2984 ldb DCDRV ; get drive number
2985 ldx #LD89D ; point to drive enable masks
2986 lda DRGRAM ; get control register value
2987 anda #0xa8 ; keep only motor, halt, double density
2988 ora b,x ; set drive select lines
2989 ora #0x20 ; set double density
2990 ldb DCTRK ; get desired track
2991 cmpb #22 ; precomp?
2992 blo LD77E ; brif not
2993 ora #0x10 ; enable precomp
2994 LD77E tfr a,b ; save image prior to enabling motors
2995 ora #8 ; turn on motors
2996 sta DRGRAM ; actuall do all that stuff above
2997 sta DSKREG
2998 bitb #8 ; were motors already on?
2999 bne LD792 ; brif so - don't wait
3000 jsr LA7D1 ; wait quite a while
3001 jsr LA7D1 ; wait quite a while longer
3002 LD792 bsr LD7D1 ; wait until read
3003 bne LD7A0 ; brif timed out
3004 clr DCSTA ; clear status (set no error)
3005 ldx #LD895 ; point to command jump table
3006 ldb DCOPC ; get operation code
3007 aslb ; two bytes per routine address
3008 jsr [b,x] ; do operation
3009 LD7A0 puls a ; get back retry count
3010 ldb DCSTA ; get status
3011 beq LD7B1 ; brif no error
3012 deca ; retried enough?
3013 beq LD7B1 ; brif so
3014 pshs a ; save retry counter again
3015 bsr LD7B8 ; restore head to track 0
3016 bne LD7A0 ; brif error
3017 bra LD765 ; try command again
3018 LD7B1 lda #120 ; drive timeout is 120 VSYNC ticks (2 seconds for 60Hz)
3019 sta RDYTMR
3020 puls a,b,x,y,u,pc ; restore registers and return
3021 LD7B8 ldx #DR0TRK ; point to track table
3022 ldb DCDRV ; get drive number
3023 clr b,x ; mark drive on track 0
3024 lda #3 ; restore head to track 0, unloaded, 30ms step
3025 sta FDCREG ; go do it
3026 exg a,a ; wait for status to stabilize
3027 exg a,a
3028 bsr LD7D1 ; wait for ready
3029 bsr LD7F0 ; wait somemore
3030 anda #0x10 ; keep only seek error
3031 sta DCSTA ; set result
3032 LD7D0 rts
3033 LD7D1 ldx ZERO ; get timeout counter
3034 LD7D3 leax -1,x ; count down
3035 beq LD7DF ; brif timed out
3036 lda FDCREG ; get status
3037 bita #1 ; is it ready?
3038 bne LD7D3 ; brif not
3039 rts
3040 LD7DF lda #0xd0 ; force interrupt
3041 sta FDCREG
3042 exg a,a ; wait for status to stabilize
3043 exg a,a
3044 lda FDCREG ; clear status
3045 lda #0x80 ; return not ready status
3046 sta DCSTA
3047 rts
3048 LD7F0 ldx #8750 ; delay for about half of a long while
3049 LD7F3 leax -1,x ; count down
3050 bne LD7F3 ; brif not done
3051 rts
3052 LD7F8 lda #0x80 ; code for read sector
3053 skip2
3054 LD7FB lda #0xa0 ; code for write sector
3055 pshs a ; save operation
3056 ldx #DR0TRK ; point to track state table
3057 ldb DCDRV ; get drive number
3058 abx ; point to correct drive table
3059 ldb ,x ; get current track number
3060 stb FDCREG+1 ; tell FDC about it
3061 cmpb DCTRK ; is it the one we want?
3062 beq LD82C ; brif so - no stepping needed
3063 lda DCTRK ; get desired track
3064 sta FDCREG+3 ; tell the FDC that too
3065 sta ,x ; record that drive is there
3066 lda #0x17 ; seek to desired track, unloaded, 30ms step, verify destination
3067 sta FDCREG
3068 exg a,a ; wait for status to be stable
3069 exg a,a
3070 bsr LD7D1 ; wait for ready
3071 bne LD82A ; brif timed out
3072 bsr LD7F0 ; wait some more
3073 anda #0x18 ; keep only seek error or CRC error in ID
3074 beq LD82C ; brif no errors
3075 sta DCSTA ; save error state
3076 LD82A puls a,pc ; clean up stack and return
3077 LD82C lda DSEC ; get desired sector
3078 sta FDCREG+2 ; tell FDC
3079 ldx #LD88B ; point to escape routine
3080 stx DNMIVC ; set up NMI escaper
3081 ldx DCBPT ; point to I/O buffer
3082 lda FDCREG ; reset FDC status
3083 lda DRGRAM ; get control register image
3084 ora #0x80 ; enable HALT
3085 puls b ; get operation code
3086 ldy ZERO ; timeout value
3087 ldu #FDCREG ; point to FDC
3088 com NMIFLG ; enable escaper
3089 orcc #0x50 ; disable interrupts
3090 stb FDCREG ; give FDC its marching orders
3091 exg a,a ; wait for stable status
3092 exg a,a
3093 cmpb #0x80 ; read?
3094 beq LD875 ; brif so
3095 ldb #2 ; DRQ mask
3096 LD85B bitb ,u ; is it ready for a byte?
3097 bne LD86B ; brif not
3098 leay -1,y ; timed out?
3099 bne LD85B ; brif not
3100 LD863 clr NMIFLG ; disable NMI escaper
3101 andcc #0xaf ; enable interrupts
3102 jmp LD7DF ; force interrupt, etc.
3103 LD86B ldb ,x+ ; get byte from buffer
3104 stb FDCREG+3 ; send it out
3105 sta DSKREG ; reprogram control register
3106 bra LD86B ; send more
3107 LD875 ldb #2 ; DRQ mask bit
3108 LD877 bitb ,u ; is a byte ready?
3109 bne LD881 ; brif not
3110 leay -1,y ; timed out?
3111 bne LD877 ; brif not
3112 bra LD863 ; bail out
3113 LD881 ldb FDCREG+3 ; get input data
3114 stb ,x+ ; put in buffer
3115 sta DSKREG ; reprogram control register
3116 bra LD881 ; read more
3117 LD88B andcc #0xaf ; enable interrupts
3118 lda FDCREG ; get status from FDC
3119 anda #0x7c ; keep write protect, write fault, not found, CRC, or lost data
3120 sta DCSTA ; set status
3121 rts
3122 LD895 fdb LD7B8 ; reset head to track 0
3123 fdb LD7D0 ; no-op - just spin up drives
3124 fdb LD7F8 ; read sector
3125 fdb LD7FB ; write sector
3126 LD89D fcb 0x01 ; drive select 0
3127 fcb 0x02 ; drive select 1
3128 fcb 0x04 ; drive select 2
3129 fcb 0x40 ; drive select 3/side select
3130 ; NMI handler
3131 DNMISV lda NMIFLG ; is the escaper enabled?
3132 beq LD8AE ; brif not
3133 ldx DNMIVC ; set return to escape hatch
3134 stx 10,s
3135 clr NMIFLG ; disable escaper now that we used it
3136 LD8AE rti
3137 ; Disk IRQ handler
3138 DIRQSV lda PIA0+3 ; is it VSYNC?
3139 bpl LD8AE ; brif HSYNC
3140 lda PIA0+2 ; clear interrupt status
3141 lda RDYTMR ; are drives waiting to stop?
3142 beq LD8CD ; brif not
3143 deca ; count down a tick
3144 sta RDYTMR ; save new count
3145 bne LD8CD ; brif they haven't timed out yet
3146 lda DRGRAM ; get control register image
3147 anda #0xb0 ; turn off motors and drive selects
3148 sta DRGRAM
3149 sta DSKREG
3150 LD8CD jmp L8955 ; transfer control to Extended Basic's handler
3151 ifeq DISKVER-1
3152 ; From here to the DOS command is unused
3153 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
3154 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
3155 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
3156 fcb 0x13,0x34,0x06,0x9D,0xA5,0x27,0x03,0xBD,0x95,0x81,0x96,0xB5,0x97,0xD8,0x35,0x06
3157 fcb 0xDD,0xB4,0x4F,0x34,0x56,0xBD,0x95,0x22,0xBD,0x92,0x8F,0xDF,0xD9,0xBD,0x99,0xDF
3158 fcb 0x27,0x0F,0xBD,0x99,0xCB,0x86,0x01,0x97,0xD7,0xBD,0x99,0xBA,0x00,0xD7,0xBD,0x99
3159 fcb 0xBA,0x10,0xDF,0xDC,0x0D,0xDB,0x26,0x03,0x10,0xDE,0xDC,0x35,0x56,0x0F,0xDB,0x10
3160 fcb 0xDF,0xDC,0x30,0x01,0x9F,0xBD,0xDF,0xD1,0x97,0xD7,0x27,0x9F,0x2B,0x06,0x5C,0xD1
3161 fcb 0xD6,0x23,0x05,0x5F,0x5D,0x27,0xDD,0x5A,0xD7,0xC0,0xBD,0x99,0xDF,0x27,0x0F,0x10
3162 fcb 0x83,0x00,0x03,0x25,0x04,0x30,0x1E,0x8D,0x38,0xBD,0x99,0xCB,0x8D,0x4C,0x43,0x53
3163 fcb 0xD3,0xD1,0xDD,0xD1,0x2F,0x16,0xBD,0x95,0x06,0xBD,0x9A,0x12,0x26,0x05,0xCC,0xFF
3164 fcb 0xFF,0x20,0xED,0xBD,0x95,0x14,0x8D,0x3E,0x8D,0x5E,0x20,0xE0,0xBD,0x95,0x06,0x30
3165 fcb 0x8B,0x9F,0xBD,0x43,0x53,0x83,0x00,0x01,0x2F,0x04,0x1F,0x01,0x8D,0x03,0x7E,0x99
3166 fcb 0x34,0xDD,0xCB,0x35,0x20,0xDC,0xBD,0x34,0x16,0x96,0xD7,0x40,0xD6,0xC0,0x34,0x06
3167 fcb 0x34,0x20,0xC6,0x02,0xBD,0xAC,0x33,0xDC,0xCB,0x39,0xDD,0xCB,0x35,0x20,0xDC,0xC3
3168 fcb 0x34,0x16,0x96,0xD7,0x20,0xE6,0x9E,0xBD,0x9F,0xC3,0x39,0xDD,0xCD,0x10,0x9E,0xC3
3169 fcb 0x8D,0xF4,0x10,0x9F,0xBD,0x8D,0x11,0x9E,0xCD,0x30,0x8B,0xC3,0x00,0x01,0x39,0xBD
3170 fcb 0x99,0xC6,0x10,0x8E,0x95,0x14,0x20,0x06,0x10,0x8E,0x95,0x06,0xAD,0xA4,0xDE,0x8A
3171 fcb 0x9E,0xBD,0x2B,0x17,0x9C,0xD3,0x22,0x13,0x34,0x60,0x8D,0x16,0x27,0x0B,0xBD,0x93
3172 fcb 0x77,0x35,0x60,0x33,0x41,0xAD,0xA4,0x20,0xE9,0x35,0x60,0x1F,0x30,0x1F,0x01,0x93
3173 fcb 0x8A,0x39,0xAD,0x9F,0x00,0xD9,0x1F,0x89,0xD4,0xD8,0x34,0x06,0xA4,0x84,0xA1,0x61
3174 fcb 0x35,0x86,0x9E,0x8A,0xC6,0x01,0x34,0x14,0xBD,0xB1,0x56,0x5F,0xBD,0xA9,0xA2,0xBD
3175 fcb 0xA9,0x76,0xBD,0xB6,0x54,0x20,0x02,0x35,0x14,0xD7,0xD8,0x27,0xFA,0x9F,0xD9,0x10
3176 fcb 0x27,0x0F,0x31,0x0D,0xD8,0x27,0xF0,0xBD,0x9B,0x98,0x81,0x3B,0x27,0xF5,0x81,0x27
3177 fcb 0x27,0xF1,0x81,0x58,0x10,0x27,0x01,0xB2,0x8D,0x02,0x20,0xE7,0x81,0x4F,0x26,0x0D
3178 fcb 0xD6,0xDE,0x5C,0x8D,0x5B,0x5A,0xC1,0x04,0x22,0x63,0xD7,0xDE,0x39,0x81,0x56,0x26
3179 fcb 0x1A,0xD6,0xDF,0x54,0x54,0xC0,0x1F,0x8D,0x47,0xC1,0x1F,0x22,0x50,0x58,0x58,0x34
3180 fcb 0x04,0xCC,0x7E,0x7E,0xAB,0xE4,0xE0,0xE0,0xDD,0xDF,0x39,0x81,0x4C,0x26,0x23,0xD6
3181 fcb 0xE1,0x8D,0x2D,0x5D,0x27,0x37,0xD7,0xE1,0x0F,0xE5,0x8D,0x03,0x24,0xFC,0x39,0x0D
3182 fcb 0xD8,0x27,0x0A,0xBD,0x9B,0x98,0x81,0x2E,0x27,0x05,0xBD,0x9B,0xE2,0x43,0x39,0x0C
3183 fcb 0xE5,0x39,0x81,0x54,0x26,0x0D,0xD6,0xE2,0x8D,0x06,0x5D,0x27,0x10,0xD7,0xE2,0x39
3184 fcb 0x7E,0x9B,0xAC,0x81,0x50,0x26,0x24,0xBD,0x9C,0xCB,0x5D,0x26,0x03,0x7E,0xB4,0x4A
3185 fcb 0x96,0xE5,0x9E,0xDF,0x34,0x12,0x86,0x7E,0x97,0xDF,0x97,0xE0,0x0F,0xE5,0x8D,0x07
3186 fcb 0x35,0x12,0x97,0xE5,0x9F,0xDF,0x39,0x6F,0xE2,0x20,0x40,0x81,0x4E,0x26,0x03,0xBD
3187 fcb 0x9B,0x98,0x81,0x41,0x25,0x04,0x81,0x47,0x23,0x05,0xBD,0x9B,0xBE,0x20,0x23,0x80
3188 fcb 0x41,0x8E,0x9C,0x5B,0xE6,0x86,0x0D,0xD8,0x27,0x18,0xBD,0x9B,0x98,0x81,0x23,0x27
3189 fcb 0x04,0x81,0x2B,0x26,0x03,0x5C,0x20,0x0A,0x81,0x2D,0x26,0x03,0x5A,0x20,0x03,0xBD
3190 fcb 0x9B,0xE2,0x5A,0xC1,0x0B,0x22,0xA6,0x34,0x04,0xD6,0xE1,0x96,0xE2,0x3D,0xDD,0xD5
3191 fcb 0x33,0x61,0x96,0xDE,0x81,0x01,0x22,0x2C,0x8E,0x9C,0x62,0xC6,0x18,0x3D,0x3A,0x35
3192 fcb 0x04,0x58,0x3A,0x31,0x84,0x8D,0x45,0xDD,0xE3,0x8D,0x0C,0x96,0xDF,0x8D,0x0B,0x8D
3193 fcb 0x06,0x96,0xE0,0x8D,0x05,0x20,0xF2,0x86,0x7E,0x12,0xB7,0xFF,0x20,0xAE,0xA4,0x30
3194 fcb 0x1F,0x26,0xFC,0x39,0x8E,0x9C,0x7A,0xC6,0x0C,0x3D,0x3A,0x35,0x04,0x3A,0x8D,0x1C
3195 fcb 0xDD,0xE3,0x8D,0x0C,0x96,0xDF,0x8D,0x0B,0x8D,0x06,0x96,0xE0,0x8D,0x05,0x20,0xF2
3196 fcb 0x86,0x7E,0x12,0xB7,0xFF,0x20,0xA6,0x84,0x4A,0x26,0xFD,0x39,0xC6,0xFF,0x96,0xE5
3197 fcb 0x27,0x05,0x8B,0x02,0x3D,0x44,0x56,0x39,0x34,0x10,0x0D,0xD8,0x27,0x4D,0x9E,0xD9
3198 fcb 0xA6,0x80,0x9F,0xD9,0x0A,0xD8,0x81,0x20,0x27,0xF0,0x35,0x90,0x8D,0xEA,0x81,0x2B
3199 fcb 0x27,0x3C,0x81,0x2D,0x27,0x3C,0x81,0x3E,0x27,0x42,0x81,0x3C,0x27,0x39,0x81,0x3D
3200 fcb 0x27,0x3F,0xBD,0x90,0xAA,0x25,0x24,0x5F,0x80,0x30,0x97,0xD7,0x86,0x0A,0x3D,0x4D
3201 fcb 0x26,0x19,0xDB,0xD7,0x25,0x15,0x0D,0xD8,0x27,0x17,0xBD,0x9B,0x98,0xBD,0x90,0xAA
3202 fcb 0x24,0xE6,0x0C,0xD8,0x9E,0xD9,0x30,0x1F,0x9F,0xD9,0x39,0x7E,0xB4,0x4A,0x5C,0x27
3203 fcb 0xFA,0x39,0x5D,0x27,0xF6,0x5A,0x39,0x5D,0x27,0xF1,0x54,0x39,0x5D,0x2B,0xEC,0x58
3204 fcb 0x39,0x34,0x60,0x8D,0x16,0xBD,0xB7,0x0E,0x35,0xE0,0xBD,0x9C,0x1B,0xC6,0x02,0xBD
3205 fcb 0xAC,0x33,0xD6,0xD8,0x9E,0xD9,0x34,0x14,0x7E,0x9A,0x32,0x9E,0xD9,0x34,0x10,0xBD
3206 fcb 0x9B,0x98,0xBD,0xB3,0xA2,0x25,0xC4,0xBD,0x9B,0x98,0x81,0x3B,0x26,0xF9,0x35,0x10
3207 fcb 0xDE,0xA6,0x34,0x40,0x9F,0xA6,0xBD,0xB2,0x84,0x35,0x10,0x9F,0xA6,0x39,0x4F,0x1F
3208 fcb 0x8B,0xDC,0xE3,0x10,0x27,0x0D,0x74,0x93,0xD5,0xDD,0xE3,0x22,0x0D,0x0F,0xE3,0x0F
3209 fcb 0xE4,0x35,0x02,0x10,0xEE,0x67,0x84,0x7F,0x34,0x02,0x3B,0x0A,0x0C,0x01,0x03,0x05
3210 fcb 0x06,0x08,0x01,0xA8,0x01,0x90,0x01,0x7A,0x01,0x64,0x01,0x50,0x01,0x3D,0x01,0x2B
3211 fcb 0x01,0x1A,0x01,0x0A,0x00,0xFB,0x00,0xED,0x00,0xDF,0x00,0xD3,0x00,0xC7,0x00,0xBB
3212 fcb 0x00,0xB1,0x00,0xA6,0x00,0x9D,0x00,0x94,0x00,0x8B,0x00,0x83,0x00,0x7C,0x00,0x75
3213 fcb 0x00,0x6E,0xA6,0x9C,0x93,0x8B,0x83,0x7B,0x74,0x6D,0x67,0x61,0x5B,0x56,0x51,0x4C
3214 fcb 0x47,0x43,0x3F,0x3B,0x37,0x34,0x31,0x2E,0x2B,0x28,0x26,0x23,0x21,0x1F,0x1D,0x1B
3215 fcb 0x19,0x18,0x16,0x14,0x13,0x12,0x9E,0x8A,0xC6,0x01,0x34,0x14,0xD7,0xC2,0x9F,0xD5
3216 fcb 0xBD,0x95,0x9A,0xBD,0xB1,0x56,0xBD,0xB6,0x54,0x20,0x08,0xBD,0x9B,0x98,0x7E,0x9B
3217 fcb 0xBE,0x35,0x14,0xD7,0xD8,0x27,0xFA,0x9F,0xD9,0x10,0x27,0x00,0xEA,0x0D,0xD8,0x27
3218 fcb 0xF0,0xBD,0x9B,0x98,0x81,0x3B,0x27,0xF5,0x81,0x27,0x27,0xF1,0x81,0x4E,0x26,0x04
3219 fcb 0x03,0xD5,0x20,0xE9,0x81,0x42,0x26,0x04,0x03,0xD6,0x20,0xE1,0x81,0x58,0x10,0x27
3220 fcb 0x00,0x96,0x81,0x4D,0x10,0x27,0x01,0x2A,0x34,0x02,0xC6,0x01,0x0D,0xD8,0x27,0x11
3221 fcb 0xBD,0x9B,0x98,0xBD,0xB3,0xA2,0x34,0x01,0xBD,0x9B,0xE2,0x35,0x01,0x24,0x02,0x8D
3222 fcb 0xAA,0x35,0x02,0x81,0x43,0x27,0x28,0x81,0x41,0x27,0x2E,0x81,0x53,0x27,0x32,0x81
3223 fcb 0x55,0x27,0x5C,0x81,0x44,0x27,0x55,0x81,0x4C,0x27,0x4C,0x81,0x52,0x27,0x43,0x80
3224 fcb 0x45,0x27,0x2F,0x4A,0x27,0x27,0x4A,0x27,0x32,0x4A,0x27,0x1D,0x7E,0xB4,0x4A,0xBD
3225 fcb 0x95,0x5D,0xD7,0xB2,0xBD,0x95,0x9A,0x20,0x84,0xC1,0x04,0x24,0xEF,0xD7,0xE8,0x20
3226 fcb 0xF6,0xC1,0x3F,0x24,0xE7,0xD7,0xE9,0x20,0xEE,0x4F,0x8D,0x58,0x21,0x4F,0x1F,0x01
3227 fcb 0x20,0x59,0x4F,0x1F,0x01,0x8D,0x4D,0x1E,0x01,0x20,0x50,0x4F,0x1F,0x01,0x8D,0x44
3228 fcb 0x20,0x49,0x4F,0x9E,0x8A,0x20,0x44,0x4F,0x8D,0x3A,0x20,0xF7,0x4F,0x20,0x03,0x4F
3229 fcb 0x8D,0x32,0x9E,0x8A,0x1E,0x10,0x20,0x33,0xBD,0x9C,0x1B,0xC6,0x02,0xBD,0xAC,0x33
3230 fcb 0xD6,0xD8,0x9E,0xD9,0x34,0x14,0x7E,0x9C,0xC6,0xD6,0xE9,0x27,0x1B,0x4F,0x1E,0x01
3231 fcb 0xA7,0xE2,0x2A,0x02,0x8D,0x0D,0xBD,0x9F,0xB5,0x1F,0x30,0x44,0x56,0x44,0x56,0x6D
3232 fcb 0xE0,0x2A,0x04,0x40,0x50,0x82,0x00,0x39,0x1F,0x10,0x39,0x34,0x06,0x8D,0xDA,0x35
3233 fcb 0x10,0x34,0x06,0x8D,0xD4,0x35,0x10,0x10,0x9E,0xE8,0x34,0x20,0x6D,0xE4,0x27,0x08
3234 fcb 0x1E,0x10,0x8D,0xDF,0x6A,0xE4,0x20,0xF4,0x35,0x20,0xDE,0x8A,0xD3,0xC7,0x2B,0x02
3235 fcb 0x1F,0x03,0x1F,0x10,0x9E,0x8A,0xD3,0xC9,0x2B,0x02,0x1F,0x01,0x11,0x83,0x01,0x00
3236 fcb 0x25,0x03,0xCE,0x00,0xFF,0x8C,0x00,0xC0,0x25,0x03,0x8E,0x00,0xBF,0xDC,0xC7,0xDD
3237 fcb 0xBD,0xDC,0xC9,0xDD,0xBF,0x9F,0xC5,0xDF,0xC3,0x0D,0xD5,0x26,0x04,0x9F,0xC9,0xDF
3238 fcb 0xC7,0xBD,0x94,0x20,0x0D,0xD6,0x26,0x03,0xBD,0x94,0xA1,0x0F,0xD5,0x0F,0xD6,0x7E
3239 fcb 0x9C,0xDD,0xBD,0x9B,0x98,0x34,0x02,0xBD,0x9E,0x5E,0x34,0x06,0xBD,0x9B,0x98,0x81
3240 fcb 0x2C,0x10,0x26,0xFF,0x07,0xBD,0x9E,0x5B,0x1F,0x01,0x35,0x40,0x35,0x02,0x81,0x2B
3241 fcb 0x27,0x04,0x81,0x2D,0x26,0xA6,0x1F,0x30,0x7E,0x9D,0xCB,0xBD,0x9B,0x98,0x81,0x2B
3242 fcb 0x27,0x07,0x81,0x2D,0x27,0x04,0xBD,0x9B,0xE2,0x4F,0x34,0x02,0xBD,0x9C,0xCB,0x35
3243 fcb 0x02,0x4D,0x27,0x04,0x4F,0x50,0x82,0x00,0x39,0x00,0x00,0x00,0x01,0xFE,0xC5,0x19
3244 fcb 0x19,0xFB,0x16,0x31,0xF2,0xF4,0xFB,0x4A,0x51,0xEC,0x84,0x61,0xF9,0xE1,0xC7,0x78
3245 fcb 0xAE,0xD4,0xDC,0x8E,0x3B,0xC5,0xE5,0xA2,0x69,0xB5,0x06,0xB5,0x06,0x81,0x40,0x26
3246 fcb 0x02,0x9D,0x9F,0xBD,0x95,0x22,0xBD,0x93,0xB2,0xBD,0x93,0x1D,0xAE,0xC4,0x9F,0xCB
3247 fcb 0xAE,0x42,0x9F,0xCD,0xBD,0xB2,0x6D,0xBD,0xB7,0x3D,0xCE,0x00,0xCF,0xAF,0xC4,0xBD
3248 fcb 0x93,0x20,0x86,0x01,0x97,0xC2,0xBD,0x95,0x81,0x8E,0x01,0x00,0x9D,0xA5,0x27,0x0F
3249 fcb 0xBD,0xB2,0x6D,0xBD,0xB1,0x41,0x96,0x4F,0x8B,0x08,0x97,0x4F,0xBD,0xB7,0x40,0x96
3250 fcb 0xB6,0x85,0x02,0x27,0x04,0x1F,0x10,0x30,0x8B,0x9F,0xD1,0xC6,0x01,0xD7,0xC2,0xD7
3251 fcb 0xD8,0xBD,0x9F,0xE2,0x34,0x06,0xBD,0x9F,0xE2,0xDD,0xD9,0x35,0x06,0x34,0x06,0x9E
3252 ; The actual implementation of the DOS command follows; presumably this is here because it was
3253 ; implemented by a different group of people given that it doesn't call DSKCON directly and uses
3254 ; the DSKCON variables pointer as well.
3255 DOSCOM swi3 ; do a software interrupt for some reason (why?)
3256 clr TMPLOC ; reset sector counter
3257 ldd #DOSBUF ; initialize load address for boot track
3258 pshs d ; save buffer address
3259 LDF09 ldx DSKVAR ; point to DSKCON variables
3260 inc TMPLOC ; bump sector counter
3261 lda TMPLOC ; get current sector
3262 cmpa #SECMAX ; loaded whole track?
3263 bhi LDF36 ; brif so
3264 sta 3,x ; tell DSKCON the sector number
3265 ldd #0x0200 ; read code and drive 0
3266 sta ,x ; set operation code (should be std to set drive)
3267 lda #34 ; track 34
3268 sta 2,x ; tell DSKCON
3269 puls a,b ; get buffer pointer
3270 std 4,x ; tell DSKCON
3271 adda #1 ; bump buffer pointer by one sector
3272 pshs a,b ; save it again
3273 jsr [DCNVEC] ; call DSKCON to read a sector
3274 tst 6,x ; error?
3275 beq LDF09 ; brif not - read another
3276 puls a,b ; clean stack
3277 ldb #2*20 ; I/O error code
3278 jmp LAC46 ; raise error
3279 LDF36 puls a,b ; clear up stack
3280 ldd DOSBUF ; get start of loaded track
3281 cmpd #'O*256+'S ; is it the "OS" tag?
3282 lbeq DOSBUF+2 ; brif so - transfer control to it
3283 clr DOSBUF ; clear first two bytes (why?)
3284 clr DOSBUF+1
3285 jmp BAWMST ; do a warm start
3286 DOSINI ldd #0x3b3b ; set up SWI3 and SWI2 with RTIs (kind of pointless)
3287 std SW3VEC
3288 std SW3VEC+2
3289 std SW2VEC+1
3290 rts
3291 ; The remainder to the end is unused garbage bytes
3292 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x10,0x93,0xD3,0x25,0x02,0xDC,0xD3,0xDD
3293 fcb 0xC3,0xA6,0xE4,0x81,0x04,0x25,0x0A,0xDC,0xCD,0x93,0xC5,0x24,0x11,0x4F,0x5F,0x20
3294 fcb 0x0D,0xDC,0xCD,0xD3,0xC5,0x25,0x05,0x10,0x93,0xD5,0x25,0x02,0xDC,0xD5,0xDD,0xC5
3295 fcb 0x0D,0xD8,0x26,0x02,0x8D,0x50,0x35,0x06,0x04,0xD8,0x25,0x05,0x10,0x93,0xD9,0x27
3296 fcb 0x0C,0x5C,0xC1,0x08,0x26,0x04,0x4C,0x5F,0x84,0x07,0x7E,0x9E,0xFD,0x39,0x9E,0xCF
3297 fcb 0xEC,0xC4,0x27,0x07,0x83,0x00,0x01,0x8D,0x03,0x1F,0x21,0x39,0x34,0x76,0x6F,0x64
3298 fcb 0xA6,0x63,0x3D,0xED,0x66,0xEC,0x61,0x3D,0xEB,0x66,0x89,0x00,0xED,0x65,0xE6,0xE4
3299 fcb 0xA6,0x63,0x3D,0xE3,0x65,0xED,0x65,0x24,0x02,0x6C,0x64,0xA6,0xE4,0xE6,0x62,0x3D
3300 fcb 0xE3,0x64,0xED,0x64,0x35,0xF6,0x7E,0x94,0xA1,0x5F,0x9D,0xA5,0x27,0x11,0xBD,0xB2
3301 fcb 0x6D,0xBD,0xB1,0x41,0x96,0x4F,0x8B,0x06,0x97,0x4F,0xBD,0xB7,0x0E,0xC4,0x3F,0x1F
3302 fcb 0x98,0xC4,0x07,0x44,0x44,0x44,0x39
3303 else
3304 ; From here to the end of the ROM is unused garbage bytes
3305 fcb 0x00,0x00,0x00
3306 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
3307 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
3308 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
3309 fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
3310 fcb 0xa7,0xfc,0x8f,0xec,0x94,0xbc,0x8c,0xf5
3311 fcb 0xbc,0xf8,0xd1,0xfa,0xfd,0xfd,0xac,0xe5
3312 fcb 0xec,0xf8,0x8a,0xea,0xad,0xec,0xb9,0xff
3313 fcb 0xbc,0xfd,0xcc,0xed,0x8c,0xe5,0x9c,0xf4
3314 fcb 0xa2,0xa6,0xe8,0xfc,0xae,0xe5,0x94,0xec
3315 fcb 0xbe,0xee,0x8c,0xed,0xea,0xe5,0xed,0x7c
3316 fcb 0xbe,0xfc,0x8e,0xed,0xfe,0xec,0x9c,0xac
3317 fcb 0xdc,0xfd,0xfb,0xf5,0xad,0xfd,0xaf,0xe9
3318 fcb 0xa0,0x30,0x24,0x8a,0x14,0x84,0x2c,0xc4
3319 fcb 0x24,0x08,0xe0,0x21,0x20,0x80,0x28,0x00
3320 fcb 0x20,0x88,0xa4,0xa0,0xa4,0x80,0xac,0x11
3321 fcb 0x30,0x90,0x24,0xd4,0x01,0xa1,0xa0,0x84
3322 fcb 0x64,0x80,0x34,0x04,0x34,0x80,0x20,0x21
3323 fcb 0xa1,0x81,0xa4,0x80,0x20,0x90,0x88,0xc0
3324 fcb 0x00,0x9a,0xa0,0xa0,0xe0,0x80,0xb6,0xa4
3325 fcb 0x20,0xa2,0x20,0x98,0x20,0x88,0x7c,0xae
3326 fcb 0xbd,0xee,0xee,0xfe,0xf1,0xec,0xad,0xbc
3327 fcb 0xed,0xec,0xdd,0xf9,0xec,0x75,0xb5,0xbd
3328 fcb 0xef,0xfd,0xa9,0xe4,0x96,0xfc,0x94,0xe4
3329 fcb 0xae,0xad,0xda,0xb4,0xac,0x7c,0xc3,0xec
3330 fcb 0xbd,0xfc,0xae,0xfd,0xee,0xfd,0x85,0xf4
3331 fcb 0xad,0xef,0x76,0xfc,0xd6,0x6e,0xef,0xed
3332 fcb 0xf6,0xbd,0xed,0xfe,0x58,0xed,0xf7,0xfd
3333 fcb 0x85,0xec,0xfc,0xe8,0xf2,0xe4,0xbf,0xa8
3334 fcb 0x30,0x80,0xa0,0x05,0xa4,0x20,0xb0,0x80
3335 fcb 0x20,0x84,0x04,0x80,0x30,0x8e,0xe0,0xa4
3336 fcb 0xb0,0x02,0x04,0x80,0x61,0x84,0x20,0x00
3337 fcb 0xa0,0x80,0x20,0x88,0x24,0x94,0x24,0xa4
3338 fcb 0x80,0x04,0x00,0x84,0x24,0x84,0x28,0x9c
3339 fcb 0x44,0x28,0xa0,0x80,0x80,0x90,0x30,0x80
3340 fcb 0xe8,0x80,0xa4,0x88,0x30,0x94,0x20,0x80
3341 fcb 0x00,0x8c,0x68,0xac,0xa4,0x84,0x30,0x06
3342 fcb 0x86,0xe4,0xbc,0xfc,0xae,0xec,0x87,0xbd
3343 fcb 0x9c,0xfd,0xec,0xbc,0xfd,0xb5,0xa9,0xed
3344 fcb 0xa7,0xac,0x8b,0x7c,0xa5,0xfc,0xcc,0xbc
3345 fcb 0xaa,0xb6,0xc9,0xfc,0xa5,0xfc,0x47,0xfc
3346 fcb 0xdd,0x6d,0x84,0xfe,0xac,0xee,0x20,0xf4
3347 fcb 0xc5,0xff,0xf4,0xee,0xf7,0xf4,0xaa,0xfc
3348 fcb 0xef,0xff,0x9c,0xfd,0xee,0xe4,0xaf,0xfc
3349 fcb 0xbe,0xbc,0xdf,0xa5,0xeb,0xec,0xee,0xa4
3350 fcb 0x34,0x86,0xac,0x84,0xa4,0x21,0x90,0x88
3351 fcb 0xa0,0xa0,0x24,0xc0,0xe0,0x80,0x70,0xe5
3352 fcb 0x3c,0xa5,0xa1,0x8c,0x34,0xa4,0xe4,0x84
3353 fcb 0x24,0x80,0xf8,0x81,0xa0,0x8d,0xec,0x4a
3354 fcb 0x2c,0xe2,0xa4,0x93,0x20,0x88,0xb0,0xc0
3355 fcb 0x34,0x10,0x20,0x91,0xa4,0x84,0xa4,0xae
3356 fcb 0x0c,0x92,0xb0,0xcd,0xb0,0xaa,0x74,0xe8
3357 fcb 0xa0,0x12,0xb9,0x85,0x21,0xf5,0xe0,0x8e
3358 fcb 0x9e,0xbd,0x81,0xf5,0xcf,0xe4,0xcc,0x66
3359 fcb 0xa7,0xad,0x98,0xbd,0xbc,0xbc,0x88,0xbc
3360 fcb 0x8e,0xed,0xa4,0xa8,0xad,0x88,0xee,0xfe
3361 fcb 0xcd,0xfc,0xac,0xfd,0x8c,0xfc,0x9a,0xf5
3362 fcb 0xb4,0xe4,0x8e,0xfc,0xfe,0xe4,0xcc,0xac
3363 fcb 0x9d,0xfc,0x97,0xe4,0x8b,0xec,0xea,0xec
3364 fcb 0xdb,0xec,0xdf,0xec,0xac,0xe4,0xae,0xfc
3365 fcb 0xd4,0xf4,0xcd,0xec,0xb4,0xec,0xef,0xee
3366 fcb 0xb2,0x24,0x28,0x20,0xac,0xd0,0x24,0x1c
3367 fcb 0x30,0x81,0xac,0x84,0x80,0x01,0xa4,0xa4
3368 fcb 0x70,0x88,0xa4,0xc4,0xa4,0x84,0x24,0x60
3369 fcb 0x08,0x04,0xa0,0x88,0x20,0x98,0x64,0xa8
3370 fcb 0x24,0x10,0xd4,0x90,0xa0,0x81,0x30,0xec
3371 fcb 0xac,0x09,0x64,0xe0,0x60,0x18,0x30,0xb0
3372 fcb 0x24,0x80,0x6c,0x88,0xa4,0x8c,0xa4,0x8c
3373 fcb 0xa8,0x10,0x21,0xa8,0x68,0x84,0xa8,0xa0
3374 fcb 0x8d,0xe5,0xa4,0x66,0x98,0xfd,0x87,0xfc
3375 fcb 0xde,0xac,0x9c,0xf4,0x8c,0xf5,0xb5,0xf5
3376 fcb 0xb6,0xf5,0xa9,0xf8,0xaf,0xed,0xe6,0xe5
3377 fcb 0xb8,0xf1,0xb1,0xfc,0xfc,0xe9,0x8c,0xec
3378 fcb 0x86,0xf9,0xb5,0xf7,0xcd,0xbc,0x84,0xe6
3379 fcb 0x8c,0xfc,0x81,0xe4,0xbc,0xe4,0x4f,0xfc
3380 fcb 0x8c,0xfc,0xae,0xe7,0xbd,0xfc,0xdc,0xfc
3381 fcb 0xf4,0xe8,0x9f,0xec,0xea,0xfc,0xef,0x6c
3382 fcb 0x20,0x82,0xa4,0x40,0xa8,0x8c,0xac,0x08
3383 fcb 0x60,0x82,0xa1,0x95,0xe0,0x30,0x60,0x80
3384 fcb 0x64,0x48,0x20,0x04,0x20,0x84,0xa4,0x82
3385 fcb 0xa0,0x04,0x20,0x94,0x44,0xa0,0xe0,0x80
3386 fcb 0x04,0xc8,0x2c,0x82,0x24,0x04,0x30,0xb8
3387 fcb 0x24,0x00,0x20,0xa0,0xa4,0x82,0xa0,0x80
3388 fcb 0x84,0x81,0x2c,0x84,0x20,0x80,0x24,0x8c
3389 fcb 0x80,0x80,0x24,0x02,0x64,0xa8,0x24,0x88
3390 fcb 0xed,0xbd,0xd1,0xff,0xb4,0xe4,0xaa,0xec
3391 fcb 0x80,0xf1,0x8c,0xed,0x89,0xac,0xb6,0xfc
3392 fcb 0x6e,0xfd,0xae,0xed,0x89,0xec,0xb6,0xec
3393 fcb 0xae,0xfd,0xee,0xf0,0x9f,0x7e,0x9f,0xfe
3394 fcb 0xd9,0xec,0xae,0xed,0xc6,0xec,0xfe,0x7d
3395 fcb 0xbc,0xfc,0xb9,0xac,0xda,0xfc,0xa5,0xbd
3396 fcb 0xcc,0xfd,0xad,0xe6,0xae,0xf4,0xcd,0xf4
3397 fcb 0xf2,0xed,0x84,0x78,0xcc,0xec,0xab,0x74
3398 fcb 0xa4,0x94,0x20,0x84,0x20,0x00,0xa0,0x00
3399 fcb 0xa4,0x05,0x28,0x0c,0x24,0x04,0x24,0x00
3400 fcb 0xa0,0x84,0x80,0x80,0x18,0x80,0x24,0x0c
3401 fcb 0xe0,0x88,0x04,0x8a,0x2c,0x88,0x0c,0x84
3402 fcb 0x00,0x80,0xe0,0x04,0x20,0xa1,0x20,0x85
3403 fcb 0x20,0x90,0x80,0x9c,0x24,0xc0,0xe0,0x8d
3404 fcb 0xa0,0x80,0x20,0x82,0xa0,0xa2,0x20,0x40
3405 fcb 0x80,0x82,0x10,0xb8,0x00,0x84,0x60,0x92
3406 fcb 0xdf,0xef,0xd1,0xec,0xa4,0xec,0xc9,0xfd
3407 fcb 0xe6,0xad,0xc6,0xe5,0xd4,0xfd,0x9a,0xed
3408 fcb 0xae,0xe4,0xac,0xbc,0x9f,0xec,0x8a,0xed
3409 fcb 0x0f,0xe5,0x8f,0xec,0xd7,0xe4,0xac,0xec
3410 fcb 0xce,0xef,0x9e,0xf4,0xd7,0xe4,0xcf,0xf5
3411 fcb 0xce,0xf4,0xe6,0x6c,0x81,0xec,0x9b,0xee
3412 fcb 0x9f,0x7c,0xbc,0xf7,0xcc,0x6d,0xfe,0xef
3413 fcb 0x8e,0x6e,0xef,0xbd,0xbe,0xbd,0x8f,0xe4
3414 fcb 0xa0,0x04,0x20,0xe0,0xb4,0x82,0xb4,0x82
3415 fcb 0x20,0x8c,0xb0,0x90,0xb0,0x90,0xb8,0x84
3416 fcb 0x24,0x90,0x6a,0x86,0x28,0x84,0xa0,0xa8
3417 fcb 0x24,0xcf,0xb8,0x88,0xa0,0xa0,0xb1,0x81
3418 fcb 0x10,0xb6,0xe0,0x98,0xc8,0xb4,0x34,0xaf
3419 fcb 0x34,0x00,0xb0,0x82,0x20,0x90,0xe4,0xac
3420 fcb 0x28,0x84,0x84,0x88,0x24,0xac,0xac,0xa4
3421 fcb 0x25,0x98,0x20,0xa0,0x20,0x80,0x32,0x00
3422 fcb 0xae,0xec,0x8d,0xbd,0x9f,0xf7,0xff,0xa1
3423 fcb 0xca,0xbe,0x8d,0x7c,0x8e,0x74,0xef,0xec
3424 fcb 0xd4,0xf5,0x9e,0xb8,0x8e,0x35,0xc6,0xe4
3425 fcb 0x90,0xed,0xed,0xfc,0x8c,0x25,0xbe,0xa4
3426 fcb 0xfc,0x6c,0x89,0xee,0xec,0xad,0xae,0x78
3427 fcb 0xee,0xec,0xad,0xed,0xad,0xec,0xbc,0xbd
3428 fcb 0x2e,0x76,0xae,0xec,0x8e,0xbd,0xef,0xfd
3429 fcb 0xac,0xec,0xef,0xb5,0xbe,0xa4,0xbf,0xe8
3430 fcb 0x04,0x00,0x24,0x08,0x04,0x84,0x24,0x80
3431 fcb 0x28,0x82,0x60,0x04,0x24,0x94,0x28,0x00
3432 fcb 0x2c,0x84,0x20,0x80,0xb5,0x86,0x30,0x04
3433 fcb 0x23,0x84,0xa0,0x80,0xa0,0x06,0x24,0xad
3434 fcb 0xa4,0x80,0xa6,0x86,0x80,0x00,0xe0,0x80
3435 fcb 0x66,0x90,0x20,0x8c,0x00,0x8c,0x04,0x82
3436 fcb 0xa4,0x46,0x00,0x01,0x20,0x98,0xa0,0x88
3437 fcb 0x20,0x2a,0x24,0xe0,0x00,0x08,0x64,0x02
3438 fcb 0x8d,0xa5,0xb5,0xe5,0xad,0xf7,0xcd,0xf4
3439 fcb 0xa8,0x29,0xbc,0x64,0xf8,0xec,0xad,0xae
3440 fcb 0xa8,0xf5,0x8c,0xa7,0xe7,0xe5,0xa9,0xf4
3441 fcb 0xf4,0xfd,0x94,0xed,0x5c,0xe4,0xc0,0xbe
3442 fcb 0x8c,0xfd,0xcd,0xa4,0x94,0xff,0xa5,0xec
3443 fcb 0xfc,0xe5,0xac,0xe4,0xae,0xbd,0x9d,0xbd
3444 fcb 0xa8,0xec,0x84,0x68,0xc9,0xad,0x8e,0xac
3445 fcb 0xea,0xed,0x8f,0xec,0xbf,0xaf,0xf7,0xed
3446 fcb 0x24,0x91,0xa0,0x04,0xb4,0x04,0x82,0x90
3447 fcb 0xac,0x08,0xb0,0xa0,0xc0,0x08,0x34,0xa0
3448 fcb 0x65,0x88,0x73,0x80,0x20,0x80,0x2c,0x04
3449 fcb 0x20,0x84,0x21,0x26,0x20,0x94,0x00,0x20
3450 fcb 0xa4,0x96,0xa4,0x80,0xb0,0x84,0x24,0x82
3451 fcb 0x25,0x86,0xa0,0x00,0x7c,0x30,0xa2,0x25
3452 fcb 0x24,0x9e,0xa0,0x88,0x20,0x80,0x20,0x00
3453 fcb 0x20,0xa9,0x20,0xa2,0xc0,0xb2,0xa1,0x0e
3454 fcb 0xae,0xec,0xa8,0xee,0xac,0xf8,0xfa,0xb4
3455 fcb 0xa4,0xfe,0xfc,0xf4,0x1c,0xed,0xae,0xf4
3456 fcb 0xd7,0xf8,0xfd,0xed,0x8e,0xfe,0xdc,0xe8
3457 fcb 0xfe,0xed,0xfc,0xed,0x9f,0xfc,0x9c,0xed
3458 fcb 0xb0,0xe7,0xbe,0xfe,0x84,0xe4,0xa7,0xfe
3459 fcb 0xad,0xe4,0xbc,0x64,0x8d,0xbf,0xaf,0xfd
3460 fcb 0xaa,0x2c,0xcd,0xed,0x8f,0xe4,0xfc,0xbd
3461 fcb 0xbf,0xef,0xe5,0xed,0xbf,0xfe,0xe5,0xfd
3462 fcb 0x84,0x82,0xa4,0x83,0xa4,0x08,0xa0,0x80
3463 fcb 0x00,0x84,0x30,0x86,0x08,0x20,0xb0,0x90
3464 fcb 0x14,0xb4,0xa0,0x80,0x20,0x90,0xa4,0x88
3465 fcb 0xec,0x80,0xa4,0x84,0xa0,0x84,0x28,0x80
3466 fcb 0xb4,0x81,0xf0,0xa0,0xe4,0x80,0x00,0x84
3467 fcb 0x34,0xb1,0xe4,0x80,0x24,0x5d,0x20,0xd2
3468 fcb 0x44,0x83,0xb0,0x88,0x20,0x14,0x30,0xbc
3469 fcb 0x20,0xa0,0xc4,0x9d,0x68,0x00,0xa0,0x20
3470 fcb 0xcf,0xec,0xaa,0x66,0xb8,0x75,0x9e,0xfc
3471 fcb 0xfe,0xb4,0xbc,0xff,0xac,0xfd,0x9a,0xbc
3472 fcb 0xba,0xec,0x8e,0xf4,0xec,0xfc,0x96,0xfd
3473 fcb 0xd2,0xea,0x84,0xfc,0xae,0xe4,0xe5,0xfd
3474 fcb 0xbd,0xec,0xdc,0xac,0xa5,0xb0,0xcf,0xec
3475 fcb 0x7a,0xb5,0xe4,0xea,0xef,0xec,0xa4,0xfe
3476 fcb 0xe5,0xff,0xf8,0xbc,0x86,0xe4,0xff,0xe5
3477 fcb 0xaf,0x6c,0xee,0xec,0xee,0x6c,0x2a,0x6c
3478 fcb 0x28,0xa0,0x64,0x84,0xb4,0x92,0x04,0x94
3479 fcb 0x80,0x00,0xb8,0x0c,0x20,0x88,0xa0,0x84
3480 fcb 0xa0,0x40,0xb0,0x00,0xa0,0x84,0xa0,0xca
3481 fcb 0x00,0x14,0x24,0xc0,0xa0,0x64,0x24,0x88
3482 fcb 0x00,0x18,0xed,0x88,0x28,0x80,0xa1,0x80
3483 fcb 0x00,0x85,0x20,0x80,0xa4,0x34,0x00,0x04
3484 fcb 0x24,0xa4,0xac,0x8c,0x34,0x88,0x2c,0x04
3485 fcb 0x24,0x84,0x60,0x88,0xa0,0xa0,0xa0,0x9c
3486 fcb 0xb9,0xf4,0x97,0xec,0x68,0xad,0xe4,0xf0
3487 fcb 0xf4,0xec,0xcb,0xfc,0xa8,0xf5,0xfd,0x3e
3488 fcb 0xfc,0xee,0x9d,0xec,0x5e,0xfc,0x9c,0xf6
3489 fcb 0x80,0xed,0xa2,0xe4,0xad,0xb6,0xbf,0xf4
3490 fcb 0xed,0xfe,0xb3,0xfc,0xdc,0xb5,0xb3,0xed
3491 fcb 0xef,0xfc,0xbf,0xfc,0xbc,0xfe,0xea,0xf4
3492 fcb 0xc5,0xe4,0x89,0xfc,0x7c,0xbd,0xde,0xfd
3493 fcb 0x87,0xe4,0x9e,0xec,0xaf,0xe4,0xfe,0xe4
3494 fcb 0x34,0xc6,0x30,0x26,0x24,0x80,0x20,0x1c
3495 fcb 0xb4,0x04,0xb4,0x28,0x24,0x98,0x20,0x00
3496 fcb 0xa4,0xa4,0xa0,0x80,0x21,0x48,0xb9,0x24
3497 fcb 0x20,0x80,0x28,0x00,0x20,0x80,0x84,0x1e
3498 fcb 0x60,0xbc,0x28,0x88,0xac,0x74,0xe0,0x04
3499 fcb 0x24,0xa6,0x00,0x20,0x70,0x85,0xa0,0x89
3500 fcb 0x30,0x0b,0xa0,0x80,0x20,0x10,0xa0,0x14
3501 fcb 0x24,0x04,0x20,0x82,0xa0,0x80,0x35,0xa0
3502 fcb 0xee,0xbc,0xbe,0xfd,0xbe,0xb9,0x89,0xe4
3503 fcb 0xfd,0x3d,0x13,0xe4,0x9e,0xec,0x8d,0xec
3504 fcb 0xde,0xfc,0x8e,0xe5,0x8f,0xf4,0xbe,0xff
3505 fcb 0xe6,0xe6,0x8c,0xe6,0xcd,0xae,0xee,0xed
3506 fcb 0xfe,0xec,0xdc,0xec,0x8e,0xfc,0x96,0xfd
3507 fcb 0xa6,0xfc,0xce,0xcd,0xbe,0xfe,0xee,0xfc
3508 fcb 0x9e,0xf4,0xee,0x6e,0xcf,0xed,0xee,0xe0
3509 fcb 0xfc,0xee,0xae,0xa0,0xfd,0xed,0xa6,0x6c
3510 fcb 0xa8,0x04,0x20,0x00,0x30,0x80,0xa0,0x90
3511 fcb 0x20,0x80,0x60,0x00,0x20,0x82,0x90,0x40
3512 fcb 0x24,0x10,0x04,0x00,0x84,0x00,0x24,0x18
3513 fcb 0xe0,0x00,0x00,0x02,0x20,0xb4,0x24,0x00
3514 fcb 0x22,0x80,0x04,0x04,0xa0,0x80,0x84,0x0a
3515 fcb 0x28,0x14,0xa0,0x80,0x00,0x86,0x40,0x86
3516 fcb 0x20,0x90,0x10,0x30,0x84,0x84,0x00,0x00
3517 fcb 0x74,0x80,0x30,0x00,0x20,0x08,0x20,0x80
3518 fcb 0xfb,0xfd,0xc9,0xe6,0x91,0xfd,0xc8,0xee
3519 fcb 0xb4,0x7c,0xbe,0xec,0x89,0xec,0xbd,0xfc
3520 fcb 0xa5,0xfd,0xd9,0xec,0x8a,0xfd,0xae,0xec
3521 fcb 0xad,0xfc,0xae,0xec,0x8d,0xec,0x8f,0xf4
3522 fcb 0xbf,0x6d,0xac,0xbd,0xea,0xed,0xaf,0xac
3523 fcb 0xfd,0xfc,0xea,0xfd,0xf0,0xf9,0xb3,0xee
3524 fcb 0x8e,0xe4,0xfd,0xec,0xff,0xe0,0x8e,0xe4
3525 fcb 0xfd,0xad,0xdc,0x6c,0xa0,0xe4,0x8e,0xe4
3526 fcb 0x28,0x00,0xb4,0x00,0x22,0x00,0xb4,0x00
3527 fcb 0x6c,0x00,0xa4,0x1b,0xb2,0x9c,0x20,0x84
3528 fcb 0x24,0xc4,0x24,0xa8,0xa0,0x80,0x64,0x88
3529 fcb 0x80,0xac,0x30,0x85,0x20,0x9c,0x74,0xf2
3530 fcb 0x88,0x88,0x38,0x80,0x2c,0xa0,0x20,0x04
3531 fcb 0xb8,0x80,0x24,0x90,0xa8,0xf8,0xbc,0x88
3532 fcb 0x20,0x20,0xa0,0xe0,0x6c,0x80,0x00,0xe8
3533 fcb 0x20,0x80,0x24,0xc0,0x23,0x9c,0x24,0x82
3534 fcb 0xb5,0xe0,0xa4,0xed,0x8e,0xe4,0xa9,0xfc
3535 fcb 0xf8,0xee,0xce,0xfc,0x89,0xe4,0x98,0xf5
3536 fcb 0xa1,0xec,0xa1,0xe0,0xb8,0xec,0xd0,0xfc
3537 fcb 0xcf,0xf9,0xae,0xec,0x8a,0xfd,0x6b,0x6e
3538 fcb 0x94,0xa8,0xb8,0xe4,0xce,0xa6,0x8c,0xf4
3539 fcb 0xee,0xbd,0x8d,0xec,0xed,0xf4,0xcf,0x6c
3540 fcb 0x99,0x6c,0xc8,0xf9,0xf9,0xa5,0xb6,0x79
3541 fcb 0x8c,0xc1,0xe4,0xf5,0xaa,0x24,0xf7,0x64
3542 fcb 0x24,0xa8,0xa4,0x80,0xa0,0x96,0x20,0x09
3543 fcb 0x20,0x18,0xa8,0x08,0xb0,0xc0,0x7c,0xcd
3544 fcb 0x24,0xdc,0x20,0x98,0x64,0x84,0xe0,0x82
3545 fcb 0x34,0xa0,0xea,0x88,0x60,0xc4,0x70,0xe8
3546 fcb 0x30,0x06,0xe5,0x1c,0x20,0x84,0x20,0x9c
3547 fcb 0xa0,0x80,0xa0,0x1c,0xa8,0x80,0x88,0x22
3548 fcb 0x24,0x80,0x24,0xb0,0xe4,0x14,0xe4,0x80
3549 fcb 0xe0,0x86,0x00,0xd6,0x8c,0x80,0xb8,0xab
3550 fcb 0xaf,0xa2,0x84,0xe8,0x86,0x2f,0x8a,0xf5
3551 fcb 0xd4,0xff,0x86,0xef,0x8e,0xf4,0xc8,0x6c
3552 fcb 0xf5,0xf4,0x4c,0xf4,0xe8,0x74,0x04,0xee
3553 fcb 0xee,0xe0,0x26,0x2c,0x9f,0xec,0x90,0xe5
3554 fcb 0xbc,0xe5,0xf8,0xe0,0xfb,0xf4,0xb4,0xed
3555 fcb 0x4e,0xe4,0xe6,0xec,0x8c,0xe4,0xbf,0xed
3556 fcb 0x9f,0xe0,0xcc,0x7c,0xbf,0xed,0x9d,0xed
3557 fcb 0xad,0xf8,0xaf,0x64,0xef,0xed,0xed,0xe4
3558 fcb 0xa0,0x8c,0x20,0x95,0x30,0x38,0xa0,0x84
3559 fcb 0x64,0x80,0xe0,0x76,0x2c,0x20,0xb4,0x04
3560 fcb 0x3f,0xb1,0xa4,0x24,0x24,0x80,0x24,0xa9
3561 fcb 0x31,0x97,0xac,0x28,0x64,0x50,0xa0,0x04
3562 fcb 0x38,0x80,0xb4,0x8e,0x20,0xcc,0xbc,0x38
3563 fcb 0x64,0x8c,0xa0,0x90,0xe4,0xa0,0x64,0x99
3564 fcb 0x64,0xaf,0x24,0xe5,0x60,0x80,0xa4,0x3c
3565 fcb 0x2c,0x8e,0xb4,0xbc,0xa4,0xcc,0x24,0xcc
3566 endc