diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/disk.s	Sat Dec 08 19:57:01 2018 -0700
@@ -0,0 +1,3566 @@
+                *pragma nolist
+                include defs.s
+; Various references to Color Basic and Extended Color Basic which are listed here to allow this ROM to be built independently.
+XBWMST          equ 0x80c0
+L813C           equ 0x813c
+L8168           equ 0x8168
+XVEC3           equ 0x8273
+XVEC8           equ 0x8286
+XVEC18          equ 0x829c
+L8311           equ 0x8311
+L8316           equ 0x8316
+L836C           equ 0x836c
+L8748           equ 0x8748
+L880E           equ 0x880e
+XVEC15          equ 0x8846
+XVEC17          equ 0x88f0
+L8955           equ 0x8955
+L8C1B           equ 0x8c1b
+XVEC4           equ 0x8cf1
+XVEC9           equ 0x8e90
+L95AC           equ 0x95ac
+L962E           equ 0x962e
+L9650           equ 0x9650
+L96CB           equ 0x96cb
+L96EC           equ 0x96ec
+L975F           equ 0x975f
+L9FB5           equ 0x9fb5
+LA0E2           equ 0xa0e2
+BAWMST          equ 0xa0e8
+LA171           equ 0xa171
+LA176           equ 0xa176
+PUTCHR          equ 0xa282
+LA35F           equ 0xa35f
+LA37C           equ 0xa37c
+LA3ED           equ 0xa3ed
+LA3FB           equ 0xa3fb
+LA406           equ 0xa406
+LA426           equ 0xa426
+LA429           equ 0xa429
+LA42D           equ 0xa42d
+LA549           equ 0xa549
+LA59A           equ 0xa59a
+LA5A2           equ 0xa5a2
+LA5A5           equ 0xa5a5
+LA5AE           equ 0xa5ae
+LA5C7           equ 0xa5c7
+LA5DA           equ 0xa5da
+LA5E4           equ 0xa5e4
+LA603           equ 0xa603
+LA616           equ 0xa616
+LA61C           equ 0xa61c
+LA61F           equ 0xa61f
+LA928           equ 0xa928
+LA951           equ 0xa951
+LA7D1           equ 0xa7d1
+LA7E9           equ 0xa7e9
+LA974           equ 0xa974
+LAC37           equ 0xac37
+LAC44           equ 0xac44
+LAC46           equ 0xac46
+LAC60           equ 0xac60
+LAC73           equ 0xac73
+LAC7C           equ 0xac7c
+LACEF           equ 0xacef
+LAD19           equ 0xad19
+LAD21           equ 0xad21
+LAD33           equ 0xad33
+LAD9E           equ 0xad9e
+LADC6           equ 0xadc6
+LADD4           equ 0xadd4
+LADEB           equ 0xadeb
+LAE15           equ 0xae15
+LAF9A           equ 0xaf9a
+LAFA4           equ 0xafa4
+LAFB1           equ 0xafb1
+LB00C           equ 0xb00c
+LB01E           equ 0xb01e
+LB069           equ 0xb069
+LB143           equ 0xb143
+LB146           equ 0xb146
+LB148           equ 0xb148
+LB156           equ 0xb156
+LB244           equ 0xb244
+LB262           equ 0xb262
+LB166           equ 0xb166
+SYNCOMMA        equ 0xb26d
+LB26F           equ 0xb26f
+LB277           equ 0xb277
+LB2CE           equ 0xb2ce
+LB357           equ 0xb357
+LB3E6           equ 0xb3e6
+LB44A           equ 0xb44a
+LB4F3           equ 0xb4f3
+GIVABF          equ 0xb4f4
+LB50F           equ 0xb50f
+LB516           equ 0xb516
+LB654           equ 0xb654
+LB657           equ 0xb657
+LB659           equ 0xb659
+LB69B           equ 0xb69b
+LB6A4           equ 0xb6a4
+EVALEXPB        equ 0xb70b
+LB70E           equ 0xb70e
+LB738           equ 0xb738
+LB73D           equ 0xb73d
+LIST            equ 0xb764
+LB958           equ 0xb958
+LB95C           equ 0xb95c
+STRINOUT        equ 0xb99c
+LB99F           equ 0xb99f
+LB9A2           equ 0xb9a2
+LB9AC           equ 0xb9ac
+LB9AF           equ 0xb9af
+LB9C5           equ 0xb9c5
+LBB91           equ 0xbb91
+LBC14           equ 0xbc14
+LBC33           equ 0xbc33
+LBC35           equ 0xbc35
+LBC5F           equ 0xbc5f
+INT             equ 0xbcee
+LBDCC           equ 0xbdcc
+LBDD9           equ 0xbdd9
+                pragma noexpandcond
+                *pragma list
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; DISK EXTENDED COLOR BASIC
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+                ifeq DISKVER
+DHITOK          equ 0xe0                        ; highest command token
+CYEAR           equ '1                          ; ones digit of copyright year
+MINORVER        equ '0
+                else
+DHITOK          equ 0xe1                        ; highest command token
+CYEAR           equ '2                          ; ones digit for copyright year
+MINORVER        equ '1
+                endc
+                org DOSBAS
+                fcc 'DK'                        ; magic number Extended Basic uses to identify the presence of a Disk ROM
+LC002           bra LC00C                       ; entry point - jump around vector table
+DCNVEC          fdb DSKCON                      ; DSKCON indirect entry point
+DSKVAR          fdb DCOPC                       ; address of DSKCON parameter block
+                ifeq DISKVER-1
+DSINIT          fdb DOSINI                      ; vector to an initialization routine, the utility of which is unclear
+DOSVEC          fdb DOSCOM                      ; pointer to the actual location of the DOS command
+                endc
+LC00C           ldx #DBUF0                      ; point to start of Disk Basic memory
+LC00F           clr ,x+                         ; clear a byte
+                cmpx #DFLBUF                    ; at end of statically allocated Disk Basic memory?
+                bne LC00F                       ; brif not
+                ldx #LC109                      ; point to initializer for the command interpretation table
+                ldu #COMVEC+20                  ; point to command interpretation table location for Disk Basic
+                ldb #10                         ; ten bytes in each table entry
+                jsr LA59A                       ; initialize interpretation table
+                ldd #LB277                      ; syntax error address
+                std 3,u                         ; set command handler for "user" table to error
+                std 8,u                         ; set function handler for "user" table to error
+                clr ,u                          ; mark user table with 0 command keywords
+                clr 5,u                         ; mark user table with 0 function keywords
+                ldd #DXCVEC                     ; intercept Extended Basic's command handler
+                std COMVEC+13
+                ldd #DXIVEC                     ; intercept Extended Basic's function handler
+                std COMVEC+18
+                ldu #RVEC0                      ; point to first RAM vector
+LC03B           lda #0x7e                       ; op code of JMP extended
+                sta RVEC22                      ; set first byte of GET/PUT vector to JMP
+                sta ,u+                         ; set this vector to be a JMP instruction
+                ldd ,x++                        ; get vector destination
+                std ,u++                        ; set the vector destination
+                cmpx #LC139                     ; done the whole list?
+                bne LC03B                       ; brif not
+                ldx #DVEC22                     ; install handler for GET/PUT vector
+                stx RVEC22+1
+                ifeq DISKVER-1
+                ldx #DVEC20                     ; install replacement interpretation loop handler
+                stx RVEC20+1
+                endc
+                ldx #DUSRVC                     ; relocate USR vector table
+                stx USRADR
+                ldu #LB44A                      ; default USR address is illegal function call
+                ldb #10                         ; there are 10 vectors
+LC061           stu ,x++                        ; set a vector
+                decb                            ; done all?
+                bne LC061                       ; brif not
+                ldx #DNMISV                     ; install NMI handler
+                stx NMIVEC+1
+                lda #0x7e                       ; make it a JMP
+                sta NMIVEC
+                ldx #DIRQSV                     ; install IRQ handler (ECB and CB already made it a JMP)
+                stx IRQVEC+1
+                lda #19                         ; initialze the number of changes needed to trigger a FAT write
+                sta WFATVL
+                clr FATBL0                      ; mark all four FAT images as having no open files
+                clr FATBL1
+                clr FATBL2
+                clr FATBL3
+                ldx #DFLBUF                     ; point to the start of the disk "heap"
+                stx RNBFAD                      ; set start of random file buffers as the end of the allocated space
+                leax 0x100,x                    ; allocate 256 bytes for random file buffers by default
+                stx FCBADR                      ; save start of FCBs (and end of random file buffers)
+                leax 1,x                        ; leave an empty byte before FCBs (why?)
+                stx FCBV1                       ; set address of FCB 1
+                clr <<FCBTYP,x                  ; mark it closed
+                leax FCBLEN,x                   ; set address of FCB 2 (2 user FCBs allocated at startup)
+                stx FCBV1+2
+                clr <<FCBTYP,x                  ; mark it closed
+                leax FCBLEN,x                   ; set address of FCB 3 (system FCB)
+                stx FCBV1+4
+                clr <<FCBTYP,x                  ; mark it closed
+                lda #2                          ; set 2 active FCBs
+                sta FCBACT
+                leax FCBLEN,x                   ; point to end of active FCBs
+                tfr x,d                         ; put it in D so we can do stuff with it
+                tstb                            ; is it a partial memory page?
+                ifeq DISKVER
+                beq LC0C2                       ; brif not
+                else
+                beq LC0BD                       ; brif not
+                endc
+                inca                            ; round up
+                ifeq DISKVER-1
+LC0BD           bita #1                         ; is it even (multiple of 512)?
+                beq LC0C2                       ; brif so
+                inca                            ; round up to even 512 byte boundary
+                endc
+LC0C2           tfr a,b                         ; save start of graphics memory
+                addb #24                        ; reserve 4 graphics pages
+                stb TXTTAB                      ; set start of program there
+                jsr L96EC                       ; do graphics initialization (A is the start of grahpics memory)
+                lda BEGGRP                      ; get start of current grahpics page
+                adda #6                         ; make one page used
+                sta ENDGRP
+                ifeq DISKVER-1
+                jsr [DSINIT]                    ; do the pointless initialization routine
+                endc
+                bsr LC0F0                       ; initialize FDC stuff and interrupt any action underway
+                andcc #0xaf                     ; enable interrupts
+                ldx #LC139-1                    ; point to sign on message
+                jsr STRINOUT                    ; show sign on
+                ldx #DKWMST                     ; install warm start handler
+                stx RSTVEC
+                jmp LA0E2                       ; jump into mainline Color Basic
+DKWMST          nop                             ; flag warm start routine as valid
+                bsr LC0F0                       ; initialize FDC variables and interrupt any action underway
+                jsr LD2D2                       ; close files and do some other stuff
+                jmp XBWMST                      ; transfer control to ECB's warm start
+LC0F0           clr NMIFLG                      ; reset the NMI handler vector
+                clr RDYTMR                      ; disable the drive timeout counter
+                clr DRGRAM                      ; turn off all drive selects and motors (RAM copy)
+                clr DSKREG                      ; turn off all drive selects and motors (real hardware)
+                lda #0xd0                       ; send "force interrupt" to controller
+                sta FDCREG
+                exg a,a                         ; wait for status to stabilize
+                exg a,a
+                lda FDCREG                      ; clear the status indicator (no error handling - nothing useful to do anyway)
+                rts
+                ifeq DISKVER
+LC109           fcb 19                          ; number of keywords (commands)
+                else
+LC109           fcb 20                          ; number of keywords (commands)
+                endc
+                fdb LC192                       ; keyword table (commands)
+                fdb LC238                       ; handler (commands)
+                fcb 6                           ; number of keywords (functions)
+                fdb LC219                       ; keyboard table (functions)
+                fdb LC24E                       ; handler (functions)
+LC113           fdb DVEC0,DVEC1,DVEC2           ; RAM hook handler addresses
+                fdb DVEC3,DVEC4,DVEC5
+                fdb DVEC6,DVEC7,DVEC8
+                fdb XVEC9,DVEC10,DVEC11
+                fdb DVEC12,DVEC13,DVEC14
+                fdb DVEC15,DVEC12,DVEC17
+                fdb DVEC18
+; Sign on message
+LC139           fcc 'DISK EXTENDED COLOR BASIC 1.'
+                fcb MINORVER
+                fcb 0x0d
+                fcc 'COPYRIGHT (C) 198'
+                fcb CYEAR
+                fcc ' BY TANDY'
+                fcb 0x0d
+                fcc 'UNDER LICENSE FROM MICROSOFT'
+                fcb 0x0d,0x0d,0x00
+; Keyword list (commands)
+LC192           fcs 'DIR'                       ; 0xce
+                fcs 'DRIVE'                     ; 0xcf
+                fcs 'FIELD'                     ; 0xd0
+                fcs 'FILES'                     ; 0xd1
+                fcs 'KILL'                      ; 0xd2
+                fcs 'LOAD'                      ; 0xd3
+                fcs 'LSET'                      ; 0xd4
+                fcs 'MERGE'                     ; 0xd5
+                fcs 'RENAME'                    ; 0xd6
+                fcs 'RSET'                      ; 0xd7
+                fcs 'SAVE'                      ; 0xd8
+                fcs 'WRITE'                     ; 0xd9
+                fcs 'VERIFY'                    ; 0xda
+                fcs 'UNLOAD'                    ; 0xdb
+                fcs 'DSKINI'                    ; 0xdc
+                fcs 'BACKUP'                    ; 0xdd
+                fcs 'COPY'                      ; 0xde
+                fcs 'DSKI$'                     ; 0xdf
+                fcs 'DSKO$'                     ; 0xe0
+                ifeq DISKVER-1
+                fcs 'DOS'                       ; 0xe1
+                endc
+; Jump table (commands)
+LC1F1           fdb DIR                         ; 0xce DIR
+                fdb DRIVE                       ; 0xcf DRIVE
+                fdb FIELD                       ; 0xd0 FIELD
+                fdb FILES                       ; 0xd1 FILES
+                fdb KILL                        ; 0xd2 KILL
+                fdb LOAD                        ; 0xd3 LOAD
+                fdb LSET                        ; 0xd4 LSET
+                fdb MERGE                       ; 0xd5 MERGE
+                fdb RENAME                      ; 0xd6 RENAME
+                fdb RSET                        ; 0xd7 RSET
+                fdb SAVE                        ; 0xd8 SAVE
+                fdb WRITE                       ; 0xd9 WRITE
+                fdb VERIFY                      ; 0xda VERIFY
+                fdb UNLOAD                      ; 0xdb UNLOAD
+                fdb DSKINI                      ; 0xdc DSKINI
+                fdb BACKUP                      ; 0xdd BACKUP
+                fdb COPY                        ; 0xde COPY
+                fdb DSKI                        ; 0xdf DSKI$
+                fdb DSKO                        ; 0xe0 DSKO$
+                ifeq DISKVER-1
+                fdb DOS                         ; 0xe1 DOS
+                endc
+; Keyword list (functions)
+LC219           fcs 'CVN'                       ; 0xa2
+                fcs 'FREE'                      ; 0xa3
+                fcs 'LOC'                       ; 0xa4
+                fcs 'LOF'                       ; 0xa5
+                fcs 'MKN$'                      ; 0xa6
+                fcs 'AS'                        ; 0xa7 (here to avoid conflict with ASC)
+; Jump table (functions)
+LC22C           fdb CVN                         ; 0xa2 CVN
+                fdb FREE                        ; 0xa3 FREE
+                fdb LOC                         ; 0xa4 LOC
+                fdb LOF                         ; 0xa5 LOF
+                fdb MKN                         ; 0xa6 MKN$
+                fdb LB277                       ; 0xa7 AS (not actually a function)
+; Command handler
+LC238           cmpa #DHITOK                    ; is it a Disk Basic valid command?
+                bhi LC244                       ; brif not
+                ldx #LC1F1                      ; point to jump table
+                suba #0xce                      ; normalize Disk Basic tokens to 0
+                jmp LADD4                       ; return to mainline to execute command
+; The next two instructions are completely pointless. If we get here, the comparison has already
+; been done and the branch condition is the exact opposite of what brought us here.
+LC244           cmpa #DHITOK                    ; is it a Disk Basic token?
+                lbls LB277                      ; brif not
+                jmp [COMVEC+33]                 ; transfer control to user command handler
+; Function handler
+LC24E           cmpb #(0xa7-0x80)*2             ; is it a Disk Basic function token?
+                bls LC256                       ; brif so
+                jmp [COMVEC+38]                 ; transfer control to user handler if not
+LC256           subb #(0xa2-0x80)*2             ; normalize Disk Basic tokens to 0
+                pshs b                          ; save jump table offset
+                jsr LB262                       ; evaluate parenthetical expression
+                puls b                          ; get back jump table offset
+                ldx #LC22C                      ; point to jump table
+                jmp LB2CE                       ; rejoin mainline code to transfer control
+; Error handler
+DVEC17          puls y                          ; get back original caller
+                jsr LAD33                       ; reset some stuff like CONT
+                jsr LD2D2                       ; clean up some Disk Basic stuff
+                pshs y,b                        ; put return address back and save error code
+                jsr DVEC7                       ; close all files
+                puls b                          ; get back error code
+                cmpb #2*27                      ; is it a Disk Basic error code?
+                lblo XVEC17                     ; brif not - pass it to Extended Basic
+                leas 2,s                        ; dump the return address
+                jsr LA7E9                       ; stop tape
+                jsr LA974                       ; stop sound
+                clr DEVNUM                      ; reset output to screen
+                jsr LB95C                       ; do a newline
+                jsr LB9AF                       ; do a ?
+                ldx #LC290-2*27                 ; point to error message table
+                jmp LAC60                       ; rejoin mainline error handler
+; Error strings (note that NE error is provided by Extended Basic)
+LC290           fcc 'BR'                        ; 27 Bad record
+                fcc 'DF'                        ; 28 Disk full
+                fcc 'OB'                        ; 29 Out of buffer space
+                fcc 'WP'                        ; 30 Write protected
+                fcc 'FN'                        ; 31 Bad file name
+                fcc 'FS'                        ; 32 Bad file structure
+                fcc 'AE'                        ; 33 File already exists
+                fcc 'FO'                        ; 34 Field overflow
+                fcc 'SE'                        ; 35 Set to non-fielded string
+                fcc 'VF'                        ; 36 Verify error
+                fcc 'ER'                        ; 37 Input or write past end of record
+BASEXT          fcc 'BAS'                       ; default Basic program file extension
+DEFEXT          fcc '   '                       ; default blank extension (three spaces)
+DATEXT          fcc 'DAT'                       ; default extension for data files
+BINEXT          fcc 'BIN'                       ; default extension for binary files
+; "CLS" vector handler. Extended Basic also chose to use this vector as a way to hook into
+; the GET/PUT commands, the RENUM token check, and the Extended Basic "functions as commands"
+; interpretation scheme. Only the GET/PUT hook is used. Checking the caller address is hacky
+; but unavoidable here.
+DVEC22          pshs x,cc                       ; save scratch register and flags
+                ldx 3,s                         ; get caller address
+                cmpx #L975F                     ; is it coming from GET/PUT?
+                bne LC2BF                       ; brif not
+                cmpa #'#                        ; is it GET # or PUT # (disk file operations)?
+                beq LC2C1                       ; brif so - don't return to mainline
+LC2BF           puls cc,x,pc                    ; restore scratch register, flags, and return to mainline
+; GET/PUT handler for random file access
+LC2C1           leas 5,s                        ; remove saved state from above and don't return to mainline
+                jsr LC82E                       ; evaluate device number and get FCB pointer
+                stx FCBTMP                      ; save the FCB pointer
+                clr FCBGET,x                    ; reset the get data pointer
+                clr FCBGET+1,x
+                clr FCBPUT,x                    ; reset the put data pointer
+                clr FCBPUT+1,x
+                clr FCBPOS,x                    ; reset print position
+                lda FCBDRV,x                    ; get drive number for the file
+                sta DCDRV                       ; set it as the DSKCON drive number
+                jsr GETCCH                      ; end of statement?
+                beq LC2EA                       ; brif so - use current record
+                jsr SYNCOMMA                    ; insist on a comma
+                ifeq DISKVER
+                jsr LB3E6                       ; evaluate expression to D
+                else
+                jsr LB73D                       ; get unsigned 16 bit number to X
+                tfr x,d                         ; stash it in D so we can use X as a pointer
+                endc
+LC2E6           ldx FCBTMP                      ; get back FCB pointer
+                std FCBREC,x                    ; set the current record number
+                ifeq DISKVER
+LC2EA           jsr LC685                       ; bump record number
+                else
+LC2EA           ldd FCBREC,x                    ; get desired record number
+                beq LC30B                       ; brif 0 - records start at 1
+                jsr LC685                       ; bump record number
+                endc
+                ldd FCBRLN,x                    ; get record length
+                ldx FCBBUF,x                    ; point to FCB data buffer
+                pshs x,b,a                      ; save them
+                leax -2,u                       ; point to record number (but zero based)
+                jsr L9FB5                       ; do unsigned multiply of record length and record number
+                pshs u,y                        ; save product (this is the file offset to the record)
+                lda ,s+                         ; is MSB 0?
+                bne LC30B                       ; brif not - record number too big
+                puls x                          ; middle two bytes are sector number in file - retrieve it
+                puls b                          ; LSB is offset into the sector - retrieve it
+LC306           cmpx #(35-1)*18                 ; is it more than the maximum number of sectors a file can have?
+                blo LC310                       ; brif so
+LC30B           ldb #2*27                       ; code for bad record
+                jmp LAC46                       ; raise error
+LC310           ldu FCBTMP                      ; get pointer to FCB
+                cmpx FCBSOF,u                   ; is it the same sector we're already handling?
+                lbeq LC3CF                      ; brif so
+                pshs x,b                        ; save sector number and sector offset
+                lda FCBFLG,u                    ; were we doing get or put?
+                beq LC324                       ; brif we were doing get
+                clr FCBFLG,u                    ; flag doing get
+                ldb #3                          ; write operation code for DSKCON
+                bsr LC357                       ; write the sector data
+LC324           ldd 1,s                         ; get sector number
+                jsr LC784                       ; convert to a granule offset
+                pshs b                          ; save granule offset
+                jsr LC779                       ; calculate starting sector of granule number
+                negb                            ; make negative
+                addb 3,s                        ; add LS byte of sector number
+                incb                            ; add one - sectors in FCB start at 1
+                stb FCBSEC,u                    ; set sector
+                ldb FCBFGR,u                    ; get first granule in file
+                jsr LC755                       ; fetch FAT pointer
+                leau FATCON,x                   ; point to actual granule table
+                lda ,s                          ; get number of granules offset to the record
+                inca                            ; bump it (compensate for deca below)
+LC33E           leax ,u                         ; point X to entry for this granule
+                abx
+                deca                            ; are we at the correct one?
+                beq LC37B                       ; bif not
+                stb ,s                          ; save granule offset on stack
+                ldb ,x                          ; get next granule in file
+                cmpb #0xc0                      ; is it "end of file" flag?
+                blo LC33E                       ; brif not
+                ldb ,s                          ; get offset to previous granule
+                tst VD8                         ; get or put?
+                bne LC366                       ; brif put
+LC352           ldb #2*23                       ; code for input past end of file
+                jmp LAC46                       ; raise error
+LC357           leax FCBCON,u                   ; point to data buffer for FCB
+LC35A           stb DCOPC                       ; set operation code for DSKCON
+                stx DCBPT                       ; set buffer pointer for DSKCON
+                leax ,u                         ; point to FCB
+                jsr LC763                       ; convert FCB track and sector to DSKCON parameters
+                jmp LD6F2                       ; read or write the sector
+LC366           pshs x,a                        ; save granule counter and pointer to last used granule
+                jsr LC7BF                       ; find a free granule
+                tfr a,b                         ; save allocated granule
+                puls a,u                        ; get last granule pointer and counter off stack
+                stb ,u                          ; add it to the file's granule chain
+                deca                            ; do we have enough of them?
+                bne LC366                       ; brif not - allocate another
+                pshs x,b                        ; save alocated granule and pointer
+                jsr LC71E                       ; write the FAT out
+                puls b,x                        ; get back allocated granule and pointer
+LC37B           leas 1,s                        ; remove granule number
+                ldu FCBTMP                      ; point to FCB
+                stb FCBCGR,u                    ; save current granule
+                lda #0xff                       ; set to illegal sector offset to force sector data to be read
+                sta FCBSOF,u
+                lda ,x                          ; get next granule pointer
+                cmpa #0xc0                      ; last granule?
+                blo LC3B2                       ; brif not
+                anda #0x3f                      ; get only the number of sectors used
+                cmpa FCBSEC,u                   ; compare calculated sector to current sector
+                bhs LC3B2                       ; brif sector is <= last one in file
+                lda VD8                         ; GET or PUT?
+                beq LC352                       ; brif GET - do IE error
+                lda FCBSEC,u                    ; get sector number from FCB
+                ora #0xc0                       ; add "last granule" flag bits
+                sta ,x                          ; update FAT
+                jsr LC5A9                       ; write FAT if needed
+                ldx FCBRLN,u                    ; get record length
+                cmpx #SECLEN                    ; exactly one sector?
+                bne LC3AD                       ; brif not
+                cmpx FCBLST,u                   ; is number of bytes in last sector a full sector?
+                beq LC3B2                       ; brif so
+                lda #0x81                       ; set "presaved" flag and force number of bytes to be 256
+                skip1                           ; skip next byte ("BRN")
+LC3AD           clra                            ; set number of bytes in last sector to 0
+                clrb                            ; clear LS byte of D
+                std FCBLST,u                    ; set number of bytes used in last sector
+LC3B2           ldb #2                          ; DSKCON read operation
+                ldx FCBRLN,u                    ; get record length
+                cmpx #SECLEN                    ; exactly one sector?
+                bne LC3C8                       ; brif not exactly
+                leas 7,s                        ; clean up stack
+                ldx FCBBUF,u                    ; point to start of random file buffer
+                lda VD8                         ; is it GET or PUT?
+                beq LC3C5                       ; brif GET
+                ldb #3                          ; DSKCON write opreation
+LC3C5           jmp LC35A                       ; go read or write a sector
+LC3C8           jsr LC357                       ; read a sector into data buffer
+                puls b,x                        ; get back byte offset to record
+                stx FCBSOF,u                    ; save sector offset
+LC3CF           pshs b                          ; save sector byte offset
+                jsr LC755                       ; point to FAT
+                leax FATCON,x                   ; point to FAT data
+                ldb FCBCGR,u                    ; get current granulenumber
+                abx                             ; point to granule data
+                lda ,x                          ; get this granule's next pointer
+                cmpa #0xc0                      ; end of file flag?
+                blo LC40A                       ; brif not
+                anda #0x3f                      ; convert to number of sectors in final granule
+                cmpa FCBSEC,u                   ; are we asking for the last sector?
+                bne LC40A                       ; brif not
+                ldd FCBLST,u                    ; get number of bytes in last sector
+                anda #0x7f                      ; lose pre-saved flag
+                pshs d                          ; save number of bytes in last sector
+                clra                            ; zero extend byte offset
+                ldb 2,s                         ; get byte offset
+                addd 3,s                        ; add in record length
+                cmpd ,s++                       ; is it more than last sector?
+                bls LC40A                       ; brif the whole record fits
+                tst VD8                         ; is it GET?
+                lbeq LC352                      ; brif so - IE error if file doesn't have a whole record available
+                ifeq DISKVER
+                anda #1                         ; keep only bit 0 of byte count
+                ora #0x80                       ; set pre-saved flag bit
+                else
+                cmpd #SECLEN                    ; is it a whole sector we need?
+                bls LC405                       ; brif not
+                ldd #SECLEN                     ; force one sector length
+LC405           ora #0x80                       ; set pre-saved flag bit
+                endc
+                std FCBLST,u                    ; save number of bytes in last sector
+LC40A           puls b                          ; get byte offset
+                leax FCBCON,u                   ; point to data buffer
+                abx                             ; offset into data buffer
+                ldu 2,s                         ; point to position in random file buffer
+                pshs b                          ; save byte offset
+                lda #-1                         ; convert D into a negative 2 byte number representing unused bytes in sector
+                addd 1,s
+                bhs LC421                       ; brif there are enough bytes to finish record
+                std 1,s                         ; save new temporary record length counter
+                puls b                          ; restore byte counter
+                negb                            ; negate it (B is number of bytes available to a record in this sector)
+                bra LC429                       ; move the data
+LC421           ldb 2,s                         ; get remaining record length
+                clr 1,s                         ; clear the temporary record length counter
+                clr 2,s
+                leas 1,s                        ; we no longer need byte offset
+LC429           lda VD8                         ; GET?
+                beq LC42F                       ; brif so
+                exg x,u                         ; swap pointers so we write to data buffer
+LC42F           jsr LA59A                       ; copy data
+                stu 2,s                         ; save new record pointer
+                ldu FCBTMP                      ; get pointer to FCB
+                lda VD8                         ; GET?
+                beq LC43E                       ; brif so
+                sta FCBFLG,u                    ; flag as PUT
+                stx 2,s                         ; save buffer pointer
+LC43E           ldx FCBSOF,u                    ; get sector offset count
+                leax 1,x                        ; bump it
+                clrb                            ; byte offset in this new sector is 0
+                ldu ,s                          ; get length of record needed
+                lbne LC306                      ; brif not already completed ar ecord
+                puls a,b,x,pc                   ; clean up stack and return
+; OPEN handler
+DVEC0           leas 2,s                        ; don't return mainline
+                jsr LB156                       ; evaluate mode expression
+                jsr LB6A4                       ; get first character in the mode string
+                pshs b                          ; save it
+                jsr LA5A2                       ; parse device number
+                tstb                            ; disk file?
+                lble LA603                      ; return mainline if not disk file
+                puls a                          ; get mode
+                pshs a,b                        ; save mode and file number
+                clr DEVNUM                      ; reset device to screen
+                jsr SYNCOMMA                    ; insist on a comma
+                ldx #DATEXT                     ; point to "DAT" extension as default for data file
+                jsr LC938                       ; parse file name
+                ldd #0x01ff                     ; file type is "data" (1) and ASCII
+                std DFLTYP                      ; save file type
+                ldx #SECLEN                     ; default record length - one whole sector
+                jsr GETCCH                      ; is there a record length specifier?
+                beq LC481                       ; brif not
+                jsr SYNCOMMA                    ; insist on comma
+                jsr LB3E6                       ; evaluate record length
+                ldx FPA0+2                      ; get evaluated length
+LC481           stx DFFLEN
+                lbeq LB44A                      ; record length of 0 makes no sense of error if so
+                jsr LA5C7                       ; raise error if more stuff
+                puls a,b                        ; get mode and fil enumber
+LC48D           pshs a                          ; save mode
+                jsr LC749                       ; point to FCB for this file
+                lbne LA61C                      ; brif the file is already open
+                stx FCBTMP                      ; save FCB pointer
+                jsr LC79D                       ; make sure FAT is valid
+                jsr LC68C                       ; search for requested file
+                puls b                          ; get mode
+                lda #INPFIL                     ; input file flag
+                pshs a                          ; save it
+                cmpb #'I                        ; input mode?
+                bne LC4C7                       ; brif not
+                jsr LC6E5                       ; see if match was found
+                jsr LC807                       ; check if it's already open
+                ldx V974                        ; point to directory data
+                ldd DIRTYP,x                    ; get file type and ASCII flag
+                std DFLTYP                      ; save it
+                bsr LC52D                       ; initialize FCB
+                jsr LC627                       ; go read first sector from file
+LC4BB           jsr LC755                       ; point to FAT
+                inc <<FAT0,x                    ; bump number of open files on this disk
+                ldx FCBTMP                      ; get back FCB pointer
+                puls a                          ; get file type
+                sta <<FCBTYP,x                  ; save file type
+                rts
+LC4C7           asl ,s                          ; set type to output
+                cmpb #'O                        ; output requested?
+                bne LC4E8                       ; brif not
+                tst V973                        ; did file exist?
+                beq LC4E1                       ; brif not
+                jsr LC6FC                       ; kill the old file
+                lda V973                        ; get directory sector number of old file
+                sta V977                        ; save as first free directory entry
+                ldx V974                        ; get directory image of old file
+                stx V978                        ; asve it as first free entry
+                ifeq DISKVER
+LC4E1           bsr LC567                       ; set up new directory entry on disk
+                else
+LC4E1           jsr LC567                       ; set up new directory entry on disk
+                endc
+                bsr LC538                       ; initialize the file buffer
+                bra LC4BB                       ; finish setting up FCB
+LC4E8           cmpb #'R                        ; random file?
+                beq LC4F2                       ; brif so
+                cmpb #'D                        ; direct file?
+                lbne LA616                      ; brif not - bad file mode
+LC4F2           asl ,s                          ; set file type to random
+                ldd RNBFAD                      ; get address of random file buffer area
+                pshs d                          ; save it
+                addd DFFLEN                     ; add in record length
+                bcs LC504                       ; brif we overflowed memory
+                cmpd FCBADR                     ; is it more than FCB data area?
+                bls LC509                       ; brif not
+LC504           ldb #2*29                       ; code for out of buffer space
+                jmp LAC46                       ; raise error
+LC509           pshs d                          ; save new end of buffer area
+                tst V973                        ; did the file exist?
+                bne LC514                       ; brif so
+                bsr LC567                       ; set up directory
+                ifeq DISKVER
+LC514           bsr LC52D                       ; inistialize FCB
+                else
+                bra LC519                       ; initialize FCB
+LC514           lda #0xff                       ; set file type match = 0xff (all types)
+                jsr LC807                       ; see if any open file matches and AO error if so
+LC519           bsr LC52D                       ; initialize FCB
+                endc
+                com FCBSOF,x                    ; set FCBSOF to 0xff (illegal offset) to force new sector to be read
+                inc FCBREC+1,x                  ; set record number to 1
+                puls a,b,u                      ; D = end of buffer, U = start of buffer
+                std RNBFAD                      ; save start of free buffer space
+                stu FCBBUF,x                    ; save buffer pointer in FCB
+                ldu DFFLEN                      ; get record length
+                stu FCBRLN,x                    ; save in FCB
+                bra LC4BB                       ; finish setting things up
+LC52D           bsr LC538                       ; initialize FCB
+                ldu V974                        ; get directory image
+                ldu DIRLST,u                    ; get number of bytes in last sector
+                stu FCBLST,x                    ; save it
+                rts
+LC538           ldx FCBTMP                      ; get FCB pointer
+                ldb #FCBCON                     ; number of control bytes
+LC53C           clr ,x+                         ; clear a control byte
+                decb                            ; done all?
+                bne LC53C                       ; brif not
+                ldx FCBTMP                      ; get back FCB pointer
+                lda DCDRV                       ; set drive number
+                sta FCBDRV,x
+                lda V976                        ; get first granule
+                sta FCBFGR,x                    ; save it in FCB
+                sta FCBCGR,x                    ; also set as current granule
+                ldb V973                        ; get directory sector offset
+                subb #3                         ; directory sectors start at 3
+                aslb                            ; 8 directory entries per sector
+                aslb
+                aslb
+                pshs b                          ; save sector offset
+                ldd V974                        ; get directory pointer
+                subd #DBUF0                     ; calculate offset in sector buffer
+                lda #8                          ; 8 directory entries per sector
+                mul                             ; now A contains 0 to 7
+                adda ,s+                        ; add to directory sector offset
+                sta FCBDIR,x                    ; save directory entry number in FCB
+                rts
+LC567           ldb #28*2                       ; code for disk full
+                lda V977                        ; get sector number of first empty entry
+                lbeq LAC46                      ; brif none found
+                sta V973                        ; save sector number of first entry
+                sta DSEC                        ; set DSKCON sector parameter
+                ldb #2                          ; DSKCON read operation
+                stb DCOPC
+                jsr LD6F2                       ; read sector
+                ldx V978                        ; get address of RAM image of unused directory
+                stx V974                        ; save as current entry
+                leau ,x                         ; point to directory image
+                ldb #DIRLEN                     ; set counter to clear the entry
+LC586           clr ,x+                         ; clear a byte
+                decb                            ; done all?
+                bne LC586                       ; brif not
+                ldx #DNAMBF                     ; point to file name
+                ldb #11                         ; 8.3 total number of characters
+                jsr LA59A                       ; copy file name into directory
+                ldd DFLTYP                      ; get file type and ASCII flag
+                std <<0,u                       ; save in directory
+                ldb #33                         ; first granule to check
+                jsr LC7BF                       ; find first gree granule
+                sta V976                        ; save granule found
+                sta 2,u                         ; save as first granule in file
+                ldb #3                          ; DSKCON write operation
+                stb DCOPC
+                jsr LD6F2                       ; write out directory entry
+LC5A9           pshs u,x,b,a                    ; save registers
+                jsr LC755                       ; point to FAT
+                inc FAT1,x                      ; mark FAT as changed
+                lda FAT1,x                      ; have enough things changed?
+                cmpa WFATVL
+                blo LC5BA                       ; brif not
+                jsr LC71E                       ; write FAT out
+LC5BA           puls a,b,x,u,pc                 ; restore registers and return
+; Generic input handler
+DVEC4           lda DEVNUM                      ; get device number
+                lble XVEC4                      ; brif not disk file
+                leas 2,s                        ; don't return mainline if disk
+LC5C4           pshs x,b                        ; save registers
+                clr CINBFL                      ; clear EOF flag
+                ldx #FCBV1-2                    ; point to input file buffer table (-2 here to avoid decrementing device)
+                ldb DEVNUM                      ; get device number
+                aslb                            ; two bytes per pointer
+                ldx b,x                         ; get pointer to FCB
+                ldb FCBTYP,x                    ; get type of file
+                cmpb #RANFIL                    ; random file?
+                bne LC5EC                       ; brif not
+                ldd FCBGET,x                    ; get record counter
+                cmpd FCBRLN,x                   ; compare to size of record
+                bhs LC5FE                       ; brif pointer is after end of record - handle empty buffer
+                addd #1                         ; move pointer forward
+                std FCBGET,x                    ; save new read pointer
+                ldx FCBBUF,x                    ; point to data buffer
+                leax d,x                        ; offset to buffer location
+                lda -1,x                        ; get the character (before the increment)
+                puls b,x,pc                     ; return the character from the record
+LC5EC           ldb FCBCFL,x                    ; has a character been "ungot"?
+                beq LC5F9                       ; brif not
+                lda FCBCDT,x                    ; get ungot character
+                clr FCBCFL,x                    ; clear ungot flag
+                puls b,x,pc                     ; restore registers and return
+LC5F9           ldb FCBDFL,x                    ; is there any data left to read?
+                beq LC602                       ; brif so
+LC5FE           com CINBFL                      ; flag EOF
+                puls b,x,pc                     ; restore registers and return
+LC602           ldb FCBCPT,x                    ; get character pointer
+                inc FCBCPT,x                    ; bump saved pointer
+                dec FCBLFT,x                    ; anything left?
+                beq LC611                       ; brif buffer is empty
+                abx                             ; add offset into buffer
+                lda FCBCON,x                    ; get actual character (offset over the FCB control structure)
+                puls b,x,pc                     ; restore registers and return
+LC611           pshs u,y                        ; save register
+                clra                            ; zero extend offset
+                leau d,x                        ; now U has buffer offset
+                lda FCBCON,u                    ; get character to return (offset over FCB control structure)
+                pshs a                          ; save return value
+                clr FCBCPT,x                    ; reset character pointer
+                lda FCBDRV,x                    ; set DSKCON to the correct drive
+                sta DCDRV
+                bsr LC627                       ; read a sector
+                puls a,y,u                      ; restore registers and get back return value
+                puls b,x,pc                     ; restore registers and return
+LC627           lda FCBSEC,x                    ; get current sector number
+LC629           inca                            ; bump sector counter
+                pshs a                          ; save sector counter for later
+                cmpa #9                         ; end of granule?
+                bls LC631                       ; brif not
+                clra                            ; reset granule sector offset
+LC631           sta FCBSEC,x                    ; save sector offset
+                ldb FCBCGR,x                    ; get granule number
+                leau ,x                         ; save FCB pointer
+                jsr LC755                       ; point to correct FAT image
+                abx                             ; now X points to granule data
+                ldb FATCON,x                    ; get next granule pointer (offset past control data structure)
+                leax ,u                         ; reset FCB pointer
+                cmpb #0xc0                      ; is the current granule the last one?
+                bhs LC64D                       ; brif so
+                puls a                          ; get sector number
+                suba #10                        ; did it overflow the granule?
+                bne LC65E                       ; brif not
+                stb FCBCGR,x                    ; save new granule number
+                bra LC629                       ; set variables for new granule
+LC64D           andb #0x3f                      ; get number of sectors in the granule
+                cmpb #9                         ; is it more than a granule has?
+                bls LC658                       ; brif not
+LC653           ldb #2*32                       ; code for bad file structure
+                jmp LAC46                       ; raise error
+LC658           subb ,s+                        ; subtract current sector number and also clean stack
+                bcs LC67D                       ; brif past last sector
+                tfr b,a
+LC65E           pshs a                          ; save sector number difference
+                bsr LC685                       ; bump record number
+                lda #2                          ; set up for read
+                sta DCOPC
+                jsr LC763                       ; set DSKCON variables for correct track and sector
+                leau FCBCON,x                   ; point past control structure to actual buffer
+                stu DCBPT                       ; set read destination
+                jsr LD6F2                       ; go ahead and read the sector
+                clr FCBLFT,x                    ; set buffer left to full sector
+                ldb ,s+                         ; get sector number back
+                bne LC684                       ; brif not last sector
+                ldd FCBLST,x                    ; get bytes in last sector
+                bne LC681                       ; brif bytes in last sector is nonzero
+LC67D           clrb                            ; set remaining bytes to 256
+                com FCBDFL,x                    ; flag buffer empty
+LC681           stb FCBLFT,x                    ; save number of bytes in buffer
+LC684           rts
+LC685           ldu FCBREC,x                    ; get current record number
+                leau 1,u                        ; bump it
+                stu FCBREC,x                    ; save new record number
+                rts
+; Scan directory for file name; return sector number in V973, granule in V976,
+; and pointer to directory data in V974. If disk is full, pointer in V978,
+; and first unused sector in V977 (and V973 is 0)
+LC68C           clr V973                        ; clear sector number (for not found)
+                clr V977                        ; clear temp sector number
+                ldd #0x1102                     ; set up to read track 17
+                sta DCTRK
+                stb DCOPC
+                ldb #3                          ; start with sector 3
+LC69B           stb DSEC                        ; set DSKCON sector
+                ldu #DBUF0                      ; read to global buffer
+                stu DCBPT
+                jsr LD6F2                       ; read directory sector
+LC6A5           stu V974                        ; set pointer to directory entry data
+                leay ,u                         ; save start of directory entry
+                lda ,u                          ; NUL (for a deleted entry)?
+                bne LC6D6                       ; brif not
+                bsr LC6D9                       ; set unused pointers
+LC6B0           ldx #DNAMBF                     ; point to desired file name
+LC6B3           lda ,x+                         ; does a character match?
+                cmpa ,u+
+                bne LC6C7                       ; brif not
+                cmpx #DNAMBF+11                 ; end of file name?
+                bne LC6B3                       ; brif not
+                stb V973                        ; save sector number for match
+                lda FCBFGR,u                    ; set first granule in file
+                sta V976
+                rts
+LC6C7           leau DIRLEN,y                   ; point to next directory entry
+                cmpu #DBUF0+SECLEN              ; end of sector?
+                bne LC6A5                       ; brif not - search another
+                incb                            ; move to next sector
+                cmpb #11                        ; 11 sectors in directory - checked all of them?
+                bls LC69B                       ; brif more sectors
+                rts
+LC6D6           coma                            ; is first byte of file name 0xff?
+                bne LC6B0                       ; brif not - actually do a search
+LC6D9           lda V977                        ; have we already found an unused entry?
+                bne DVEC12                      ; brif so
+                stb V977                        ; save sector number for unused entry
+                stu V978                        ; save pointer to unused entry
+DVEC12          rts                             ; NOTE: this is used as a dummy do-nothing RAM hook handler
+LC6E5           ldb #2*26                       ; code for NE error
+                tst V973                        ; was entry found?
+                bne DVEC12                      ; brif so
+                jmp LAC46                       ; raise error
+; KILL command
+KILL            jsr LC935                       ; parse file name
+                jsr LA5C7                       ; brif something after file name
+                jsr LC79D                       ; load FAT data
+                bsr LC68C                       ; look up file
+                bsr LC6E5                       ; raise error if not found
+LC6FC           lda #0xff                       ; file type to match (all types)
+                jsr LC807                       ; find any file that matches type
+                ldx V974                        ; get directory entry pointer
+                clr ,x                          ; mark it as unused
+                ldb #3                          ; set up to write
+                stb DCOPC
+                jsr LD6F2                       ; write out the updated directory sector
+                ldb DIRGRN,x                    ; get starting granule of file
+LC70F           bsr LC755                       ; point to correct FAT
+                leax FATCON,x                   ; skip control structure
+                abx                             ; now X points to next granule
+                ldb ,x                          ; get next granule pointer
+                lda #0xff                       ; mark granule free
+                sta ,x
+                cmpb #0xc0                      ; was it last one?
+                blo LC70F                       ; brif not
+; Write FAT to drive
+LC71E           ldu #DBUF0                      ; point to global sector buffer
+                stu DCBPT                       ; point DSKCON there
+                ldd #0x1103                     ; set up to write track 17
+                sta DCTRK
+                stb DCOPC
+                ldb #2                          ; FAT is in sector 2
+                stb DSEC
+                bsr LC755                       ; point to proper FAT entry
+                clr FAT1,x                      ; mark FAT as having no outstanding changes
+                leax FATCON,x                   ; move past control structure
+                ldb #GRANMX                     ; get total granule count in a FAT
+                jsr LA59A                       ; copy the FAT data to buffer
+                ifeq DISKVER
+LC739           clr ,x+                         ; clear a byte
+                cmpx #DBUF0+SECLEN              ; end of sector?
+                else
+LC739           clr ,u+                         ; clear out the rest of the sector (to avoid junk going into it)
+                cmpu #DBUF0+SECLEN              ; end of sector?
+                endc
+                ifeq DISKVER-1
+                bne LC739                       ; brif not
+                endc
+                jmp LD6F2                       ; go write the FAT sector out
+; Point X to the correct FCB based on DEVNUM (or B if entering at LC749)
+LC744           pshs b                          ; save register
+                ldb DEVNUM                      ; get device number
+                skip2
+LC749           pshs b                          ; save register
+                lslb                            ; two bytes per pointer
+                ldx #FCBV1-2                    ; point to FCB table (-2 to adjust for 1-based file numbers)
+                ldx b,x                         ; get pointer
+                ldb <<FCBTYP,x                  ; set flags for file type
+                puls b,pc                       ; restore register and return
+; Point X to FAT image for the selected drive
+LC755           pshs b,a                        ; save registers
+                lda DCDRV                       ; get drive number
+                ldb #FATLEN                     ; get size of FAT mirror
+                mul                             ; calculate offset from first FAT image
+                ldx #FATBL0                     ; point to first FAT image
+                leax d,x                        ; offset to correct one
+                puls a,b,pc                     ; restore registers and return
+; Set up DSKCON variables to point to the correct sector and track for the current file position
+LC763           ldb FCBCGR,x                    ; get granule number
+                lsrb                            ; two granules per track
+                stb DCTRK                       ; save track
+                cmpb #17                        ; is it below the directory?
+                blo LC76E                       ; brif so
+                inc DCTRK                       ; skip directory track if not
+LC76E           aslb                            ; double track number
+                negb                            ; subtract from actual granule number: -(TRK*2)+CGR
+                addb FCBCGR,x
+                bsr LC779                       ; set B=9 for odd granule, B=0 for even
+                addb FCBSEC,x                   ; add granule sector offset
+                stb DSEC                        ; set DSKCON sector
+                rts
+LC779           pshs b,a                        ; temp store original
+                aslb                            ; times 2
+                rola
+                aslb                            ; times 4
+                rola
+                aslb                            ; times 8
+                rola
+                addd ,s++                       ; times 9
+                rts
+; Convert sector offset in D to a granule offset (0-67) in B (lose fractional part)
+LC784           clr ,-s                         ; make a temporary counter
+LC786           inc ,s                          ; bump division counter
+                subd #90                        ; does 90 go?
+                bpl LC786                       ; brif so
+                lda ,s                          ; get quotient (+1)
+                stb ,s                          ; save remainder (negative)
+                ldb #10                         ; multiply result by 10 (we divided by 90)
+                mul
+                puls a                          ; get back remainder
+LC796           decb                            ; decrement granule count
+                adda #9                         ; have we used up the remainder?
+                bmi LC796                       ; brif not
+                clra                            ; zero extend result
+LC79C           rts
+; Make sure FAT data is valid
+LC79D           bsr LC755                       ; point to correct FAT
+                tst <<FAT0,x                    ; any open files?
+                bne LC79C                       ; brif so
+                clr FAT1,x                      ; reset change count
+                leau FATCON,x                   ; point past control structure
+                ldx #DBUF0                      ; point DSKCON to sector buffer
+                stx DCBPT
+                ldd #0x1102                     ; read track 17
+                sta DCTRK
+                stb DCOPC
+                ldb #2                          ; read sector 2 (FAT)
+                stb DSEC
+                jsr LD6F2                       ; go read FAT
+                ldb #GRANMX                     ; get total FAT data size
+                jmp LA59A                       ; copy FAT data from sector buffer to FAT image
+; Find free granule; enter with B containing the start location; mark granule with 0xc0 in the
+; FAT to indicate last granule in file. Return granule number in A
+LC7BF           bsr LC755                       ; get pointer to FAT
+                leax FATCON,x                   ; move past controls structure
+                clra                            ; reset granule counter
+                andb #0xfe                      ; start at first granule on track
+                clr ,-s                         ; initialize direction counter to down
+LC7C8           com b,x                         ; is this granule free
+                beq LC7FD                       ; brif so
+                com b,x                         ; restore granule data
+                inca                            ; bump counter
+                cmpa #GRANMX                    ; searched whole FAT?
+                bhs LC7F8                       ; brif so - disk full
+                incb                            ; bump granule counter
+                bitb #1                         ; odd?
+                bne LC7C8                       ; brif so
+                pshs b,a                        ; save granule counter and current granule
+                subb #2                         ; move back one track
+                com 2,s                         ; flip direction
+                bne LC7EC                       ; brif we're switching to "up"
+                subb ,s+                        ; subtract out granule counter (moves other side of start)
+                bpl LC7E8                       ; brif below lower bound
+                ldb ,s                          ; get original granule number
+LC7E6           com 1,s                         ; restore direction flag
+LC7E8           leas 1,s                        ; remove saved granule number
+                bra LC7C8                       ; see if we found a free granule yet
+LC7EC           addb ,s+                        ; move to the top side of starting position
+                cmpb #GRANMX                    ; did we overflow upward?
+                blo LC7E8                       ; brif not
+                ldb ,s                          ; get original granule number
+                subb #4                         ; move an extra track in the other direction if overflowed up
+                bra LC7E6                       ; go see if we found a free one yet
+LC7F8           ldb #2*28                       ; code for disk full
+                jmp LAC46                       ; raise error
+LC7FD           leas 1,s                        ; clean up direction flag
+                tfr b,a                         ; put granule number in A
+                abx                             ; point X to granule data
+                ldb #0xc0                       ; set granule to "used 0, last of file"
+                stb ,x
+LC806           rts
+; Check active files to see if a file is already open; drive number and granule number
+; AO will not be generated if the current status matches *exactly* the requested type in A.
+LC807           pshs a                          ; save desired file type
+                ldb FCBACT                      ; get number of active FCBs
+                incb                            ; include the system FCB in the check
+LC80D           jsr LC749                       ; point to FCB
+                beq LC829                       ; brif not open at all
+                lda DCDRV                       ; get desired drive
+                cmpa FCBDRV,x                   ; match?
+                bne LC829                       ; brif not
+                ldu V974                        ; get directory entry pointer
+                lda DIRGRN,u                    ; get first granule in file
+                cmpa FCBFGR,x                   ; does it match?
+                bne LC829                       ; brif not
+                lda <<FCBTYP,x                  ; get file type
+                cmpa ,s                         ; does it match the type we want?
+                lbne LA61C                      ; brif not - raise AO error
+LC829           decb                            ; checked all FCBs?
+                bne LC80D                       ; brif not
+                puls a,pc                       ; clean stack and return
+; Parse device number and make sure it's open in random mode
+LC82E           jsr LA5A5                       ; evaluate device number
+                clr DEVNUM                      ; reset device number to screen
+                tstb                            ; set flags on device number
+                lble LB44A                      ; brif not a disk file
+                jsr LC749                       ; fetch FCB pointer
+                lda <<FCBTYP,x                  ; is file open?
+                lbeq LA3FB                      ; brif not
+                cmpa #RANFIL                    ; random file?
+                beq LC806                       ; brif so
+LC845           jmp LA616                       ; raise bad file mode
+; Input device number check handler
+DVEC5           lda #INPFIL                     ; set to check for input file
+                skip2
+; Output device number check handler
+DVEC6           lda #OUTFIL                     ; set to check for output file
+                tst DEVNUM                      ; set flags on device number
+                ble LC806                       ; brif not a disk file (return)
+                stx ,s                          ; save X and lose return address
+                jsr LC744                       ; point to FCB
+                ifeq DISKVER
+                pshs a                          ; save file type requested
+                else
+                pshs d                          ; save b and file type requested
+                endc
+                lda <<FCBTYP,x                  ; get file type
+                lbeq LA3FB                      ; brif not open
+                cmpa #RANFIL                    ; random file?
+                ifeq DISKVER
+                beq LC866                       ; brif so - it's good (both input and output)
+                else
+                beq LC868                       ; brif so - it's good (both input and output)
+                endc
+                cmpa ,s                         ; is it the right type?
+                bne LC845                       ; brif not - bad file mode
+                ifeq DISKVER
+LC866           puls a,x,pc                     ; restore registers and return
+                else
+LC866           puls a,b,x,pc                   ; clean up stack, restore registers, and return to caller
+; This code is required to work around the dumbosity in the INPUT command which outputs the
+; prompt string uncondionally so it would cause the prompt string to end up being output to
+; a random file.
+LC868           ldx 4,s                         ; are we coming from INPUT?
+                cmpx #LB00C
+                bne LC866                       ; brif not
+                jsr SYNCOMMA                    ; make sure there's a comma after device
+                cmpa #'"                        ; is there a prompt string?
+                bne LC881                       ; brif not
+                jsr LB244                       ; parse prompt string
+                jsr LB657                       ; fetch string details (and discard them)
+                ldb #';                         ; make sure there's a semicolon after the prompt string
+                jsr LB26F
+LC881           ldx #LB01E                      ; return after the prompt string check
+                stx 4,s
+                puls a,b,x,pc                   ; return to mainline flow
+                endc
+; Device number validity check handler
+                ifeq DISKVER
+DVEC1           ble LC806                       ; brif not a disk file
+                else
+DVEC1           ble LC8AF                       ; brif not a disk file
+                endc
+                cmpb FCBACT                     ; is it in range for open files?
+                lbhi LA61F                      ; brif not - device number error
+                puls x,pc                       ; purge RAM hook call return and return to original caller
+; Set print parameters handler
+DVEC2           tst DEVNUM                      ; is it disk file?
+                ifeq DISKVER
+                ble LC806                       ; brif not
+                else
+                ble LC8AF                       ; brif not
+                endc
+                leas 2,s                        ; don't return to mainline code
+                pshs x,b,a                      ; save registers
+                clr PRTDEV                      ; set print device to "display"
+                jsr LC744                       ; point to correct FCB
+                ldb FCBPOS,x                    ; get print position
+                clra                            ; line width (256)
+                ldx #0x1000                     ; tab width of 16, no last tab position
+                jmp LA37C                       ; go save print parameters
+; LIST break check handler
+DVEC11          tst DEVNUM                      ; is it disk file?
+                ble LC8AF                       ; brif not
+                leas 2,s                        ; purge return - don't do break check if disk file
+LC8AF           rts
+                ifeq DISKVER-1
+; Command interpreation handler
+; This code replaces the main command interpretation loop completely. It includes a check
+; to see if any keys are down before doing a break check. This is unneeded with Color Basic
+; 1.2, but earlier versions of Color Basic benefit from it. This is the only change compared
+; to plain ECB.
+DVEC20          leas 2,s                        ; don't return to mainline code
+LC8B2           andcc #0xaf                     ; enable interrupts
+                clr PIA0+2                      ; strobe all keyboard columns
+                lda PIA0                        ; get row data
+                coma                            ; invert bits so 1 means pressed
+                anda #0x7f                      ; lose the comparator input
+                beq LC8C2                       ; brif no keys down - don't check for BREAK
+                jsr LADEB                       ; do a break check
+LC8C2           ldx CHARAD                      ; get input pointer
+                stx TINPTR                      ; save it so things can find the start of this statement
+                lda ,x+                         ; get current character
+                beq LC8D1                       ; brif end of line
+                cmpa #':                        ; is it end of statement?
+                beq LC8F3                       ; brif so
+                jmp LB277                       ; raise syntax error if not end of statement
+LC8D1           lda ,x++                        ; get MSB of next line address
+                sta ENDFLG                      ; this sets ENDFLG to "END" (unless program code is above 0x7FFF)
+                bne LC8DA                       ; brif not end of program
+                jmp LAE15                       ; go do "END" If we fell off the end of the program
+LC8DA           ldd ,x+                         ; get line number for this line (and leave pointer one before line text)
+                std CURLIN                      ; set current line number
+                stx CHARAD                      ; set input pointer to start of line text
+                lda TRCFLG                      ; are we doing "TRON"?
+                beq LC8F3                       ; brif not
+                lda #'[                         ; show [
+                jsr PUTCHR
+                lda CURLIN                      ; restore MSB of line number
+                jsr LBDCC                       ; show line number
+                lda #']                         ; show ]
+                jsr PUTCHR
+LC8F3           jsr GETNCH                      ; get starting character of next statement
+                tfr cc,b                        ; save flags
+                cmpa #0x98                      ; CSAVE?
+                bne LC8FE                       ; brif not
+                jmp L8316                       ; go handle ECB's CSAVE extensions (CSAVEM)
+LC8FE           cmpa #0x97                      ; CLOAD?
+                bne LC905                       ; brif not
+                jmp L8311                       ; go handle ECB's CLOAD extensions (multi-origin binaries)
+LC905           tfr b,cc                        ; restore flags for input byte
+                jsr LADC6                       ; go interpret command token
+                bra LC8B2                       ; process next statement
+                endc
+; EOF handler
+DVEC14          leas 2,s                        ; dont return to mainline code
+                lda DEVNUM                      ; get device number
+                pshs a                          ; save it
+                jsr LA5AE                       ; evaluate device number
+                jsr LA3ED                       ; make sure it's open for input
+                tst DEVNUM                      ; set flags on device
+                lble LA5DA                      ; brif not disk file - go to mainline code
+                jsr LC744                       ; point to correct FCB
+                ldb <<FCBTYP,x                  ; get file type
+                cmpb #RANFIL                    ; is it random file? (have to check since random is valid for input)
+                ifeq DISKVER
+                beq LC845                       ; bad file mode if so
+                else
+                lbeq LA616                      ; bad file mode if so
+                endc
+                clrb                            ; set flag to not EOF (false)
+                lda FCBCFL,x                    ; is there an "ungot" character?
+                bne LC932                       ; brif so
+                ldb FCBDFL,x                    ; is there anything in the buffer? Will be 0xff if not
+LC932           jmp LA5E4                       ; return status
+; Parse a disk file name. Enter at LC938 with a pointer to the default extension in X.
+; Valid file name patterns are:
+; N:FILENAME[.EXT]
+; N:FILENAME[/EXT]
+; FILENAME[.EXT][:N]
+; FILENAME[/EXT][:N]
+; where N is a drive number.
+LC935           ldx #DEFEXT                     ; point to blank default extension
+LC938           clr ,-s                         ; set a flag for whether drive number was seen
+                lda DEFDRV                      ; set drive number to default (as set by DRIVE)
+                sta DCDRV
+                ldu #DNAMBF                     ; point to file name buffer
+                ldd #0x2008                     ; space character and 8 characters to set
+LC945           sta ,u+                         ; blank a character
+                decb                            ; done all?
+                bne LC945                       ; brif not
+                ldb #3                          ; three characters in extension
+                jsr LA59A                       ; set default extension
+                jsr L8748                       ; evaluate file name string
+                leau ,x                         ; point to start of the string
+                cmpb #2                         ; is string less than 2 characters?
+                blo LC96A                       ; brif so - can't be N:FILENAME.EXT pattern
+                lda 1,u                         ; get second character
+                cmpa #':                        ; is it colon?
+                bne LC96A                       ; brif not - no leading drive number
+                lda ,u                          ; get leading character
+                cmpa #'0                        ; is it below ASCII 0?
+                blo LC96A                       ; brif so - not a drive number
+                cmpa #'3                        ; is it above ASCII 3?
+                bhi LC96A                       ; brif so - not a drive number
+                bsr LC99D                       ; get drive number
+LC96A           ldx #DNAMBF                     ; point to start of file name buffer
+                incb                            ; compensate for DECB below
+LC96E           decb                            ; end of string?
+                bne LC97D                       ; brif so
+                leas 1,s                        ; clean up drive number seen flag
+LC973           cmpx #DNAMBF                    ; was there a file name?
+                bne LC9DF                       ; brif not
+LC978           ldb #2*31                       ; bad file name error code
+                jmp LAC46                       ; raise error
+LC97D           lda ,u+                         ; get character from string
+                cmpa #'.                        ; is it extension?
+                beq LC9B0                       ; brif so
+                cmpa #'/                        ; is it other extension introducer?
+                beq LC9B0                       ; brif so
+                cmpa #':                        ; drive number introducer?
+                beq LC994                       ; brif so
+                cmpx #DEXTBF                    ; are we at the end of the file name buffer?
+                beq LC978                       ; brif so - name too long
+                bsr LC9D0                       ; put character in file name
+                bra LC96E                       ; process another
+LC994           bsr LC973                       ; bad file name if no name yet
+                bsr LC99D                       ; parse drive number
+                tstb                            ; is there anything left?
+                bne LC978                       ; brif so
+LC99B           puls a,pc                       ; clean up strack and return
+LC99D           com 2,s                         ; toggle drive number seen flag
+                beq LC978                       ; brif we've seen drive number already
+                lda ,u++                        ; get drive number and skip trailing : if leading
+                subb #2                         ; take two characters from string
+                suba #'0                        ; remove ASCII bias
+                blo LC978                       ; brif not a digit
+                cmpa #3                         ; is it in range?
+                bhi LC978                       ; brif not
+                sta DCDRV                       ; save drive number
+                rts
+LC9B0           bsr LC973                       ; error if no file name yet
+                ldx #DFLTYP                     ; point to end of extension buffer
+                lda #0x20                       ; space (for padding extension)
+LC9B7           sta ,-x                         ; insert padding character
+                cmpx #DEXTBF                    ; done yet?
+                bne LC9B7                       ; brif not
+LC9BE           decb                            ; are we at the end of the string?
+                beq LC99B                       ; brif so
+                lda ,u+                         ; get character
+                cmpa #':                        ; drive number?
+                beq LC994                       ; brif so
+                cmpx #DFLTYP                    ; is extension full?
+                beq LC978                       ; brif so - bad fil ename
+                bsr LC9D0                       ; put character in buffer
+                bra LC9BE                       ; process another character
+LC9D0           sta ,x+                         ; put character in buffer
+                beq LC978                       ; brif NUL - don't allow it (first character NUL is deleted file)
+                cmpa #'.                        ; dot?
+                beq LC978                       ; brif not - don't allow extension separator
+                cmpa #'/                        ; ditto for slash
+                beq LC978
+                inca                            ; is if 0xff?
+                beq LC978                       ; brif so - first character 0xff means never used entry
+LC9DF           rts
+; SAVE command
+SAVE            cmpa #'M                        ; is it SAVEM?
+                lbeq LCF68                      ; brif so
+                bsr LCA33                       ; parse file name
+                ldx ZERO                        ; set to BASIC program and binary
+                stx DFLTYP
+                jsr GETCCH                      ; is there something after the file name?
+                beq LCA12                       ; brif not
+                jsr SYNCOMMA                    ; make sure we have a comma
+                ldb #'A                         ; only valid flag is "A" for ASCII
+                jsr LB26F
+                bne LC9DF                       ; brif more stuff follows - error
+                com DASCFL                      ; set to ASCII type
+                bsr LCA04                       ; open sequential file for output
+                clra                            ; set Z to cause whole program to be listed
+                jmp LIST                        ; let LIST do the heavy lifting
+LCA04           lda #'O                         ; output file type
+                skip2
+LCA07           lda #'I                         ; iput file type
+                ldb FCBACT                      ; get number of active FCBs
+                incb                            ; bump to system FCB
+                stb DEVNUM                      ; use the system FCB
+                jmp LC48D                       ; open file and initialize FCB
+LCA12           bsr LCA04                       ; open file for output
+                lda #0xff                       ; send basic file flag
+                jsr LCC24
+                ldd VARTAB                      ; get end of program address
+                subd TXTTAB                     ; now we have length of program
+                jsr LCC24                       ; output length MS byte
+                tfr b,a                         ; output length LS byte
+                jsr LCC24
+                ldx TXTTAB                      ; point to start of program text
+LCA27           lda ,x+                         ; output byte from program
+                jsr LCC24
+                cmpx VARTAB                     ; end of program?
+                bne LCA27                       ; brif not
+                jmp LA42D                       ; close the file
+LCA33           ldx #BASEXT                     ; point to BAS extension (for basic programs)
+                jmp LC938                       ; parse file name
+; MERGE command
+MERGE           clra                            ; run flag: 0 = don't run
+                ldb #0xff                       ; merge flag: 0xff = merge
+                bra LCA50
+; RUN handler
+DVEC18          cmpa #'"                        ; do we have a file name?
+                lbne XVEC18                     ; brif not
+                lda #2                          ; RUN flag - run after loading
+                bra LCA4F                       ; load file
+; LOAD command
+LOAD            cmpa #'M                        ; is it LOADM?
+                lbeq LCFC1                      ; brif so
+                clra                            ; set not to RUN
+LCA4F           clrb                            ; set not to MERGE
+LCA50           sta DRUNFL                      ; save RUN flag
+                stb DMRGFL                      ; save MERGE flag
+                bsr LCA33                       ; parse file name
+                jsr GETCCH                      ; is there anything after the file name?
+                beq LCA6C                       ; brif not
+                jsr SYNCOMMA                    ; make sure comma
+                ldb #'R                         ; make sure the flag is "R"
+                jsr LB26F
+                jsr LA5C7                       ; error if anything else
+                lda #3                          ; set flags to RUN and not close files
+                sta DRUNFL
+LCA6C           bsr LCA07                       ; open file for input
+                lda DASCFL                      ; is it ASCII?
+                beq LCA7E                       ; brif not
+                tst DMRGFL                      ; is it merge?
+                bne LCA7B                       ; brif so
+                jsr LAD19                       ; do a "NEW" - erase existing program
+LCA7B           jmp LAC7C                       ; let immediate mode do the heavy lifting now
+LCA7E           lda DFLTYP                      ; get type
+                ora DMRGFL                      ; mix with merge flag
+                lbne LA616                      ; if either of the above was nonzero, raise bad file mode
+                jsr LAD19                       ; erase existing program
+                com DLODFL                      ; flag that we're loading a program
+                jsr LCDBC                       ; get initial character (discard it, should be 0xff)
+                jsr LCDBC                       ; get MSB of length
+                pshs a                          ; save it
+                jsr LCDBC                       ; get LSB of length
+                tfr a,b                         ; save length in D
+                puls a
+                addd TXTTAB                     ; add to start of program text
+                jsr LAC37                       ; make sure it fits
+                ldx TXTTAB                      ; point to start of program
+LCAA4           jsr LC5C4                       ; get a character
+                ldb CINBFL                      ; EOF?
+                bne LCAAF                       ; brif so
+                sta ,x+                         ; save character
+                bra LCAA4                       ; process more
+LCAAF           clr DLODFL                      ; clear load flag - no errors
+                stx VARTAB                      ; set new end of program
+                ldb #3                          ; make sure the last three bytes were 0
+LCAB6           lda ,-x                         ; do we have a 0?
+                bne LCABD                       ; brif not
+                decb                            ; done all three?
+                bne LCAB6                       ; brif not
+LCABD           ldx VARTAB                      ; get end of program
+LCABF           stx VARTAB                      ; save new end of program
+                clr ,x+                         ; blank a byte
+                decb                            ; done enough?
+                bpl LCABF                       ; brif not
+LCAC6           jsr LA42D                       ; close the file
+                jsr LAD21                       ; clear variables, reset stack, etc.
+                jsr XVEC18                      ; initalize graphics stuff
+                jsr LACEF                       ; recalculate line pointers
+                asr DRUNFL                      ; are we supposed to close all files?
+                bcs LCADA                       ; brif not
+                jsr LA426                       ; close all open files
+LCADA           asr DRUNFL                      ; are we supposed to run the program/
+                lbcs LAD9E                      ; brif so - launch program
+                jmp LAC73                       ; return to immediate mode
+; EOF handler for main loop
+DVEC13          tst DEVNUM                      ; is it disk file?
+                bgt LCAC6                       ; brif so - run it if required
+                rts                             ; return to mainline otherwise
+; Close all files handler
+DVEC7           ldb FCBACT                      ; get number of reserved FCBs
+                incb                            ; include system FCB
+LCAED           pshs b                          ; save file count
+                stb DEVNUM                      ; set device to close
+                bsr LCB01                       ; close it
+                puls b                          ; get back file count
+                decb                            ; move to next one
+                bne LCAED                       ; brif not done all disk files
+LCAF8           rts
+; Close one file handler
+DVEC8           tst DEVNUM                      ; is it a disk file?
+                lble XVEC8                      ; brif not
+                leas 2,s                        ; don't return to mainline
+LCB01           jsr LC744                       ; get FCB pointer
+                clr DEVNUM                      ; reset device number
+LCB06           stx FCBTMP                      ; save FCB pointer
+                lda <<FCBTYP,x                  ; get file type
+                beq LCAF8                       ; brif file isn't open - we don't have to do anything
+                pshs a                          ; save file type
+                clr <<FCBTYP,x                  ; mark file closed
+                ldb FCBDRV,x                    ; tell DSKCON which drive the file is on
+                stb DCDRV
+                cmpa #OUTFIL                    ; output file?
+                bne LCB31                       ; brif not
+                ldb FCBLFT,x                    ; get number of characters in output buffer
+                lda #0x80                       ; set pre-saved bit to indicate data already saved
+                ifeq DISKVER-1
+                ora FCBCPT,x                    ; merge with full sector flag
+                endc
+                std FCBLST,x                    ; save number of bytes used in last sector
+                inc FCBSEC,x                    ; bump sector counter
+                ldb FCBCGR,x                    ; get current granule
+                jsr LC755                       ; point to FAT
+                sta FAT1,x                      ; mark FAT data invalid
+                abx                             ; add granule offset to pointer
+                inc FATCON,x                    ; add one to sector count for last granule (skip control bytes)
+                ifeq DISKVER
+LCB2E           bra LCBC3                       ; update FAT and directory, write out any final data
+                else
+LCB2E           jmp LCBC3                       ; update FAT and directory, write out any final data
+                endc
+LCB31           cmpa #RANFIL                    ; random file?
+                ifeq DISKVER
+                bne LCBC3                       ; brif not
+                else
+                bne LCB2E                       ; brif not - update FAT and directory for input file
+                endc
+                ldd FCBRLN,x                    ; get record length
+                ldx FCBBUF,x                    ; get buffer pointer
+                leay d,x                        ; point to end of random file buffer
+                pshs y,x,b,a                    ; save pointers and length
+                ifeq DISKVER-1
+                leay ,s                         ; save stack pointer
+                endc
+                ldu VARTAB                      ; get start of variables
+LCB41           cmpu ARYTAB                     ; end of scalars?
+                beq LCB54                       ; brif so
+                lda 1,u                         ; get second byte of variable name
+                leau 2,u                        ; move past variable name
+                bpl LCB4E                       ; brif numeric
+                bsr LCB76                       ; adjust string variable if in random file buffer
+LCB4E           leau 5,u                        ; move to next variable entry
+                bra LCB41                       ; process next variable entry
+LCB52           puls u                          ; get address of next array
+LCB54           cmpu ARYEND                     ; end of arrays?
+                ifeq DISKVER
+                beq LCB91                       ; brif so
+                else
+                beq LCB93                       ; brif so
+                endc
+                tfr u,d                         ; save array start
+                addd 2,u                        ; add length of array
+                pshs d                          ; save address of next array
+                lda 1,u                         ; is it string?
+                bpl LCB52                       ; brif not - do next array
+                ldb 4,u                         ; get number of dimensions
+                aslb                            ; two bytes per dimension size
+                addb #5                         ; 5 bytes constant per array header
+                clra                            ; zero extend
+                leau d,u                        ; point to start of array data
+LCB6B           cmpu ,s                         ; end of this array?
+                beq LCB52                       ; brif so
+                bsr LCB76                       ; adjust string variable if in random file buffer
+                leau 5,u                        ; move to next entry
+                bra LCB6B                       ; process next entry
+LCB76           ldx 2,u                         ; get pointer to start of string
+                cmpx RNBFAD                     ; is it above top of random buffer area?
+                bhs LCB8B                       ; brif so
+                ifeq DISKVER
+                cmpx 4,s                        ; is it below this file's buffer area?
+                blo LCB8C                       ; brif so
+                cmpx 6,s                        ; is it above this file's buffer?
+                else
+                cmpx 2,y                        ; is it above start of this file's buffer area?
+                blo LCB8B                       ; brif not
+                cmpx 4,y                        ; is it below end of this file's buffer area?
+                endc
+                blo LCB8C                       ; brif so - we have to adjust it
+                tfr x,d                         ; save pointer in D
+                ifeq DISKVER
+                subd 2,s                        ; adjust pointer down by length of buffer area for this file
+                else
+                subd ,y                         ; adjust pointer down by length of buffer area for this file
+                endc
+                std 2,u                         ; save new start of string
+LCB8B           rts
+LCB8C           clr ,u                          ; mark string empty
+                clr 2,u                         ; NULL out string address
+                clr 3,u
+                rts
+                ifeq DISKVER
+LCB91           puls a,b,x,u                    ; clean up stack
+                else
+LCB93           ldb FCBACT                      ; get number of active files
+                incb                            ; include system FCB
+LCB97           pshs b                          ; save files count
+                jsr LC749                       ; point to FCB number in B
+                lda <<FCBTYP,x                  ; open as random file?
+                cmpa #RANFIL
+                bne LCBAD                       ; brif not
+                ldd FCBBUF,x                    ; get buffer pointer
+                cmpd 4,y                        ; is it above this file's buffer?
+                blo LCBAD                       ; brif not
+                subd ,y                         ; subtract out length for this file's buffer
+                std FCBBUF,x                    ; save new buffer area pointer
+LCBAD           puls b                          ; get files counter back
+                decb                            ; done all?
+                bne LCB97                       ; brif not
+                puls a,b,x,u                    ; get back pointers and buffer length
+                endc
+LCBB4           cmpu RNBFAD                     ; at top of buffers?
+                beq LCBC0                       ; brif so
+                lda ,u+                         ; copy a byte down
+                sta ,x+
+                bra LCBB4                       ; see if we're done yet
+LCBC0           stx RNBFAD                      ; save new start of free buffer area
+LCBC3           jsr LC755                       ; point to proper FAT
+                dec <<FAT0,x                    ; remove one active file
+                tst FAT1,x                      ; new data in FAT image?
+                beq LCBCF                       ; brif not
+                jsr LC71E                       ; save modified FAT
+LCBCF           ldx FCBTMP                      ; get FCB pointer back
+                puls a                          ; get file type
+                cmpa #OUTFIL                    ; output?
+                beq LCBDF                       ; brif so
+                cmpa #RANFIL                    ; random?
+                bne LCB8B                       ; brif not
+                lda FCBFLG,x                    ; doing GET?
+                beq LCBE9                       ; brif so
+LCBDF           jsr LC763                       ; set up track and sector parameters
+                leau FCBCON,x                   ; point to data buffer
+                stu DCBPT
+                bsr LCC15                       ; write out the sector data
+LCBE9           lda FCBLST,x                    ; data pre-saved?
+                bpl LCB8B                       ; brif it has already been saved
+                ldb FCBDIR,x                    ; get directory number for this file
+                andb #7                         ; 8 entries per sector
+                lda #DIRLEN                     ; calculate offset into directory sector
+                mul
+                ldu #DBUF0                      ; point to global buffer
+                stu DCBPT                       ; set DSKCON buffer address
+                leay d,u                        ; Y points to directory entry now
+                ldb FCBDIR,x                    ; get directory entry number
+                lsrb                            ; divide by 8 (gives sector number)
+                lsrb
+                lsrb
+                addb #3                         ; first directory sector is 3
+                stb DSEC                        ; tell DSKCON
+                ldd #0x1102                     ; set up to read track 17
+                sta DCTRK
+                bsr LCC17                       ; read directory sector
+                ldd FCBLST,x                    ; get number of bytes in last sector
+                anda #0x7f                      ; remove pre-saved flag
+                std DIRLST,y                    ; update directory entry
+LCC15           ldb #3                          ; write operation
+LCC17           stb DCOPC                       ; tell DSKCON what to do
+                jmp LD6F2                       ; go read or write sector
+; Generic output handler
+DVEC3           tst DEVNUM                      ; disk file?
+                lble XVEC3                      ; brif not
+                leas 2,s                        ; don't return to mainline
+LCC24           pshs x,b,a                      ; save registers
+                ldx #FCBV1-2                    ; point to FCB list (-2 for 1-based file numbers)
+                ldb DEVNUM                      ; get device number
+                aslb                            ; two bytes per pointer
+                ldx b,x                         ; get FCB pointer
+                ldb ,x                          ; get file type
+                cmpb #INPFIL                    ; input?
+                beq LCC6A                       ; brif so - bail
+                cmpa #0x0d                      ; carriage return?
+                bne LCC3A                       ; brif so
+                clr FCBPOS,x                    ; reset print position if CR
+LCC3A           cmpa #0x20                      ; control code?
+                blo LCC40                       ; brif so
+                inc FCBPOS,x                    ; bump print position if printing character
+LCC40           cmpb #RANFIL                    ; random file?
+                bne LCC5E                       ; brif not
+                ldd FCBPUT,x                    ; get put pointer
+                addd #1                         ; bump it
+                cmpd FCBRLN,x                   ; did we overflow the record?
+                lbhi LCDCB                      ; brif so - raise error
+                std FCBPUT,x                    ; save updated pointer
+                ldx FCBBUF,x                    ; get buffer pointer
+                leax d,x                        ; add in offset
+                puls a                          ; get back output character
+                sta -1,x                        ; save in buffer (-1 because we already bumped pointer)
+                puls b,x,pc                     ; restore registers and return
+LCC5E           inc FCBLFT,x                    ; bump character count
+                ldb FCBLFT,x                    ; did we max out a sector?
+                beq LCC6C                       ; brif so
+                abx                             ; add offset into sector
+                sta FCBCON-1,x                  ; save output character in buffer, offset past control structure
+LCC6A           puls a,b,x,pc                   ; restore registers and return
+LCC6C           pshs u,y                        ; save registers
+                sta SECLEN+FCBCON-1,x           ; save last character in buffer
+                ifeq DISKVER
+                jsr LC685
+                endc
+                ldb FCBDRV,x                    ; tell DSKCON which drive
+                stb DCDRV
+                inc FCBSEC,x                    ; bump sector counter (in granule)
+                jsr LCBDF                       ; write file buffer to disk
+                leay ,x                         ; save FCB pointer
+                ldb FCBCGR,x                    ; get granule number
+                jsr LC755                       ; get pointer to FAT
+                abx                             ; offset into granule data
+                leau FATCON,x                   ; now U points to granule data (offset past control structure)
+                lda FCBSEC,y                    ; get current sector offset
+                cmpa #9                         ; end of granule?
+                blo LCC99                       ; brif not
+                ifeq DISKVER-1
+                dec FCBSEC,y                    ; decrement sector number and bump error flag in case error occurs
+                inc FCBCPT,y
+                else
+                clr FCBSEC,y
+                endc
+                jsr LC7BF                       ; allocate granule
+                ifeq DISKVER-1
+                clr FCBSEC,y                    ; clear sector number
+                clr FCBCPT,y                    ; clear error flag - disk not full
+                endc
+                sta FCBCGR,y                    ; save new granule in FCB
+                skip2
+LCC99           ora #0xc0                       ; mark granule as end of file
+                sta ,u                          ; save in granule map
+                ifeq DISKVER-1
+                leax ,y                         ; get back FCB pointer
+                jsr LC685                       ; bump record number
+                endc
+                jsr LC5A9                       ; update FAT
+                puls y,u                        ; restore registers
+                puls a,b,x,pc                   ; restore registers and return
+; DIR command
+DIR             jsr LD24F                       ; parse drive number
+                jsr LC79D                       ; fetch FAT for drive
+                jsr LB958                       ; do a linefeed
+                ldd #0x1102                     ; set up to read track 17
+                sta DCTRK
+                stb DCOPC
+                ldb #3                          ; start at sector 3 for the directory
+LCCBB           stb DSEC                        ; set sector to read
+                ldx #DBUF0                      ; use the global sector buffer
+                stx DCBPT
+                jsr LD6F2                       ; read directory sector
+LCCC5           puls u                          ; do some stack games due to break check requirements
+                jsr LA549
+                pshs u
+                lda ,x                          ; is this entry used?
+                beq LCD08                       ; brif not
+                coma                            ; is it the start of never entries?
+                beq LCD17                       ; brif so - we're done
+                pshs x                          ; save directory data pointer
+                ldb #8                          ; print out 8 characters for the filename
+                jsr LB9A2                       ; display file name
+                bsr LCD1B                       ; put a blank
+                ldb #3                          ; show 3 characters in extension
+                jsr LB9A2                       ; display extension
+                bsr LCD1B                       ; put a blank
+                ldb <<0,x                       ; get file type
+                cmpb #10                        ; is it one digit?
+                bhs LCCEB                       ; brif so
+                bsr LCD1B                       ; put another blank
+LCCEB           clra                            ; zero extend type
+                jsr LBDCC                       ; show file type
+                bsr LCD1B                       ; another blank
+                ldx ,s                          ; get directory entry back
+                lda #'B                         ; set to binary
+                adda DIRASC,x                   ; add ASCII flag - will subtract 1 (to A) if ASCII
+                bsr LCD18                       ; show character and a blank
+                ldb DIRGRN,x                    ; point to first granule in file
+                bsr LCD1E                       ; count granules
+                tfr a,b                         ; zero extend into D
+                clra
+                jsr LBDCC                       ; show granule count
+                jsr LB958                       ; do a newline
+                puls x                          ; get back directory pointer
+LCD08           leax DIRLEN,x                   ; move to next entry
+                cmpx #DBUF0+SECLEN              ; end of sector?
+                blo LCCC5                       ; brif not
+                ldb DSEC                        ; get sector number
+                incb                            ; move to next one
+                cmpb #SECMAX                    ; end of track?
+                bls LCCBB                       ; brif not
+LCD17           rts
+LCD18           jsr PUTCHR                      ; display character
+LCD1B           jmp LB9AC                       ; display a space
+; Count granule chain starting at granule number in B
+LCD1E           jsr LC755                       ; get FAT pointer
+                leau FATCON,x                   ; point past control structure
+                clra                            ; reset count to 0
+LCD24           inca                            ; bump granule count
+                cmpa #GRANMX                    ; at maximum size of disk?
+                lbhi LC653                      ; do FS error if so
+                leax ,u                         ; point to base FAT data
+                abx                             ; offset to granule number
+                ldb ,x                          ; get next granule pointer
+                cmpb #0xc0                      ; end of file marker?
+                blo LCD24                       ; brif not
+                rts
+; INPUT handler; this whole mess is requried because the disk data format varies from that used
+; by tape files.
+DVEC10          tst DEVNUM                      ; are we reading from a disk file?
+                ble LCD97                       ; brif not
+                ldx #LB069                      ; change return address to skip ? prompt
+                stx ,s
+                ldx #LINBUF+1                   ; point to input buffer
+                ldb #',                         ; set item separator to ,
+                stb CHARAC
+                lda VALTYP                      ; get type wanted
+                bne LCD4B                       ; brif string
+                ldb #0x20                       ; space is the numeric delimiter
+LCD4B           bsr LCDBC                       ; fetch input character
+                cmpa #0x20                      ; space?
+                beq LCD4B                       ; brif so
+                cmpa #'"                        ; quote?
+                bne LCD5F                       ; brif not
+                cmpb #',                        ; delim is ,?
+                bne LCD5F                       ; brif not - numeric
+                tfr a,b                         ; save quote as search character
+                stb CHARAC
+                bra LCD81                       ; save quote as first item in buffer
+LCD5F           cmpb #'"                        ; string value?
+                beq LCD74                       ; brif so
+                cmpa #0x0d                      ; end of line?
+                bne LCD74                       ; brif not
+                cmpx #LINBUF+1                  ; at start of buffer?
+                beq LCDB0                       ; brif so - check for LF
+                lda -1,x                        ; get back input character
+                cmpa #0x0a                      ; was it LF?
+                bne LCDB0                       ; brif not
+                lda #0x0d                       ; restore CR as input character
+LCD74           tsta                            ; NUL?
+                beq LCD8E                       ; brif so - ignore it
+                cmpa CHARAC                     ; hit a delimiter?
+                beq LCD98                       ; brif so
+                pshs b                          ; does it match the other delimiter?
+                cmpa ,s+
+                beq LCD98                       ; brif so
+LCD81           sta ,x+                         ; save character in buffer
+                cmpx #LINBUF+LBUFMX             ; end of buffer?
+                bne LCD8E                       ; brif not
+                bsr LCDD0                       ; fetch character
+                bne LCD92                       ; brif buffer empty
+                bra LCDAC                       ; check for CR/CRLF
+LCD8E           bsr LCDD0                       ; get input character
+                beq LCD5F                       ; brif we have something
+LCD92           clr ,x                          ; put NUL at end of buffer
+                ldx #LINBUF                     ; point to input buffer
+LCD97           rts
+LCD98           cmpa #'"                        ; quote?
+                beq LCDA0                       ; brif so
+                cmpa #0x20                      ; space?
+                bne LCD92                       ; brif not
+LCDA0           bsr LCDD0                       ; get character
+                bne LCD92                       ; brif end
+                cmpa #0x20                      ; space?
+                beq LCDA0                       ; brif so - skip it
+                cmpa #',                        ; item separator?
+                beq LCD92                       ; brif so - done
+LCDAC           cmpa #0x0d                      ; carriage return?
+                bne LCDB8                       ; brif not
+LCDB0           bsr LCDD0                       ; fetch character
+                bne LCD92                       ; brif end
+                cmpa #0x0a                      ; line feed?
+                beq LCD92                       ; brif so - skip it
+LCDB8           bsr LCDD6                       ; unget character
+                bra LCD92                       ; handle exit
+LCDBC           bsr LCDD0                       ; fetch character
+                beq LCDD5                       ; brif not end of file
+                jsr LC744                       ; point to FCB
+                ldb <<FCBTYP,x                  ; get file type
+                cmpb #RANFIL                    ; random file?
+                lbne LC352                      ; brif not - do input past end of file
+LCDCB           ldb #2*37                       ; code for input past end of record
+                jmp LAC46                       ; raise error
+LCDD0           jsr LA176                       ; read character
+                tst CINBFL                      ; set Z if not EOF
+LCDD5           rts
+LCDD6           pshs x,b                        ; save registers
+                jsr LC744                       ; point to FCB
+                ldb <<FCBTYP,x                  ; random file?
+                cmpb #RANFIL
+                bne LCDEC                       ; brif not
+                ldd FCBGET,x                    ; get input pointer
+                subd #1                         ; move it back (no error check!)
+                std FCBGET,x                    ; save new pointer
+                puls b,x,pc                     ; restore registers and return
+LCDEC           sta FCBCDT,x                    ; save unget character
+                com FCBCFL,x                    ; flag that we have an ungot character
+                puls b,x,pc                     ; restore registers and return
+; CVN function
+CVN             jsr LB654                       ; evaluate argument string
+                cmpb #5                         ; is it at least 5 bytes (packed FP number)?
+                lblo LB44A                      ; brif not - raise error
+                clr VALTYP                      ; result is numeric
+                jmp LBC14                       ; unpack string into return value
+; MKN$ function
+MKN             jsr LB143                       ; make sure we have a number
+                ldb #5                          ; string will be 5 bytes long
+                jsr LB50F                       ; reserve space for it
+                jsr LBC35                       ; pack argument into the string
+                jmp LB69B                       ; return the newly created string
+; LOC function
+LOC             bsr LCE19                       ; get pointer to correct FCB
+                ldd FCBREC,x                    ; get record number (random file) or sector counter
+                ifeq DISKVER
+LCE14           jmp GIVABF                      ; return result as integer
+                else
+LCE14           std FPA0+2                      ; return result as an unsigned integer
+                jmp L880E
+                endc
+; Evaluate device number, set print parameters, and point to FCB
+LCE19           lda DEVNUM                      ; save current device number
+                pshs a
+                jsr LB143                       ; make sure we have a number
+                jsr LA5AE                       ; check device and set print params
+                tst DEVNUM                      ; is it a disk file?
+                lble LB44A                      ; brif not
+                jsr LC744                       ; point to FCB
+                puls a                          ; restore original device number
+                sta DEVNUM
+                tst <<FCBTYP,x                  ; is file open?
+                lbeq LA3FB                      ; brif not, do NO error
+                rts
+; LOF function
+LOF             bsr LCE19                       ; point to FCB
+                lda FCBDRV,x                    ; tell DSKCON the drive number
+                sta DCDRV
+                ldb FCBFGR,x                    ; get first granule of file
+                pshs x                          ; save FCB pointer
+                jsr LCD1E                       ; count granules in file
+                deca                            ; subtract out last granule
+                andb #0x3f                      ; get number of sectors in last granule
+                pshs b                          ; save it
+                tfr a,b                         ; zero extend granule number to D
+                clra
+                jsr LC779                       ; multiply by 9 for total sector count
+                addb ,s+                        ; add in sectors in last granule
+                adca #0
+                puls x                          ; get back FCB pointer
+                pshs a                          ; temp save
+                lda <<FCBTYP,x                  ; is it random file?
+                cmpa #RANFIL
+                puls a                          ; restore register
+                bne LCE14                       ; brif not random file - return number of sectors
+                pshs x                          ; save FCB pointer
+                subd ZERO                       ; "tstd"
+                beq LCE68                       ; brif file is empty
+                subd #1                         ; don't count last sector as fully used
+LCE68           bsr LCE14                       ; put D into FPA0
+                ldb FP0EXP                      ; is it 0?
+                beq LCE72                       ; brif so
+                addb #8                         ; multiply by 256
+                stb FP0EXP
+LCE72           jsr LBC5F                       ; save result in FPA1
+                ldx ,s                          ; get back FCB pointer
+                ldd FCBLST,x                    ; get number of bytes in last sector
+                anda #0x7f                      ; clear out pre-save flag
+                bsr LCE14                       ; stuff that number in FPA0
+                clr RESSGN                      ; result will be positive
+                lda FP1EXP                      ; get exponents
+                ldb FP0EXP
+                jsr LB9C5                       ; add number of bytes in last sector
+                jsr LBC5F                       ; save total in FPA1
+                puls x                          ; get FCB
+                ldd FCBRLN,x                    ; get record length
+                bsr LCE14                       ; turn it into a FP number
+                clr RESSGN                      ; make result positive
+                lda FP1EXP                      ; get exponents
+                ldb FP0EXP
+                jsr LBB91                       ; divide total by record size
+                jmp INT                         ; return the result as an integer
+; FREE function
+FREE            jsr LB143                       ; make sure we have a number
+                jsr LB70E                       ; get value in B
+                cmpb #3                         ; valid drive?
+                lbhi LA61F                      ; brif not
+                stb DCDRV                       ; set drive
+                jsr LC79D                       ; read FAT
+                jsr LC755                       ; point to FAT
+                leax FATCON,x                   ; point to actual granule data
+                clr ,-s                         ; initialize free count
+                ldb #GRANMX                     ; total granules to check
+LCEB6           lda ,x+                         ; get granule data
+                coma                            ; is it free?
+                bne LCEBD                       ; brif not
+                inc ,s                          ; bump free count
+LCEBD           decb                            ; checked them all?
+                bne LCEB6                       ; brif not
+                puls b                          ; get free count
+                jmp LB4F3                       ; return free count
+; DRIVE command
+DRIVE           jsr EVALEXPB                    ; evaluate drive number to B
+                cmpb #3                         ; valid?
+                lbhi LA61F                      ; brif not
+                stb DEFDRV                      ; set default drive
+                rts
+; Expression evaluation handler; this is needed so we can move strings into string space
+; if regular assignment to a FIELDed string is done. There really isn't a better place to
+; intercept this, unfortunately.
+DVEC15          lda 4,s                         ; is it end of operation?
+                bne LCEE9                       ; brif not
+                ldx 5,s                         ; are we comming from LET?
+                cmpx #LAF9A
+                bne LCEE9                       ; brif not
+                ldx 2,s
+                cmpx #LB166
+                bne LCEE9                       ; and brif not again
+                ldx #LCEEC                      ; install intercept for LET
+                stx 5,s
+LCEE9           jmp XVEC15                      ; let ECB do its thing
+; LET modifier
+LCEEC           puls a                          ; get variable type
+                rora                            ; set C if string
+                jsr LB148                       ; make sure things match
+                lbeq LBC33                      ; brif numeric - we can go back to mainline
+                ldx FPA0+2                      ; get string descriptor
+                ldd 2,x                         ; get data pointer
+                cmpd #DFLBUF                    ; is it below random buffers?
+                blo LCF07                       ; brif so
+                subd FCBADR                     ; is it within the random buffers?
+                lblo LAFB1                      ; brif so - move string to string space
+LCF07           jmp LAFA4                       ; return to mainline code
+; ECB interpretation handler intercept; the PMODE intercept fixes a stupid usage of a constant 6 for the
+; start of graphics memory in PMODE.  The DLOAD intercept fixes the problem where DLOADM couldn't be
+; detected due to A being clobbered before it was checked. Both of those bugs were fixed in ECB 1.1.
+DXCVEC          cmpa #0xca                      ; DLOAD?
+                beq LCF2A                       ; brif so
+                cmpa #0xc8                      ; PMODE?
+                lbne L813C                      ; brif not - return to ECB's handler
+                jsr GETNCH                      ; get input character
+                cmpa #',                        ; no PMODE argument?
+                lbeq L9650                      ; brif not - return to mainline
+                jsr EVALEXPB                    ; evaluate PMODE number
+                cmpb #4                         ; valid?
+                lbhi LB44A                      ; brif not
+                lda GRPRAM                      ; fetch start of grahpics memory (work around usage of constant 6 in ECB 1.0)
+                jmp L962E                       ; return to mainline PMODE
+LCF2A           jsr LA429                       ; close files 
+                jsr GETNCH                      ; fetch input character
+                jmp L8C1B                       ; return to mainlnie
+; ECB function interpetation handler intercept; this is needed to patch into the POS() function.
+DXIVEC          cmpb #(0x9a-0x80)*2             ; is it POS?
+                lbne L8168                      ; brif not - return to ECB mainline
+                jsr LB262                       ; evaluate argument
+                lda DEVNUM                      ; get device number
+                pshs a                          ; save it
+                jsr LA5AE                       ; evaluate device number
+                jsr LA406                       ; make sure it's open
+                tst DEVNUM                      ; disk file?
+                ble LCF5C                       ; brif not
+                jsr LC744                       ; point to FCB
+                ldb <<FCBTYP,x                  ; get file type
+                cmpb #RANFIL                    ; random file?
+                bne LCF5C                       ; brif not
+                puls a                          ; get back saved device number
+                sta DEVNUM
+                ldd FCBPUT,x                    ; get "put" position
+                jmp GIVABF                      ; return that as the position
+LCF5C           jsr LA35F                       ; set print parameters
+                puls a                          ; restore device number
+                sta DEVNUM
+                ldb DEVPOS                      ; get print position
+                jmp LB4F3                       ; return B as unsigned
+; SAVEM command (comes from SAVE command)
+LCF68           jsr GETNCH                      ; eat the "M"
+                bsr LCFBB                       ; parse filename
+                jsr L836C                       ; evaluate start address
+                jsr L836C                       ; evaluate end address
+                cmpx 2,s                        ; is start > end?
+                lblo LB44A                      ; brif so - throw an error
+                jsr L836C                       ; evaluate execution address
+                jsr LA5C7                       ; make sure there's nothing more
+                ldd #0x200                      ; file type 2 (M/L) and binary
+                std DFLTYP
+                jsr LCA04                       ; open file for output
+                clra                            ; write preamble header
+                bsr LCFB5
+                ldd 2,s                         ; get end address
+                subd 4,s                        ; subtract start - gets length
+                addd #1                         ; length is inclusive
+                tfr d,y                         ; set data counter
+                bsr LCFB3                       ; output the length of the block
+                ldd 4,s                         ; output the load address
+                bsr LCFB3
+                ldx 4,s                         ; point to start of block
+LCF9B           lda ,x+                         ; grab output byte
+                jsr LCC24                       ; write it
+                leay -1,y                       ; done yet?
+                bne LCF9B                       ; brif not
+                lda #0xff                       ; write header for postamble
+                bsr LCFB5
+                clra                            ; write dummy 16 bits (would be block length)
+                clrb
+                bsr LCFB3
+                puls d,x,y                      ; get back execution address and clean stack
+                bsr LCFB3                       ; write out execution address
+                jmp LA42D                       ; close file
+LCFB3           bsr LCFB5                       ; write MSB of word; fall through for LSB
+LCFB5           jsr LCC24                       ; write byte out
+                exg a,b                         ; swap bytes in word
+                rts
+LCFBB           ldx #BINEXT                     ; set default extension to "BIN"
+                jmp LC938                       ; parse filename
+; LOADM command (comes from LOAD command)
+LCFC1           jsr GETNCH                      ; eat the "M"
+                bsr LCFBB                       ; parse filename
+                jsr LCA07                       ; open file for input
+                ldd DFLTYP                      ; get type of file
+                subd #0x200                     ; is it M/L and binary?
+                lbne LA616                      ; bad file mode if not
+                ldx ZERO                        ; set default offset value
+                jsr GETCCH                      ; is there a load offset?
+                beq LCFDE                       ; brif not
+                jsr SYNCOMMA                    ; insist on a comma
+                jsr LB73D                       ; evaluate offset to X
+LCFDE           stx VD3                         ; save offset
+                jsr LA5C7                       ; insist on end of statement
+LCFE3           jsr LCDBC                       ; read "amble" header
+                pshs a                          ; save "amble" type
+                bsr LD013                       ; read block length
+                tfr d,y                         ; save it (in counter)
+                bsr LD013                       ; read block address
+                addd VD3                        ; add load offset
+                std EXECJP                      ; set execution address
+                tfr d,x                         ; put it also in a pointer
+                lda ,s+                         ; set flags on "amble" type
+                lbne LA42D                      ; brif postamble - stop reading
+LCFFA           jsr LC5C4                       ; read a byte
+                ldb CINBFL                      ; EOF?
+                beq LD004                       ; brif not
+                jmp LC352                       ; raise "IE" error
+LD004           sta ,x                          ; save byte in memory
+                cmpa ,x+                        ; does the byte match?
+                beq LD00D                       ; brif so
+                jmp LD709                       ; bad store - throw I/O error
+LD00D           leay -1,y                       ; done whole block?
+                bne LCFFA                       ; brif not
+                bra LCFE3                       ; process another "amble"
+LD013           bsr LD015                       ; read MSB then fall through for LSB
+LD015           jsr LCDBC                       ; read a byte from the file
+                exg a,b                         ; swap bytes in word
+                rts
+; RENAME command
+RENAME          ldx CHARAD                      ; get input pointer
+                pshs x                          ; save it
+                bsr LD056                       ; evaluate source file name
+                lda DCDRV                       ; save drive for first file
+                pshs a
+                bsr LD051                       ; evaluate TO and destination file
+                puls a                          ; get back original drive number
+                cmpa DCDRV                      ; does it match?
+                lbne LB44A                      ; brif not - we can't rename across drives
+                bsr LD059                       ; make sure new file does not already exist
+                puls x                          ; get back input pointer
+                stx CHARAD
+                bsr LD056                       ; re-evaluate source file
+                jsr LC68C                       ; find the source file
+                jsr LC6E5                       ; throw error if not found
+                bsr LD051                       ; evaluate destination file name
+                ldx #DNAMBF                     ; point to destinatoin file name
+                ldu V974                        ; point to directory entry
+                ldb #11                         ; 8 characters file name and 3 characters extension
+                jsr LA59A                       ; replace file name
+                ldb #3                          ; operation code for write
+                stb DCOPC
+                jmp LD6F2                       ; write updated directory sector
+LD051           ldb #0xa5                       ; insist on "TO"
+                jsr LB26F
+LD056           jmp LC935                       ; evaluate file name with default blank extension
+LD059           jsr LC68C                       ; find file
+                ldb #33*2                       ; code for already exists
+                tst V973                        ; does it exist?
+                lbne LAC46                      ; brif so - raise error
+                rts
+; WRITE command
+WRITE           lbeq LB958                      ; do CR if end of statement
+                bsr LD06F                       ; write an item list
+                clr DEVNUM                      ; reset device to screen
+LD06E           rts
+LD06F           cmpa #'#                        ; device number?
+                bne LD082                       ; brif not
+                jsr LA5A5                       ; evaluate device number
+                jsr LA406                       ; check for output
+                jsr GETCCH                      ; end of statement?
+                lbeq LB958                      ; brif so - do newline
+LD07F           jsr SYNCOMMA                    ; need a comma after device
+LD082           jsr LB156                       ; evaluate expression
+                lda VALTYP                      ; number or string?
+                bne LD0A7                       ; brif string
+                jsr LBDD9                       ; convert number to strng
+                jsr LB516                       ; stash it as the current value
+                jsr LB99F                       ; output the string
+LD092           jsr GETCCH                      ; is there more?
+                lbeq LB958                      ; brif not - do newline
+                lda #',                         ; comma for non-tape separator
+                jsr LA35F                       ; set print parameters
+                tst PRTDEV                      ; tape?
+                beq LD0A3                       ; brif not
+                lda #0x0d                       ; carriage return for tape separator
+LD0A3           bsr LD0B9                       ; send separator
+                bra LD07F                       ; process another item
+LD0A7           bsr LD0B0                       ; print leading string delimiter
+                jsr LB99F                       ; print string
+                bsr LD0B0                       ; print ending string delimiter
+                bra LD092                       ; handle separator or next item
+LD0B0           jsr LA35F                       ; set print parameters
+                tst PRTDEV                      ; tape?
+                bne LD06E                       ; brif so
+                lda #'"                         ; string delimiter
+LD0B9           jmp PUTCHR                      ; send character out
+; FIELD command
+FIELD           jsr LC82E                       ; evaluate device number and make sure it's a random file
+                clra                            ; clear total field length counter
+                clrb
+                pshs x,b,a                      ; save field length and FCB pointer
+LD0C3           jsr GETCCH                      ; are we at the end of the statement?
+                bne LD0C9                       ; brif not
+                puls a,b,x,pc                   ; clean up stack and return
+LD0C9           jsr LB738                       ; evaluate comma and expression
+                pshs x,b                        ; save field length (B) and make a hole for a temp
+                clra                            ; zero extend length
+                addd 3,s                        ; add in current accumulated size
+                bcs LD0DA                       ; brif we overflowed
+                ldx 5,s                         ; point to FCB
+                cmpd FCBRLN,x                   ; have we overflowed the record?
+                bls LD0DF                       ; brif not
+LD0DA           ldb #34*2                       ; code for field overflow
+                jmp LAC46                       ; raise error
+LD0DF           ldu 3,s                         ; get old accumulated length
+                std 3,s                         ; save new accumulated length
+                ldd FCBBUF,x                    ; get start of random buffer
+                leau d,u                        ; now U is the start of the field in the buffer
+                stu 1,s                         ; save it so we can set string descriptor
+                ldb #0xff                       ; insist on two byte "AS" token
+                jsr LB26F
+                ldb #0xa7
+                jsr LB26F
+                jsr LB357                       ; evaluate variable
+                jsr LB146                       ; error if it's a number
+                puls b,u                        ; get back field length and buffer address
+                stb ,x                          ; put those in the string descriptor
+                stu 2,x
+                bra LD0C3                       ; look for another entry
+; RSET command
+RSET            skip1lda                        ; set nonzero for right justify and fall through
+; LSET command
+LSET            clra                            ; set zero to flag left justify
+                pshs a                          ; save justification type
+                jsr LB357                       ; evaluate variable
+                jsr LB146                       ; make sure it's a string
+                pshs x                          ; save descriptor address
+                ldx 2,x                         ; get address of string data
+                cmpx #DFLBUF                    ; is it below random buffer area?
+                blo LD119                       ; brif below - throw error
+                cmpx FCBADR                     ; is it above the random buffer area?
+                blo LD11E                       ; brif not - it's good
+LD119           ldb #2*35                       ; code for "set to non-fielded string"
+                jmp LAC46                       ; raise error
+LD11E           ldb #0xb3                       ; insist on =
+                jsr LB26F
+                jsr L8748                       ; evaluate string expression; return details
+                puls y                          ; get back destination descriptor pointer
+                lda ,y                          ; get length of field string
+                beq LD15A                       ; brif empty destination
+                pshs b                          ; save length of new string
+                ldb #0x20                       ; pad characteris space
+                ldu 2,y                         ; point to destination string
+LD132           stb ,u+                         ; blank out string
+                deca                            ; done yet?
+                bne LD132                       ; brif not
+                ldb ,s+                         ; get length of data string
+                beq LD15A                       ; brif that one is NULL
+                cmpb ,y                         ; is data string smaller than destination?
+                blo LD143                       ; brif not
+                ldb ,y                          ; get length of destination string as the copy length
+                clr ,s                          ; we'll do left justify if string is longer
+LD143           ldu 2,y                         ; get address of the destination
+                tst ,s+                         ; left or right justify?
+                beq LD157                       ; brif left set
+                pshs b                          ; save number of bytes to move into field string
+                clra                            ; get negation of that in D (do -DLEN+FLEN)
+                negb
+                sbca #0
+                addb ,y                         ; then add string length of destination to it
+                adca #0
+                leau d,u                        ; now U points to destination offset
+                puls b                          ; get back destination size
+LD157           jmp LA59A                       ; copy data and return
+LD15A           puls a,pc                       ; clean up stack and return
+; FILES command
+FILES           jsr L95AC                       ; reset video display
+                ldd FCBADR                      ; get current size of buffer space
+                subd #DFLBUF
+                pshs d                          ; save it as the default size
+                ldb FCBACT                      ; get number of available disk files
+                pshs b                          ; save it as the default number
+                jsr GETCCH                      ; get input character
+                cmpa #',                        ; is numer of files specified?
+                beq LD181                       ; brif not
+                jsr EVALEXPB                    ; evaluate the number of files wanted
+                cmpb #15                        ; we only allow 15
+                lbhi LB44A                      ; raise error if too many
+                stb ,s                          ; save number of FCBs to allocate
+                jsr GETCCH                      ; see what's after the number
+                beq LD189                       ; brif no buffer size specified
+LD181           jsr SYNCOMMA                    ; insist on a comma
+                jsr LB3E6                       ; evaluate buffer size
+                ifeq DISKVER
+                addd #1
+                endc
+                std 1,s                         ; save buffer size
+LD189           jsr DVEC7                       ; close all disk files
+                ldb ,s                          ; get number of files
+                pshs b                          ; initialize the file number count
+                ldd #DFLBUF                     ; point to start of random buffers
+                addd 2,s                        ; add in size requested for buffer space
+                bcs LD208                       ; raise error if we carry
+                std 2,s                         ; save start of FCBs
+LD199           addd #FCBLEN                    ; add size of one FCB
+                bcs LD208                       ; brif we overflowed
+                dec ,s                          ; added on for all files?
+                bpl LD199                       ; brif not yet (BPL so we set up the system one as well)
+                tstb                            ; are we at an even page boundary?
+                ifeq DISKVER
+                beq LD1AF                       ; brif so
+                else
+                beq LD1A8                       ; brif so
+                endc
+                inca                            ; round up
+                beq LD208                       ; brif we overflowed
+                ifeq DISKVER-1
+LD1A8           bita #1                         ; on an even 512 byte boundary?
+                beq LD1AF                       ; brif so
+                inca                            ; round up
+                beq LD208                       ; brif we overflowed
+                endc
+LD1AF           sta ,s                          ; save MSB of graphics memory
+                ldd VARTAB                      ; get end of program
+                suba GRPRAM                     ; subtract out start of graphics (D is now size of program and graphics)
+                adda ,s                         ; add in the new start of graphics
+                bcs LD208                       ; brif overflow
+                tfr d,x                         ; save new top of program
+                inca                            ; add some extra room for the stack
+                beq LD208                       ; brif overflow
+                cmpd FRETOP                     ; does it fit in memory?
+                bhs LD208                       ; brif not
+                deca                            ; restore actual top of program
+                subd VARTAB                     ; get difference compared to the original top of program
+                addd TXTTAB                     ; add that to the program start
+                tfr d,y                         ; now Y is the new start of the program
+                lda ,s                          ; get back start of graphics memory
+                suba GRPRAM                     ; this gives difference between old graphics start and new grahpics start
+                tfr a,b                         ; we need this twice
+                adda BEGGRP                     ; set new start of active page
+                sta BEGGRP
+                addb ENDGRP                     ; set new end of active page
+                stb ENDGRP
+                puls a,b,u                      ; get back graphics start, number of files, and start of buffers
+                sta GRPRAM                      ; set graphics memory start
+                stb FCBACT                      ; set number of active FCBs
+                stu FCBADR                      ; set start of FCBs
+                ifeq DISKVER-1
+                lda CURLIN                      ; in immediate mode?
+                inca
+                beq LD1EF                       ; brif so
+                tfr y,d                         ; calculate how much the program is moving
+                subd TXTTAB
+                addd CHARAD                     ; adjust input pointer for the change
+                std CHARAD
+                endc
+LD1EF           ldu VARTAB                      ; get old end of program
+                stx VARTAB                      ; save new end of program
+                cmpu VARTAB                     ; which way did it move?
+                bhi LD20B                       ; brif it moved up
+LD1F8           lda ,-u                         ; move a byte down
+                sta ,-x
+                cmpu TXTTAB                     ; at start?
+                bne LD1F8                       ; brif not
+                sty TXTTAB                      ; set new start of program
+                clr -1,y                        ; make sure there's a NUL before the program
+                bra LD21B                       ; clean up
+LD208           jmp LAC44                       ; raise OM error
+LD20B           ldu TXTTAB                      ; get old start of program
+                sty TXTTAB                      ; save new start of program
+                clr -1,y                        ; make sure there's a NUL before the program
+LD212           lda ,u+                         ; move a byte up
+                sta ,y+
+                cmpy VARTAB                     ; at end yet?
+                bne LD212                       ; brif not
+LD21B           ldu #FCBV1                      ; point to FCB pointers
+                ldx FCBADR                      ; point to start of FCBs
+                clrb                            ; file counter
+LD222           stx ,u++                        ; set FCB pointer
+                clr <<FCBTYP,x                  ; mark FCB as closed
+                leax FCBLEN,x                   ; point to next FCB
+                incb                            ; bump file counter
+                cmpb FCBACT                     ; do we have enough of them yet?
+                bls LD222                       ; brif not (BLS so we include system FCB)
+                jmp L96CB                       ; fix up line pointers, etc.
+; UNLOAD command
+UNLOAD          bsr LD24F                       ; get drive number
+                clrb                            ; clear file counter
+LD236           incb                            ; bump file counter
+                jsr LC749                       ; point to FCB
+                beq LD249                       ; brif file not open
+                lda FCBDRV,x                    ; is it on the right drive?
+                cmpa DCDRV
+                bne LD249                       ; brif not
+                pshs b                          ; save file counter
+                jsr LCB06                       ; close the file
+                puls b                          ; restore file counter
+LD249           cmpb FCBACT                     ; done all files?
+                bls LD236                       ; brif not (includes system FCB)
+                rts
+; Parse drive number; use default if none given
+LD24F           ldb DEFDRV                      ; set default drive
+                jsr GETCCH                      ; is there something there?
+                beq LD25F                       ; brif not
+LD256           jsr EVALEXPB                    ; evaluate drive number
+                cmpb #3                         ; valid?
+                lbhi LA61F                      ; brif not
+LD25F           stb DCDRV                       ; set drive number
+                rts
+; BACKUP command
+BACKUP          lbeq LA61F                      ; raise error if no drive numbers
+                jsr L95AC                       ; reset display
+                jsr LD256                       ; get source drive number
+                stb DBUF0+255                   ; save it (we're going to put our stack in DBUF0)
+                jsr GETCCH                      ; is there something else?
+                beq LD27B                       ; brif not
+                ldb #0xa5                       ; insist on TO
+                jsr LB26F
+                jsr LD256                       ; fetch destination drive
+LD27B           lds #DBUF0+255                  ; put the stack somewhere safe (source drive number already there)
+                pshs b                          ; save destination drive number
+                jsr LA5C7                       ; bail of there's more
+                jsr DVEC7                       ; close files
+                clr ,-s                         ; initialize track counter
+                ldx #DFLBUF-1                   ; point to start of the heap
+LD28C           inc ,s                          ; bump track counter
+                leax SECMAX*SECLEN,x            ; add a whole track to the count
+                cmpx MEMSIZ                     ; does it fit in memory?
+                bls LD28C                       ; brif so
+                dec ,s                          ; decrement track counter
+                lbeq LAC44                      ; error if less than one track memory available
+                lda #TRKMAX                     ; get maximum number of tracks
+                clrb                            ; set tracks copied to 0
+                pshs a,b                        ; save track counters
+                com DRESFL                      ; force a "reset" of the disk system
+LD2A4           clrb                            ; initialize write counter
+LD2A5           incb                            ; add one to track counter
+                dec ,s                          ; whole disk done?
+                beq LD2AE                       ; brif not
+                cmpb 2,s                        ; will it fit in memory?
+                bne LD2A5                       ; brif so
+LD2AE           stb TMPLOC                      ; save number of tracks to copy
+                ldb 4,s                         ; get source drive number
+                bsr LD2FC                       ; read TMPLOC tracks
+                lda #0xff                       ; set source/dest flag to dest
+                jsr LD322                       ; show prompt if needed
+                ldb 3,s                         ; get destination drive
+                bsr LD2FF                       ; write TMPLOC tracks
+                tst ,s                          ; is there anything left?
+                beq LD2CD                       ; brif not - we're done
+                clra                            ; set source/desetination to source
+                jsr LD322                       ; show prompt
+                ldb 1,s                         ; get tracks written
+                addb TMPLOC                     ; account for the ones we just wrote
+                stb 1,s                         ; save new written counter
+                bra LD2A4                       ; go copy some more tracks
+LD2CD           bsr LD2D2                       ; check for re-init
+                jmp LAC73                       ; return to immediate mode
+LD2D2           puls u                          ; get return address (we might be resetting the stack)
+                lda DRESFL                      ; reset desired?
+                beq LD2EF                       ; brif not
+                ldx #FCBV1                      ; point to FCB addresses
+                clra                            ; set file counter to 0
+LD2DD           clr [,x++]                      ; mark FCB as closed
+                inca                            ; bump file counter
+                cmpa FCBACT                     ; end of allocated FCBs?
+                bls LD2DD                       ; brif not
+                ldx TXTTAB                      ; get start of program
+                clr -1,x                        ; make sure there's a NUL there
+                jsr LAD19                       ; do a "NEW"
+                clr DRESFL                      ; mark reset as not needed
+LD2EF           lda DLODFL                      ; were we loading something?
+                beq LD2FA                       ; brif not
+                clr DLODFL                      ; clear out the loading state
+                jsr LAD19                       ; empty out the program
+LD2FA           jmp ,u                          ; return to caller
+LD2FC           lda #2                          ; opcode for read
+                skip2
+LD2FF           lda #3                          ; opcode for write
+                std DCOPC                       ; save operation and drive number
+                lda 3,s                         ; get number of the first track to write
+                sta DCTRK                       ; tell DSKCON
+                ldx #DFLBUF                     ; put track buffer at the start of the heap
+                stx DCBPT
+                lda TMPLOC                      ; get track counter
+LD30E           ldb #1                          ; start at sector 1
+LD310           stb DSEC                        ; set sector
+                jsr LD6F2                       ; read or write a sector
+                inc DCBPT                       ; bump buffer pointer
+                incb                            ; bump sector number
+                cmpb #SECMAX                    ; end of track?
+                bls LD310                       ; brif not
+                inc DCTRK                       ; bump track
+                deca                            ; done all the tracks?
+                bne LD30E                       ; brif not
+                rts
+LD322           ldb 5,s                         ; get destination drive number
+                cmpb 6,s                        ; compare to source
+LD326           bne LD35E                       ; brif no prompt needed
+                clr RDYTMR                      ; reset drive motor
+                clr DSKREG
+                clr DRGRAM
+                pshs a                          ; save source/dest flag
+                jsr LA928                       ; clear screen
+                ldx #LD35F                      ; point to "source"
+                ldb #13                         ; 13 bytes
+                lda ,s+                         ; set flags on source/dest flag
+                beq LD344                       ; brif source
+                ldx #LD36C                      ; point to "dest"
+                ldb #18                         ; 18 bytes
+LD344           jsr LB9A2                       ; display message
+                ldx #LD37E                      ; point to remainder of message
+                ldb #27                         ; 27 bytes
+                jsr LB9A2                       ; display it
+                ldd #0x6405                     ; set up SOUND parameters
+                sta SNDTON
+                jsr LA951                       ; do a beep
+LD357           jsr LA171                       ; read generic input (shows cursor)
+                cmpa #0x0d                      ; carriage return?
+                bne LD357                       ; bri fnot
+LD35E           rts
+LD35F           fcc 'INSERT SOURCE'
+LD36C           fcc 'INSERT DESTINATION'
+LD37E           fcc ' DISKETTE AND'
+                fcb 0x0d
+                fcc "PRESS 'ENTER'"
+; Save file name and extension on stack, and also the current drive number
+LD399           puls y                          ; get return address
+                ldb #11                         ; 11 characters for both name and extension
+                ldx #DNAMBF+11                  ; point to end of buffer
+LD3A0           lda ,-x                         ; fetch a file name character
+                pshs a                          ; stuff it on the stack
+                decb                            ; done yet?
+                bne LD3A0                       ; brif not
+                lda DCDRV                       ; save drive number
+                pshs a
+                jmp ,y                          ; return to caller
+; Copy drive, filename, and extension from X to state
+LD3AD           lda ,x+                         ; set drive number
+                sta DCDRV
+                ldb #11                         ; 11 characters in file name and extension
+                ldu #DNAMBF                     ; point to disk file name buffer
+                jmp LA59A                       ; copy the file name
+; COPY command
+; NOTE: an error during COPY will cause the system to hang due to the FCB's buffer pointer
+; being moved out of normal buffer space.
+COPY            jsr LC935                       ; get source file name
+                bsr LD399                       ; save it on the stack
+                clr ,-s                         ; set flag for "single disk" copy
+                jsr GETCCH                      ; is there a destination?
+                beq LD3CE                       ; brif not - single disk (swapping)
+                com ,s                          ; set to "two parameter" copy
+                ldb #0xa5                       ; insist on TO
+                jsr LB26F
+                jsr LC935                       ; parse the destination file name
+LD3CE           bsr LD399                       ; save destination file name
+                jsr LA5C7                       ; bail if more stuff
+                jsr DVEC7                       ; close everything
+                clr ,-s                         ; clear sector counter
+                ifeq DISKVER
+                leax -100,s                     ; leave a buffer below the stack
+                else
+                leax -SECLEN,s                  ; point one sector below the stack
+                endc
+LD3DC           inc ,s                          ; bump sector counter
+                leax -SECLEN,x                  ; move back a sector
+                cmpx ARYEND                     ; did we hit the top of variables?
+                bhs LD3DC                       ; brif not
+                dec ,s                          ; decrement off the last one that didn't fit
+                lbeq LAC44                      ; brif not at least one sector free memory
+                leax 14,s                       ; set up for source file name/drive
+                bsr LD3AD
+                jsr LC68C                       ; find file
+                jsr LC6E5                       ; error if not found
+                ldx V974                        ; get directory data pointer
+                ldu DIRLST,x                    ; get file type and last sector data
+                ldx DIRTYP,x
+                pshs u,x                        ; save them
+                jsr LC79D                       ; read FAT data
+                ldb V976                        ; get first granule in file
+                jsr LCD1E                       ; count granules in chain
+                pshs a                          ; save number of granules in file
+                deca                            ; subtract off last granule (may be partial)
+                andb #0x3f                      ; get number of sectors in last granule
+                pshs b                          ; save sectors in last granule
+                tfr a,b                         ; zero extend to granule count to D
+                clra
+                jsr LC779                       ; get number of sectors in complete granules
+                addb ,s                         ; add in partial sector count
+                adca #0
+                ldx #1                          ; initialize record counter to 1
+                pshs x,b,a                      ; save record counter and sector counter
+LD41E           clrb                            ; set sector counter to 0
+                ldx ,s                          ; get number of sectors remaining in the file
+                beq LD42C                       ; brif none left
+LD423           incb                            ; add a sector to counter
+                leax -1,x                       ; at bottom of file?
+                beq LD42C                       ; brif so
+                cmpb 10,s                       ; at maximum memory space?
+                bne LD423                       ; brif not
+LD42C           stx ,s                          ; save number of sectors that will be left after this iteration
+                stb 4,s                         ; save number of sectors to be copied this time
+                bsr LD482                       ; get sectors to buffer
+                lda #0xff                       ; show swap message for dest
+                bsr LD476
+                tst 5,s                         ; do we need to test for enough free space?
+                beq LD45F                       ; brif not
+                leax 11,s                       ; retrieve destination file parameters
+                jsr LD3AD
+                jsr LD059                       ; find the file, AE error if it exists
+                jsr LC79D                       ; get FAT data
+                jsr LC755                       ; point to FAT
+                leax FATCON,x                   ; point to granuledata
+                lda 5,s                         ; get number of granules in file
+                ldb #GRANMX                     ; maximum granules to check
+LD44E           com ,x                          ; is granule free?
+                bne LD455                       ; brif not
+                deca                            ; found enough?
+                beq LD45D                       ; brif not
+LD455           com ,x+                         ; restore FAT data
+                decb                            ; run through whole fat?
+                bne LD44E                       ; brif not
+                jmp LC7F8                       ; do "disk full"
+LD45D           com ,x                          ; restore FAT data
+LD45F           bsr LD47C                       ; put data from memory to destination file
+                ldx ,s                          ; get number of sectors left
+                beq LD472                       ; brif none - we're done
+                ldd 2,s                         ; get current recordcounter
+                addb 4,s                        ; add in number of sectors
+                adca #0
+                std 2,s                         ; save new record counter
+                clra                            ; show source message if needed
+                bsr LD476
+                bra LD41E                       ; copy some more stuff
+LD472           leas 36,s                       ; clean up stack
+                rts
+LD476           tst 25,s                        ; doing a "single disk" copy?
+                jmp LD326                       ; show message if needed
+; put or get data for copy
+LD47C           lda #0xff                       ; put flag
+                leax 13,s                       ; point to destination file
+                bra LD486                       ; go do the write
+LD482           clra                            ; get flag
+                leax 26,s                       ; point to source file
+LD486           sta VD8                         ; save get/put flag
+                jsr LD3AD                       ; fetch file parameters from stack
+                ldx 8,s                         ; get file type and ASCII flag
+                stx DFLTYP                      ; save it
+                ldx #SECLEN                     ; set record length to one sector
+                stx DFFLEN
+                lda #'R                         ; set type to "random"
+                ldb FCBACT                      ; point to system FCB
+                incb
+                jsr LC48D
+                ldx FCBTMP                      ; get FCB pointer
+                ldd #SECLEN                     ; set number of bytes in last sector to one sector
+                std FCBLST,x
+                ldb 6,s                         ; get number of sectors to read/write
+                beq LD4D4                       ; brif none
+                ldb VD8                         ; get or put?
+                andb 7,s                        ; is it first time on put?
+                beq LD4BA                       ; brif not
+                ldd 2,s                         ; get number of sectors remaining
+                addb 6,s                        ; add to number copied this time
+                adca #0
+                jsr LC2E6                       ; put the last record in the file (this allocates the file)
+LD4BA           ldx FCBTMP                      ; point to FCB
+                ldu 4,s                         ; get current record number
+                stu FCBREC,x                    ; save in FCB
+                ldb 6,s                         ; get number of sectors to move
+                ldu ARYEND                      ; point to start of free memory
+LD4C4           pshs u,b                        ; save buffer pointer and counter
+                ldx FCBTMP                      ; fetch FCB pointer
+                stu FCBBUF,x                    ; set buffer to free memory (will cause hang on error)
+                jsr LC2EA                       ; do get or put
+                inc 1,s                         ; bump buffer pointer
+                puls b,u                        ; get back buffer pointer and sector count
+                decb                            ; done all yet?
+                bne LD4C4                       ; brif not
+LD4D4           ldx FCBTMP                      ; get FCB pointer
+                ldu #DFLBUF                     ; reset buffer pointer to bottom of buffer area
+                stu FCBBUF,x
+                ldb VD8                         ; first time through on PUT?
+                andb 7,s
+                beq LD4EA                       ; brif not
+                clr 7,s                         ; reset the "first time" flag
+                ldd 10,s                        ; get bytes in last sector
+                ora #0x80                       ; set "pre-save" flag
+                std FCBLST,x                    ; set correct last sector size
+LD4EA           jmp LCB06                       ; close the file
+; DSKI$ command
+DSKI            bsr LD527                       ; get drive, track, and sector
+                bsr LD51C                       ; evaluate frist string sand save descriptor address
+                pshs x
+                bsr LD51C                       ; evaluate second string and save descriptor address
+                pshs x
+                ldb #2                          ; read operation
+                jsr LD58F                       ; read sector
+                ldu #DBUF0+128                  ; point to second half
+                puls x                          ; get descriptor for second string
+                bsr LD508                       ; stow second string
+                ldu #DBUF0                      ; point to first half
+                puls x                          ; get descriptor for first string
+LD508           pshs u,x                        ; save source data and descriptor
+                ldb #128                        ; do 128 bytes exactly
+                jsr LB50F                       ; reserve space
+                leau ,x                         ; point to reserved space
+                puls x                          ; get string descriptor address
+                stb ,x                          ; save length in descriptor
+                stu 2,x                         ; save data pointer
+                puls x                          ; get buffer pointer
+LD519           jmp LA59A                       ; copy bytes to string
+LD51C           jsr SYNCOMMA                    ; make sure there's a comma
+                ldx #LB357                      ; point to variable evaluation routine
+                bsr LD553                       ; evaluate variable
+LD524           jmp LB146                       ; make sure we have a string
+LD527           jsr EVALEXPB                    ; evaluate 8 bit expression
+                cmpb #3                         ; valid drive?
+                bhi LD54A                       ; brif not
+                pshs b                          ; save it
+                jsr LB738                       ; evaluate track expression (after a comma)
+                cmpb #TRKMAX-1                  ; valid track?
+                bhi LD54A                       ; brif not
+                pshs b                          ; save track number
+                jsr LB738                       ; evaluate comma followed by sector number
+                stb DSEC                        ; set DSKCON variable
+                decb                            ; zero-base it
+                cmpb #SECMAX-1                  ; is it a valid sector?
+                bhi LD54A                       ; brif not
+                puls a,b                        ; get drive and track
+                sta DCTRK                       ; set DSKCON
+                stb DCDRV
+                rts
+LD54A           jmp LB44A                       ; raise FC error
+LD54D           jsr SYNCOMMA                    ; insist on a comma
+                ldx #LB156                      ; evaluate expression pointer
+LD553           ldb DCDRV                       ; save drive, track, and sector values
+                ldu DCTRK
+                pshs u,b                        ; save them
+                jsr ,x                          ; evaluate variable or expression
+                puls b,u                        ; restore DSKCON
+                stb DCDRV
+                stu DCTRK
+                rts
+; DSKO$ command
+DSKO            bsr LD527                       ; evaluate drive, track, and sector
+                bsr LD54D                       ; evaluate string 1
+                bsr LD524                       ; make sure it's a string
+                ldx FPA0+2                      ; get descriptor address
+                pshs x                          ; save it
+                bsr LD54D                       ; evaluate string 2
+                jsr LB654                       ; get string details
+                pshs x,b                        ; save them
+                clrb                            ; clear full sector (so junk doesn't get in if strings are short)
+                ldx #DBUF0                      ; point to sector buffer
+LD577           clr ,x+                         ; clear a byte
+                decb                            ; done whole sector?
+                bne LD577                       ; brif not
+                puls b,x                        ; get string data
+                ldu #DBUF0+128                  ; point to second half of sector
+                bsr LD519                       ; copy string data (anything over 128 will go in second I/O buffer so harmless)
+                puls x                          ; get first string
+                jsr LB659                       ; fetch string details
+                ldu #DBUF0                      ; point to start of sector buffer
+                bsr LD519                       ; copy string data (this will overwrite up to 255 bytes!)
+                ldb #3                          ; write operation
+LD58F           ldx #DBUF0                      ; point to sector buffer
+                stx DCBPT
+                stb DCOPC                       ; set read/write
+                jmp LD6F2                       ; go read/write sector
+; DSKINI command
+DSKINI          lbeq LA61F                      ; error if no drive number specified
+                jsr LD256                       ; parse driven umber
+                ldb #4                          ; default skip factor is 4
+                jsr GETCCH                      ; is there a skip factor?
+                beq LD5B2                       ; brif not
+                jsr LB738                       ; evaluate comma followed by skip factor
+                cmpb #17                        ; max value is 16
+                lbhs LB44A                      ; brif too high
+                jsr LA5C7                       ; carp if there's anything else
+LD5B2           pshs b                          ; save skip factor
+                ldx #DBUF1+SECMAX               ; poitn to end of sector number scratch area
+                ldb #SECMAX                     ; get the maximum sector number
+LD5B9           clr ,-x                         ; mark sector number unset
+                decb                            ; done all of them?
+                bne LD5B9                       ; brif not
+                clra                            ; reset sector counter
+                bra LD5CE                       ; start assigning sector numbers
+LD5C1           addb ,s                         ; add in skip factor
+LD5C3           incb                            ; bump sector number
+LD5C4           subb #SECMAX                    ; remove a whole track worth
+                bhs LD5C4                       ; brif we can still do more
+                addb #SECMAX                    ; undo extra subtraction
+                tst b,x                         ; has this sector been numbered?
+                bne LD5C3                       ; brif so - try again on next one
+LD5CE           inca                            ; bump sector number
+                sta b,x                         ; set actual sector number
+                cmpa #SECMAX                    ; done all?
+                blo LD5C1                       ; brif not
+                leas 1,s                        ; remove skip factor - we don't need it
+                ldx #DFLBUF+0x1888-2            ; point to top of memory used by DSKINI (for track image)
+                cmpx MEMSIZ                     ; does it fit?
+                lbhi LAC44                      ; brif not
+                jsr DVEC7                       ; close files
+                com DRESFL                      ; cause reset of things
+                lds #DBUF1+SECLEN               ; put stack somewhere safe
+                jsr L95AC                       ; reset display
+                lda #0                          ; restore head to track 0
+                sta DCOPC
+                ifeq DISKVER-1
+                clr DCTRK                       ; set track number to 0 (used as a track counter for the format)
+                endc
+                jsr LD6F2                       ; restorehead to track 0
+                clr RDYTMR                      ; don't allow motor to turn off
+                lda #0xc0                       ; FDC read address code
+                sta FDCREG                      ; instruct FDC
+                jsr LD7D1                       ; wait until drive ready
+                ifeq DISKVER
+                lbne LD688                      ; brif drive not ready
+                clr DCTRK                       ; reset track counter
+                bra LD620                       ; go format tracks
+                else
+                beq LD620                       ; brif drive ready
+                jmp LD688                       ; raise error if not ready
+                endc
+LD606           cmpa #22                        ; precomp?
+                blo LD612                       ; brif not
+                lda DRGRAM                      ; enable precomp
+                ora #0x10
+                sta DSKREG
+LD612           lda #0x53                       ; "step in"
+                sta FDCREG                      ; go do a step
+                exg a,a                         ; wait for FDC status to stabilize
+                exg a,a
+                jsr LD7D1                       ; wait for ready
+                bne LD688                       ; bri fnot ready - raise error
+LD620           jsr LD7F0                       ; wait for a bit
+                bsr LD691                       ; build formatted track
+                ldy #FDCREG+3                   ; point to data register
+                orcc #0x50                      ; disable interrupts
+                ldx #LD64F                      ; where to return to
+                stx DNMIVC                      ; set up NMI escaper
+                ldx #DFLBUF                     ; point to track image
+                lda FDCREG                      ; reset status of FDC
+                lda #0xff                       ; enable NMI escaper
+                sta NMIFLG
+                ldb #0xf4                       ; write track command
+                stb FDCREG                      ; instruct FDC
+                lda DRGRAM                      ; enable HALT
+                ora #0x80
+                sta DSKREG
+LD649           ldb ,x+                         ; fetch track byte
+                stb ,y                          ; stuff it out to FDC
+                bra LD649                       ; do another ASAP (HALT will clock this)
+LD64F           lda FDCREG                      ; fetch status
+                andcc #0xaf                     ; restore interrupts
+                anda #0x44                      ; keep only write protect and lost data
+                sta DCSTA                       ; save status
+                bne LD688                       ; brif error
+                inc DCTRK                       ; bump track number
+                lda DCTRK                       ; done all tracks?
+                cmpa #TRKMAX
+                bne LD606                       ; brif not
+                lda #2                          ; DSKCON read operation
+                sta DCOPC
+                ldx #DBUF0                      ; point to disk buffer
+                stx DCBPT
+                ldu #DBUF1                      ; point to sector numbers
+                clra                            ; reset track counter
+LD66F           sta DCTRK                       ; set track
+                clrb                            ; reset sector counter
+LD672           lda b,u                         ; get real sector number
+                sta DSEC                        ; tell DSKCON
+                jsr LD6F2                       ; read a sector
+                incb                            ; bump sector counter
+                cmpb #SECMAX                    ; done whole track?
+                blo LD672                       ; brif not
+                lda DCTRK                       ; get track number
+                inca                            ; bump it
+                cmpa #TRKMAX                    ; done all?
+                blo LD66F                       ; brif not
+                jmp LD2CD                       ; do the reset thing if needed
+LD688           clr DRGRAM                      ; stop drive motors and selects
+                clr DSKREG
+                jmp LD701                       ; wait for ready signal
+LD691           ldx #DFLBUF                     ; point to track buffer
+                ldd #0x204e                     ; write out 32 * 0x4e
+                bsr LD6C2
+                clrb                            ; reset sector counter
+LD69A           pshs b                          ; save sector counter
+                ldu #DBUF1                      ; point to sector numbers
+                ldb b,u                         ; get real sector number
+                stb DSEC                        ; save it
+                ldu #LD6D4                      ; point to format table for a sector
+                ldb #3                          ; process three blocks
+                bsr LD6C8
+                lda DCTRK                       ; save track number
+                sta ,x+
+                clr ,x+                         ; set side number to 0
+                lda DSEC                        ; set sector number
+                sta ,x+
+                ldb #9                          ; process 9 blocks
+                bsr LD6C8
+                puls b                          ; get sector counter
+                incb                            ; bump it
+                cmpb #SECMAX                    ; done all?
+                blo LD69A                       ; brif not - do another sector
+                ldd #0xc84e                     ; write 200 times 0x4e for track trailer
+LD6C2           stb ,x+                         ; stow a byte
+                deca                            ; done enough?
+                bne LD6C2                       ; brif not
+                rts
+LD6C8           pshs b                          ; save item counter
+                ldd ,u++                        ; get count and data byte
+                bsr LD6C2                       ; process it
+                puls b                          ; get item count back
+                decb                            ; done all?
+                bne LD6C8                       ; brif not
+                rts
+LD6D4           fcb 8,0                         ; SYNC field
+                fcb 3,0xf5
+                fcb 1,0xfe                      ; address mark
+                ; track, side, sector here
+                fcb 1,1                         ; sector size flag
+                fcb 1,0xf7                      ; CRC request
+                fcb 22,0x4e                     ; post-ID gap
+                fcb 12,0                        ; sync field
+                fcb 3,0xf5
+                fcb 1,0xfb                      ; data address mark
+                fcb 0,0xff                      ; default track data
+                fcb 1,0xf7                      ; CRC request
+                fcb 24,0x4e                     ; post data gap
+                ifeq DISKVER-1
+; DOS command
+DOS             bne LD742                       ; brif argument given
+                jmp [DOSVEC]                    ; transfer control to DOS command
+                endc
+; General sector read/write routine; this implements VERIFY on write and does several retries
+LD6F2           pshs b                          ; save register
+                ldb #5                          ; we'll try 5 times on VERIFY failure
+                stb ATTCTR
+                puls b                          ; restore register
+LD6FB           bsr DSKCON                      ; execute command
+                tst DCSTA                       ; success?
+                beq LD70E                       ; brif so
+LD701           lda DCSTA                       ; get status
+                ldb #2*30                       ; code for write protect
+                bita #0x40                      ; was it write protected?
+                bne LD70B                       ; brif so
+LD709           ldb #2*20                       ; I/O error code
+LD70B           jmp LAC46                       ; raise error
+LD70E           pshs a                          ; save A
+                lda DCOPC                       ; was it write?
+                cmpa #3
+                puls a                          ; restore register
+                bne LD742                       ; brif not
+                tst DVERFL                      ; verify?
+                beq LD742                       ; brif not
+                pshs u,x,b,a                    ; save registers
+                lda #2                          ; set for read
+                sta DCOPC
+                ldu DCBPT                       ; get original buffer pointer
+                ldx #DBUF1                      ; point to secondary buffer
+                stx DCBPT
+                bsr DSKCON                      ; read the sector
+                stu DCBPT                       ; restore buffer pointer
+                lda #3                          ; restore write operation
+                sta DCOPC
+                lda DCSTA                       ; did we have a problem?
+                bne LD743                       ; brif so
+                clrb                            ; check 256 bytes
+LD737           lda ,x+                         ; compare two bytes
+                cmpa ,u+
+                bne LD743                       ; brif no match - error
+                decb                            ; done all?
+                bne LD737                       ; brif not
+                puls a,b,x,u                    ; restore registers
+LD742           rts
+LD743           puls a,b,x,u                    ; restore registers
+                dec ATTCTR                      ; tried enough times?
+                bne LD6FB                       ; brif not - try again
+                ldb #2*36                       ; code for verify error
+                bra LD70B                       ; raise error
+; VERIFY command
+VERIFY          clrb                            ; off flag
+                cmpa #0xaa                      ; OFF?
+                beq LD75A                       ; brif so
+                comb                            ; set to on flag
+                cmpa #0x88                      ; ON?
+                lbne LB277                      ; brif not - raise error
+LD75A           stb DVERFL                      ; set verify state
+                jmp GETNCH                      ; eat the ON/OFF and return
+; DSKCON - the main disk I/O driver
+DSKCON          pshs u,y,x,b,a                  ; save registers
+                lda #5                          ; retry 5 times
+                pshs a                          ; save retry counter
+LD765           clr RDYTMR                      ; reset drive timeout (so drive won't turn off if it's already on)
+                ldb DCDRV                       ; get drive number
+                ldx #LD89D                      ; point to drive enable masks
+                lda DRGRAM                      ; get control register value
+                anda #0xa8                      ; keep only motor, halt, double density
+                ora b,x                         ; set drive select lines
+                ora #0x20                       ; set double density
+                ldb DCTRK                       ; get desired track
+                cmpb #22                        ; precomp?
+                blo LD77E                       ; brif not
+                ora #0x10                       ; enable precomp
+LD77E           tfr a,b                         ; save image prior to enabling motors
+                ora #8                          ; turn on motors
+                sta DRGRAM                      ; actuall do all that stuff above
+                sta DSKREG
+                bitb #8                         ; were motors already on?
+                bne LD792                       ; brif so - don't wait
+                jsr LA7D1                       ; wait quite a while
+                jsr LA7D1                       ; wait quite a while longer
+LD792           bsr LD7D1                       ; wait until read
+                bne LD7A0                       ; brif timed out
+                clr DCSTA                       ; clear status (set no error)
+                ldx #LD895                      ; point to command jump table
+                ldb DCOPC                       ; get operation code
+                aslb                            ; two bytes per routine address
+                jsr [b,x]                       ; do operation
+LD7A0           puls a                          ; get back retry count
+                ldb DCSTA                       ; get status
+                beq LD7B1                       ; brif no error
+                deca                            ; retried enough?
+                beq LD7B1                       ; brif so
+                pshs a                          ; save retry counter again
+                bsr LD7B8                       ; restore head to track 0
+                bne LD7A0                       ; brif error
+                bra LD765                       ; try command again
+LD7B1           lda #120                        ; drive timeout is 120 VSYNC ticks (2 seconds for 60Hz)
+                sta RDYTMR
+                puls a,b,x,y,u,pc               ; restore registers and return
+LD7B8           ldx #DR0TRK                     ; point to track table
+                ldb DCDRV                       ; get drive number
+                clr b,x                         ; mark drive on track 0
+                lda #3                          ; restore head to track 0, unloaded, 30ms step
+                sta FDCREG                      ; go do it
+                exg a,a                         ; wait for status to stabilize
+                exg a,a
+                bsr LD7D1                       ; wait for ready
+                bsr LD7F0                       ; wait somemore
+                anda #0x10                      ; keep only seek error
+                sta DCSTA                       ; set result
+LD7D0           rts
+LD7D1           ldx ZERO                        ; get timeout counter
+LD7D3           leax -1,x                       ; count down
+                beq LD7DF                       ; brif timed out
+                lda FDCREG                      ; get status
+                bita #1                         ; is it ready?
+                bne LD7D3                       ; brif not
+                rts
+LD7DF           lda #0xd0                       ; force interrupt
+                sta FDCREG
+                exg a,a                         ; wait for status to stabilize
+                exg a,a
+                lda FDCREG                      ; clear status
+                lda #0x80                       ; return not ready status
+                sta DCSTA
+                rts
+LD7F0           ldx #8750                       ; delay for about half of a long while
+LD7F3           leax -1,x                       ; count down
+                bne LD7F3                       ; brif not done
+                rts
+LD7F8           lda #0x80                       ; code for read sector
+                skip2
+LD7FB           lda #0xa0                       ; code for write sector
+                pshs a                          ; save operation
+                ldx #DR0TRK                     ; point to track state table
+                ldb DCDRV                       ; get drive number
+                abx                             ; point to correct drive table
+                ldb ,x                          ; get current track number
+                stb FDCREG+1                    ; tell FDC about it
+                cmpb DCTRK                      ; is it the one we want?
+                beq LD82C                       ; brif so - no stepping needed
+                lda DCTRK                       ; get desired track
+                sta FDCREG+3                    ; tell the FDC that too
+                sta ,x                          ; record that drive is there
+                lda #0x17                       ; seek to desired track, unloaded, 30ms step, verify destination
+                sta FDCREG
+                exg a,a                         ; wait for status to be stable
+                exg a,a
+                bsr LD7D1                       ; wait for ready
+                bne LD82A                       ; brif timed out
+                bsr LD7F0                       ; wait some more
+                anda #0x18                      ; keep only seek error or CRC error in ID
+                beq LD82C                       ; brif no errors
+                sta DCSTA                       ; save error state
+LD82A           puls a,pc                       ; clean up stack and return
+LD82C           lda DSEC                        ; get desired sector
+                sta FDCREG+2                    ; tell FDC
+                ldx #LD88B                      ; point to escape routine
+                stx DNMIVC                      ; set up NMI escaper
+                ldx DCBPT                       ; point to I/O buffer
+                lda FDCREG                      ; reset FDC status
+                lda DRGRAM                      ; get control register image
+                ora #0x80                       ; enable HALT
+                puls b                          ; get operation code
+                ldy ZERO                        ; timeout value
+                ldu #FDCREG                     ; point to FDC
+                com NMIFLG                      ; enable escaper
+                orcc #0x50                      ; disable interrupts
+                stb FDCREG                      ; give FDC its marching orders
+                exg a,a                         ; wait for stable status
+                exg a,a
+                cmpb #0x80                      ; read?
+                beq LD875                       ; brif so
+                ldb #2                          ; DRQ mask
+LD85B           bitb ,u                         ; is it ready for a byte?
+                bne LD86B                       ; brif not
+                leay -1,y                       ; timed out?
+                bne LD85B                       ; brif not
+LD863           clr NMIFLG                      ; disable NMI escaper
+                andcc #0xaf                     ; enable interrupts
+                jmp LD7DF                       ; force interrupt, etc.
+LD86B           ldb ,x+                         ; get byte from buffer
+                stb FDCREG+3                    ; send it out
+                sta DSKREG                      ; reprogram control register
+                bra LD86B                       ; send more
+LD875           ldb #2                          ; DRQ mask bit
+LD877           bitb ,u                         ; is a byte ready?
+                bne LD881                       ; brif not
+                leay -1,y                       ; timed out?
+                bne LD877                       ; brif not
+                bra LD863                       ; bail out
+LD881           ldb FDCREG+3                    ; get input data
+                stb ,x+                         ; put in buffer
+                sta DSKREG                      ; reprogram control register
+                bra LD881                       ; read more
+LD88B           andcc #0xaf                     ; enable interrupts
+                lda FDCREG                      ; get status from FDC
+                anda #0x7c                      ; keep write protect, write fault, not found, CRC, or lost data
+                sta DCSTA                       ; set status
+                rts
+LD895           fdb LD7B8                       ; reset head to track 0
+                fdb LD7D0                       ; no-op - just spin up drives
+                fdb LD7F8                       ; read sector
+                fdb LD7FB                       ; write sector
+LD89D           fcb 0x01                        ; drive select 0
+                fcb 0x02                        ; drive select 1
+                fcb 0x04                        ; drive select 2
+                fcb 0x40                        ; drive select 3/side select
+; NMI handler
+DNMISV          lda NMIFLG                      ; is the escaper enabled?
+                beq LD8AE                       ; brif not
+                ldx DNMIVC                      ; set return to escape hatch
+                stx 10,s
+                clr NMIFLG                      ; disable escaper now that we used it
+LD8AE           rti
+; Disk IRQ handler
+DIRQSV          lda PIA0+3                      ; is it VSYNC?
+                bpl LD8AE                       ; brif HSYNC
+                lda PIA0+2                      ; clear interrupt status
+                lda RDYTMR                      ; are drives waiting to stop?
+                beq LD8CD                       ; brif not
+                deca                            ; count down a tick
+                sta RDYTMR                      ; save new count
+                bne LD8CD                       ; brif they haven't timed out yet
+                lda DRGRAM                      ; get control register image
+                anda #0xb0                      ; turn off motors and drive selects
+                sta DRGRAM
+                sta DSKREG
+LD8CD           jmp L8955                       ; transfer control to Extended Basic's handler
+                ifeq DISKVER-1
+; From here to the DOS command is unused
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+                fcb 0x13,0x34,0x06,0x9D,0xA5,0x27,0x03,0xBD,0x95,0x81,0x96,0xB5,0x97,0xD8,0x35,0x06
+                fcb 0xDD,0xB4,0x4F,0x34,0x56,0xBD,0x95,0x22,0xBD,0x92,0x8F,0xDF,0xD9,0xBD,0x99,0xDF
+                fcb 0x27,0x0F,0xBD,0x99,0xCB,0x86,0x01,0x97,0xD7,0xBD,0x99,0xBA,0x00,0xD7,0xBD,0x99
+                fcb 0xBA,0x10,0xDF,0xDC,0x0D,0xDB,0x26,0x03,0x10,0xDE,0xDC,0x35,0x56,0x0F,0xDB,0x10
+                fcb 0xDF,0xDC,0x30,0x01,0x9F,0xBD,0xDF,0xD1,0x97,0xD7,0x27,0x9F,0x2B,0x06,0x5C,0xD1
+                fcb 0xD6,0x23,0x05,0x5F,0x5D,0x27,0xDD,0x5A,0xD7,0xC0,0xBD,0x99,0xDF,0x27,0x0F,0x10
+                fcb 0x83,0x00,0x03,0x25,0x04,0x30,0x1E,0x8D,0x38,0xBD,0x99,0xCB,0x8D,0x4C,0x43,0x53
+                fcb 0xD3,0xD1,0xDD,0xD1,0x2F,0x16,0xBD,0x95,0x06,0xBD,0x9A,0x12,0x26,0x05,0xCC,0xFF
+                fcb 0xFF,0x20,0xED,0xBD,0x95,0x14,0x8D,0x3E,0x8D,0x5E,0x20,0xE0,0xBD,0x95,0x06,0x30
+                fcb 0x8B,0x9F,0xBD,0x43,0x53,0x83,0x00,0x01,0x2F,0x04,0x1F,0x01,0x8D,0x03,0x7E,0x99
+                fcb 0x34,0xDD,0xCB,0x35,0x20,0xDC,0xBD,0x34,0x16,0x96,0xD7,0x40,0xD6,0xC0,0x34,0x06
+                fcb 0x34,0x20,0xC6,0x02,0xBD,0xAC,0x33,0xDC,0xCB,0x39,0xDD,0xCB,0x35,0x20,0xDC,0xC3
+                fcb 0x34,0x16,0x96,0xD7,0x20,0xE6,0x9E,0xBD,0x9F,0xC3,0x39,0xDD,0xCD,0x10,0x9E,0xC3
+                fcb 0x8D,0xF4,0x10,0x9F,0xBD,0x8D,0x11,0x9E,0xCD,0x30,0x8B,0xC3,0x00,0x01,0x39,0xBD
+                fcb 0x99,0xC6,0x10,0x8E,0x95,0x14,0x20,0x06,0x10,0x8E,0x95,0x06,0xAD,0xA4,0xDE,0x8A
+                fcb 0x9E,0xBD,0x2B,0x17,0x9C,0xD3,0x22,0x13,0x34,0x60,0x8D,0x16,0x27,0x0B,0xBD,0x93
+                fcb 0x77,0x35,0x60,0x33,0x41,0xAD,0xA4,0x20,0xE9,0x35,0x60,0x1F,0x30,0x1F,0x01,0x93
+                fcb 0x8A,0x39,0xAD,0x9F,0x00,0xD9,0x1F,0x89,0xD4,0xD8,0x34,0x06,0xA4,0x84,0xA1,0x61
+                fcb 0x35,0x86,0x9E,0x8A,0xC6,0x01,0x34,0x14,0xBD,0xB1,0x56,0x5F,0xBD,0xA9,0xA2,0xBD
+                fcb 0xA9,0x76,0xBD,0xB6,0x54,0x20,0x02,0x35,0x14,0xD7,0xD8,0x27,0xFA,0x9F,0xD9,0x10
+                fcb 0x27,0x0F,0x31,0x0D,0xD8,0x27,0xF0,0xBD,0x9B,0x98,0x81,0x3B,0x27,0xF5,0x81,0x27
+                fcb 0x27,0xF1,0x81,0x58,0x10,0x27,0x01,0xB2,0x8D,0x02,0x20,0xE7,0x81,0x4F,0x26,0x0D
+                fcb 0xD6,0xDE,0x5C,0x8D,0x5B,0x5A,0xC1,0x04,0x22,0x63,0xD7,0xDE,0x39,0x81,0x56,0x26
+                fcb 0x1A,0xD6,0xDF,0x54,0x54,0xC0,0x1F,0x8D,0x47,0xC1,0x1F,0x22,0x50,0x58,0x58,0x34
+                fcb 0x04,0xCC,0x7E,0x7E,0xAB,0xE4,0xE0,0xE0,0xDD,0xDF,0x39,0x81,0x4C,0x26,0x23,0xD6
+                fcb 0xE1,0x8D,0x2D,0x5D,0x27,0x37,0xD7,0xE1,0x0F,0xE5,0x8D,0x03,0x24,0xFC,0x39,0x0D
+                fcb 0xD8,0x27,0x0A,0xBD,0x9B,0x98,0x81,0x2E,0x27,0x05,0xBD,0x9B,0xE2,0x43,0x39,0x0C
+                fcb 0xE5,0x39,0x81,0x54,0x26,0x0D,0xD6,0xE2,0x8D,0x06,0x5D,0x27,0x10,0xD7,0xE2,0x39
+                fcb 0x7E,0x9B,0xAC,0x81,0x50,0x26,0x24,0xBD,0x9C,0xCB,0x5D,0x26,0x03,0x7E,0xB4,0x4A
+                fcb 0x96,0xE5,0x9E,0xDF,0x34,0x12,0x86,0x7E,0x97,0xDF,0x97,0xE0,0x0F,0xE5,0x8D,0x07
+                fcb 0x35,0x12,0x97,0xE5,0x9F,0xDF,0x39,0x6F,0xE2,0x20,0x40,0x81,0x4E,0x26,0x03,0xBD
+                fcb 0x9B,0x98,0x81,0x41,0x25,0x04,0x81,0x47,0x23,0x05,0xBD,0x9B,0xBE,0x20,0x23,0x80
+                fcb 0x41,0x8E,0x9C,0x5B,0xE6,0x86,0x0D,0xD8,0x27,0x18,0xBD,0x9B,0x98,0x81,0x23,0x27
+                fcb 0x04,0x81,0x2B,0x26,0x03,0x5C,0x20,0x0A,0x81,0x2D,0x26,0x03,0x5A,0x20,0x03,0xBD
+                fcb 0x9B,0xE2,0x5A,0xC1,0x0B,0x22,0xA6,0x34,0x04,0xD6,0xE1,0x96,0xE2,0x3D,0xDD,0xD5
+                fcb 0x33,0x61,0x96,0xDE,0x81,0x01,0x22,0x2C,0x8E,0x9C,0x62,0xC6,0x18,0x3D,0x3A,0x35
+                fcb 0x04,0x58,0x3A,0x31,0x84,0x8D,0x45,0xDD,0xE3,0x8D,0x0C,0x96,0xDF,0x8D,0x0B,0x8D
+                fcb 0x06,0x96,0xE0,0x8D,0x05,0x20,0xF2,0x86,0x7E,0x12,0xB7,0xFF,0x20,0xAE,0xA4,0x30
+                fcb 0x1F,0x26,0xFC,0x39,0x8E,0x9C,0x7A,0xC6,0x0C,0x3D,0x3A,0x35,0x04,0x3A,0x8D,0x1C
+                fcb 0xDD,0xE3,0x8D,0x0C,0x96,0xDF,0x8D,0x0B,0x8D,0x06,0x96,0xE0,0x8D,0x05,0x20,0xF2
+                fcb 0x86,0x7E,0x12,0xB7,0xFF,0x20,0xA6,0x84,0x4A,0x26,0xFD,0x39,0xC6,0xFF,0x96,0xE5
+                fcb 0x27,0x05,0x8B,0x02,0x3D,0x44,0x56,0x39,0x34,0x10,0x0D,0xD8,0x27,0x4D,0x9E,0xD9
+                fcb 0xA6,0x80,0x9F,0xD9,0x0A,0xD8,0x81,0x20,0x27,0xF0,0x35,0x90,0x8D,0xEA,0x81,0x2B
+                fcb 0x27,0x3C,0x81,0x2D,0x27,0x3C,0x81,0x3E,0x27,0x42,0x81,0x3C,0x27,0x39,0x81,0x3D
+                fcb 0x27,0x3F,0xBD,0x90,0xAA,0x25,0x24,0x5F,0x80,0x30,0x97,0xD7,0x86,0x0A,0x3D,0x4D
+                fcb 0x26,0x19,0xDB,0xD7,0x25,0x15,0x0D,0xD8,0x27,0x17,0xBD,0x9B,0x98,0xBD,0x90,0xAA
+                fcb 0x24,0xE6,0x0C,0xD8,0x9E,0xD9,0x30,0x1F,0x9F,0xD9,0x39,0x7E,0xB4,0x4A,0x5C,0x27
+                fcb 0xFA,0x39,0x5D,0x27,0xF6,0x5A,0x39,0x5D,0x27,0xF1,0x54,0x39,0x5D,0x2B,0xEC,0x58
+                fcb 0x39,0x34,0x60,0x8D,0x16,0xBD,0xB7,0x0E,0x35,0xE0,0xBD,0x9C,0x1B,0xC6,0x02,0xBD
+                fcb 0xAC,0x33,0xD6,0xD8,0x9E,0xD9,0x34,0x14,0x7E,0x9A,0x32,0x9E,0xD9,0x34,0x10,0xBD
+                fcb 0x9B,0x98,0xBD,0xB3,0xA2,0x25,0xC4,0xBD,0x9B,0x98,0x81,0x3B,0x26,0xF9,0x35,0x10
+                fcb 0xDE,0xA6,0x34,0x40,0x9F,0xA6,0xBD,0xB2,0x84,0x35,0x10,0x9F,0xA6,0x39,0x4F,0x1F
+                fcb 0x8B,0xDC,0xE3,0x10,0x27,0x0D,0x74,0x93,0xD5,0xDD,0xE3,0x22,0x0D,0x0F,0xE3,0x0F
+                fcb 0xE4,0x35,0x02,0x10,0xEE,0x67,0x84,0x7F,0x34,0x02,0x3B,0x0A,0x0C,0x01,0x03,0x05
+                fcb 0x06,0x08,0x01,0xA8,0x01,0x90,0x01,0x7A,0x01,0x64,0x01,0x50,0x01,0x3D,0x01,0x2B
+                fcb 0x01,0x1A,0x01,0x0A,0x00,0xFB,0x00,0xED,0x00,0xDF,0x00,0xD3,0x00,0xC7,0x00,0xBB
+                fcb 0x00,0xB1,0x00,0xA6,0x00,0x9D,0x00,0x94,0x00,0x8B,0x00,0x83,0x00,0x7C,0x00,0x75
+                fcb 0x00,0x6E,0xA6,0x9C,0x93,0x8B,0x83,0x7B,0x74,0x6D,0x67,0x61,0x5B,0x56,0x51,0x4C
+                fcb 0x47,0x43,0x3F,0x3B,0x37,0x34,0x31,0x2E,0x2B,0x28,0x26,0x23,0x21,0x1F,0x1D,0x1B
+                fcb 0x19,0x18,0x16,0x14,0x13,0x12,0x9E,0x8A,0xC6,0x01,0x34,0x14,0xD7,0xC2,0x9F,0xD5
+                fcb 0xBD,0x95,0x9A,0xBD,0xB1,0x56,0xBD,0xB6,0x54,0x20,0x08,0xBD,0x9B,0x98,0x7E,0x9B
+                fcb 0xBE,0x35,0x14,0xD7,0xD8,0x27,0xFA,0x9F,0xD9,0x10,0x27,0x00,0xEA,0x0D,0xD8,0x27
+                fcb 0xF0,0xBD,0x9B,0x98,0x81,0x3B,0x27,0xF5,0x81,0x27,0x27,0xF1,0x81,0x4E,0x26,0x04
+                fcb 0x03,0xD5,0x20,0xE9,0x81,0x42,0x26,0x04,0x03,0xD6,0x20,0xE1,0x81,0x58,0x10,0x27
+                fcb 0x00,0x96,0x81,0x4D,0x10,0x27,0x01,0x2A,0x34,0x02,0xC6,0x01,0x0D,0xD8,0x27,0x11
+                fcb 0xBD,0x9B,0x98,0xBD,0xB3,0xA2,0x34,0x01,0xBD,0x9B,0xE2,0x35,0x01,0x24,0x02,0x8D
+                fcb 0xAA,0x35,0x02,0x81,0x43,0x27,0x28,0x81,0x41,0x27,0x2E,0x81,0x53,0x27,0x32,0x81
+                fcb 0x55,0x27,0x5C,0x81,0x44,0x27,0x55,0x81,0x4C,0x27,0x4C,0x81,0x52,0x27,0x43,0x80
+                fcb 0x45,0x27,0x2F,0x4A,0x27,0x27,0x4A,0x27,0x32,0x4A,0x27,0x1D,0x7E,0xB4,0x4A,0xBD
+                fcb 0x95,0x5D,0xD7,0xB2,0xBD,0x95,0x9A,0x20,0x84,0xC1,0x04,0x24,0xEF,0xD7,0xE8,0x20
+                fcb 0xF6,0xC1,0x3F,0x24,0xE7,0xD7,0xE9,0x20,0xEE,0x4F,0x8D,0x58,0x21,0x4F,0x1F,0x01
+                fcb 0x20,0x59,0x4F,0x1F,0x01,0x8D,0x4D,0x1E,0x01,0x20,0x50,0x4F,0x1F,0x01,0x8D,0x44
+                fcb 0x20,0x49,0x4F,0x9E,0x8A,0x20,0x44,0x4F,0x8D,0x3A,0x20,0xF7,0x4F,0x20,0x03,0x4F
+                fcb 0x8D,0x32,0x9E,0x8A,0x1E,0x10,0x20,0x33,0xBD,0x9C,0x1B,0xC6,0x02,0xBD,0xAC,0x33
+                fcb 0xD6,0xD8,0x9E,0xD9,0x34,0x14,0x7E,0x9C,0xC6,0xD6,0xE9,0x27,0x1B,0x4F,0x1E,0x01
+                fcb 0xA7,0xE2,0x2A,0x02,0x8D,0x0D,0xBD,0x9F,0xB5,0x1F,0x30,0x44,0x56,0x44,0x56,0x6D
+                fcb 0xE0,0x2A,0x04,0x40,0x50,0x82,0x00,0x39,0x1F,0x10,0x39,0x34,0x06,0x8D,0xDA,0x35
+                fcb 0x10,0x34,0x06,0x8D,0xD4,0x35,0x10,0x10,0x9E,0xE8,0x34,0x20,0x6D,0xE4,0x27,0x08
+                fcb 0x1E,0x10,0x8D,0xDF,0x6A,0xE4,0x20,0xF4,0x35,0x20,0xDE,0x8A,0xD3,0xC7,0x2B,0x02
+                fcb 0x1F,0x03,0x1F,0x10,0x9E,0x8A,0xD3,0xC9,0x2B,0x02,0x1F,0x01,0x11,0x83,0x01,0x00
+                fcb 0x25,0x03,0xCE,0x00,0xFF,0x8C,0x00,0xC0,0x25,0x03,0x8E,0x00,0xBF,0xDC,0xC7,0xDD
+                fcb 0xBD,0xDC,0xC9,0xDD,0xBF,0x9F,0xC5,0xDF,0xC3,0x0D,0xD5,0x26,0x04,0x9F,0xC9,0xDF
+                fcb 0xC7,0xBD,0x94,0x20,0x0D,0xD6,0x26,0x03,0xBD,0x94,0xA1,0x0F,0xD5,0x0F,0xD6,0x7E
+                fcb 0x9C,0xDD,0xBD,0x9B,0x98,0x34,0x02,0xBD,0x9E,0x5E,0x34,0x06,0xBD,0x9B,0x98,0x81
+                fcb 0x2C,0x10,0x26,0xFF,0x07,0xBD,0x9E,0x5B,0x1F,0x01,0x35,0x40,0x35,0x02,0x81,0x2B
+                fcb 0x27,0x04,0x81,0x2D,0x26,0xA6,0x1F,0x30,0x7E,0x9D,0xCB,0xBD,0x9B,0x98,0x81,0x2B
+                fcb 0x27,0x07,0x81,0x2D,0x27,0x04,0xBD,0x9B,0xE2,0x4F,0x34,0x02,0xBD,0x9C,0xCB,0x35
+                fcb 0x02,0x4D,0x27,0x04,0x4F,0x50,0x82,0x00,0x39,0x00,0x00,0x00,0x01,0xFE,0xC5,0x19
+                fcb 0x19,0xFB,0x16,0x31,0xF2,0xF4,0xFB,0x4A,0x51,0xEC,0x84,0x61,0xF9,0xE1,0xC7,0x78
+                fcb 0xAE,0xD4,0xDC,0x8E,0x3B,0xC5,0xE5,0xA2,0x69,0xB5,0x06,0xB5,0x06,0x81,0x40,0x26
+                fcb 0x02,0x9D,0x9F,0xBD,0x95,0x22,0xBD,0x93,0xB2,0xBD,0x93,0x1D,0xAE,0xC4,0x9F,0xCB
+                fcb 0xAE,0x42,0x9F,0xCD,0xBD,0xB2,0x6D,0xBD,0xB7,0x3D,0xCE,0x00,0xCF,0xAF,0xC4,0xBD
+                fcb 0x93,0x20,0x86,0x01,0x97,0xC2,0xBD,0x95,0x81,0x8E,0x01,0x00,0x9D,0xA5,0x27,0x0F
+                fcb 0xBD,0xB2,0x6D,0xBD,0xB1,0x41,0x96,0x4F,0x8B,0x08,0x97,0x4F,0xBD,0xB7,0x40,0x96
+                fcb 0xB6,0x85,0x02,0x27,0x04,0x1F,0x10,0x30,0x8B,0x9F,0xD1,0xC6,0x01,0xD7,0xC2,0xD7
+                fcb 0xD8,0xBD,0x9F,0xE2,0x34,0x06,0xBD,0x9F,0xE2,0xDD,0xD9,0x35,0x06,0x34,0x06,0x9E
+; The actual implementation of the DOS command follows; presumably this is here because it was
+; implemented by a different group of people given that it doesn't call DSKCON directly and uses
+; the DSKCON variables pointer as well.
+DOSCOM          swi3                            ; do a software interrupt for some reason (why?)
+                clr TMPLOC                      ; reset sector counter
+                ldd #DOSBUF                     ; initialize load address for boot track
+                pshs d                          ; save buffer address
+LDF09           ldx DSKVAR                      ; point to DSKCON variables
+                inc TMPLOC                      ; bump sector counter
+                lda TMPLOC                      ; get current sector
+                cmpa #SECMAX                    ; loaded whole track?
+                bhi LDF36                       ; brif so
+                sta 3,x                         ; tell DSKCON the sector number
+                ldd #0x0200                     ; read code and drive 0
+                sta ,x                          ; set operation code (should be std to set drive)
+                lda #34                         ; track 34
+                sta 2,x                         ; tell DSKCON
+                puls a,b                        ; get buffer pointer
+                std 4,x                         ; tell DSKCON
+                adda #1                         ; bump buffer pointer by one sector
+                pshs a,b                        ; save it again
+                jsr [DCNVEC]                    ; call DSKCON to read a sector
+                tst 6,x                         ; error?
+                beq LDF09                       ; brif not - read another
+                puls a,b                        ; clean stack
+                ldb #2*20                       ; I/O error code
+                jmp LAC46                       ; raise error
+LDF36           puls a,b                        ; clear up stack
+                ldd DOSBUF                      ; get start of loaded track
+                cmpd #'O*256+'S                 ; is it the "OS" tag?
+                lbeq DOSBUF+2                   ; brif so - transfer control to it
+                clr DOSBUF                      ; clear first two bytes (why?)
+                clr DOSBUF+1
+                jmp BAWMST                      ; do a warm start
+DOSINI          ldd #0x3b3b                     ; set up SWI3 and SWI2 with RTIs (kind of pointless)
+                std SW3VEC
+                std SW3VEC+2
+                std SW2VEC+1
+                rts
+; The remainder to the end is unused garbage bytes
+                fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x10,0x93,0xD3,0x25,0x02,0xDC,0xD3,0xDD
+                fcb 0xC3,0xA6,0xE4,0x81,0x04,0x25,0x0A,0xDC,0xCD,0x93,0xC5,0x24,0x11,0x4F,0x5F,0x20
+                fcb 0x0D,0xDC,0xCD,0xD3,0xC5,0x25,0x05,0x10,0x93,0xD5,0x25,0x02,0xDC,0xD5,0xDD,0xC5
+                fcb 0x0D,0xD8,0x26,0x02,0x8D,0x50,0x35,0x06,0x04,0xD8,0x25,0x05,0x10,0x93,0xD9,0x27
+                fcb 0x0C,0x5C,0xC1,0x08,0x26,0x04,0x4C,0x5F,0x84,0x07,0x7E,0x9E,0xFD,0x39,0x9E,0xCF
+                fcb 0xEC,0xC4,0x27,0x07,0x83,0x00,0x01,0x8D,0x03,0x1F,0x21,0x39,0x34,0x76,0x6F,0x64
+                fcb 0xA6,0x63,0x3D,0xED,0x66,0xEC,0x61,0x3D,0xEB,0x66,0x89,0x00,0xED,0x65,0xE6,0xE4
+                fcb 0xA6,0x63,0x3D,0xE3,0x65,0xED,0x65,0x24,0x02,0x6C,0x64,0xA6,0xE4,0xE6,0x62,0x3D
+                fcb 0xE3,0x64,0xED,0x64,0x35,0xF6,0x7E,0x94,0xA1,0x5F,0x9D,0xA5,0x27,0x11,0xBD,0xB2
+                fcb 0x6D,0xBD,0xB1,0x41,0x96,0x4F,0x8B,0x06,0x97,0x4F,0xBD,0xB7,0x0E,0xC4,0x3F,0x1F
+                fcb 0x98,0xC4,0x07,0x44,0x44,0x44,0x39
+                else
+; From here to the end of the ROM is unused garbage bytes
+	fcb 0x00,0x00,0x00
+	fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+	fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+	fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+	fcb 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+	fcb 0xa7,0xfc,0x8f,0xec,0x94,0xbc,0x8c,0xf5
+	fcb 0xbc,0xf8,0xd1,0xfa,0xfd,0xfd,0xac,0xe5
+	fcb 0xec,0xf8,0x8a,0xea,0xad,0xec,0xb9,0xff
+	fcb 0xbc,0xfd,0xcc,0xed,0x8c,0xe5,0x9c,0xf4
+	fcb 0xa2,0xa6,0xe8,0xfc,0xae,0xe5,0x94,0xec
+	fcb 0xbe,0xee,0x8c,0xed,0xea,0xe5,0xed,0x7c
+	fcb 0xbe,0xfc,0x8e,0xed,0xfe,0xec,0x9c,0xac
+	fcb 0xdc,0xfd,0xfb,0xf5,0xad,0xfd,0xaf,0xe9
+	fcb 0xa0,0x30,0x24,0x8a,0x14,0x84,0x2c,0xc4
+	fcb 0x24,0x08,0xe0,0x21,0x20,0x80,0x28,0x00
+	fcb 0x20,0x88,0xa4,0xa0,0xa4,0x80,0xac,0x11
+	fcb 0x30,0x90,0x24,0xd4,0x01,0xa1,0xa0,0x84
+	fcb 0x64,0x80,0x34,0x04,0x34,0x80,0x20,0x21
+	fcb 0xa1,0x81,0xa4,0x80,0x20,0x90,0x88,0xc0
+	fcb 0x00,0x9a,0xa0,0xa0,0xe0,0x80,0xb6,0xa4
+	fcb 0x20,0xa2,0x20,0x98,0x20,0x88,0x7c,0xae
+	fcb 0xbd,0xee,0xee,0xfe,0xf1,0xec,0xad,0xbc
+	fcb 0xed,0xec,0xdd,0xf9,0xec,0x75,0xb5,0xbd
+	fcb 0xef,0xfd,0xa9,0xe4,0x96,0xfc,0x94,0xe4
+	fcb 0xae,0xad,0xda,0xb4,0xac,0x7c,0xc3,0xec
+	fcb 0xbd,0xfc,0xae,0xfd,0xee,0xfd,0x85,0xf4
+	fcb 0xad,0xef,0x76,0xfc,0xd6,0x6e,0xef,0xed
+	fcb 0xf6,0xbd,0xed,0xfe,0x58,0xed,0xf7,0xfd
+	fcb 0x85,0xec,0xfc,0xe8,0xf2,0xe4,0xbf,0xa8
+	fcb 0x30,0x80,0xa0,0x05,0xa4,0x20,0xb0,0x80
+	fcb 0x20,0x84,0x04,0x80,0x30,0x8e,0xe0,0xa4
+	fcb 0xb0,0x02,0x04,0x80,0x61,0x84,0x20,0x00
+	fcb 0xa0,0x80,0x20,0x88,0x24,0x94,0x24,0xa4
+	fcb 0x80,0x04,0x00,0x84,0x24,0x84,0x28,0x9c
+	fcb 0x44,0x28,0xa0,0x80,0x80,0x90,0x30,0x80
+	fcb 0xe8,0x80,0xa4,0x88,0x30,0x94,0x20,0x80
+	fcb 0x00,0x8c,0x68,0xac,0xa4,0x84,0x30,0x06
+	fcb 0x86,0xe4,0xbc,0xfc,0xae,0xec,0x87,0xbd
+	fcb 0x9c,0xfd,0xec,0xbc,0xfd,0xb5,0xa9,0xed
+	fcb 0xa7,0xac,0x8b,0x7c,0xa5,0xfc,0xcc,0xbc
+	fcb 0xaa,0xb6,0xc9,0xfc,0xa5,0xfc,0x47,0xfc
+	fcb 0xdd,0x6d,0x84,0xfe,0xac,0xee,0x20,0xf4
+	fcb 0xc5,0xff,0xf4,0xee,0xf7,0xf4,0xaa,0xfc
+	fcb 0xef,0xff,0x9c,0xfd,0xee,0xe4,0xaf,0xfc
+	fcb 0xbe,0xbc,0xdf,0xa5,0xeb,0xec,0xee,0xa4
+	fcb 0x34,0x86,0xac,0x84,0xa4,0x21,0x90,0x88
+	fcb 0xa0,0xa0,0x24,0xc0,0xe0,0x80,0x70,0xe5
+	fcb 0x3c,0xa5,0xa1,0x8c,0x34,0xa4,0xe4,0x84
+	fcb 0x24,0x80,0xf8,0x81,0xa0,0x8d,0xec,0x4a
+	fcb 0x2c,0xe2,0xa4,0x93,0x20,0x88,0xb0,0xc0
+	fcb 0x34,0x10,0x20,0x91,0xa4,0x84,0xa4,0xae
+	fcb 0x0c,0x92,0xb0,0xcd,0xb0,0xaa,0x74,0xe8
+	fcb 0xa0,0x12,0xb9,0x85,0x21,0xf5,0xe0,0x8e
+	fcb 0x9e,0xbd,0x81,0xf5,0xcf,0xe4,0xcc,0x66
+	fcb 0xa7,0xad,0x98,0xbd,0xbc,0xbc,0x88,0xbc
+	fcb 0x8e,0xed,0xa4,0xa8,0xad,0x88,0xee,0xfe
+	fcb 0xcd,0xfc,0xac,0xfd,0x8c,0xfc,0x9a,0xf5
+	fcb 0xb4,0xe4,0x8e,0xfc,0xfe,0xe4,0xcc,0xac
+	fcb 0x9d,0xfc,0x97,0xe4,0x8b,0xec,0xea,0xec
+	fcb 0xdb,0xec,0xdf,0xec,0xac,0xe4,0xae,0xfc
+	fcb 0xd4,0xf4,0xcd,0xec,0xb4,0xec,0xef,0xee
+	fcb 0xb2,0x24,0x28,0x20,0xac,0xd0,0x24,0x1c
+	fcb 0x30,0x81,0xac,0x84,0x80,0x01,0xa4,0xa4
+	fcb 0x70,0x88,0xa4,0xc4,0xa4,0x84,0x24,0x60
+	fcb 0x08,0x04,0xa0,0x88,0x20,0x98,0x64,0xa8
+	fcb 0x24,0x10,0xd4,0x90,0xa0,0x81,0x30,0xec
+	fcb 0xac,0x09,0x64,0xe0,0x60,0x18,0x30,0xb0
+	fcb 0x24,0x80,0x6c,0x88,0xa4,0x8c,0xa4,0x8c
+	fcb 0xa8,0x10,0x21,0xa8,0x68,0x84,0xa8,0xa0
+	fcb 0x8d,0xe5,0xa4,0x66,0x98,0xfd,0x87,0xfc
+	fcb 0xde,0xac,0x9c,0xf4,0x8c,0xf5,0xb5,0xf5
+	fcb 0xb6,0xf5,0xa9,0xf8,0xaf,0xed,0xe6,0xe5
+	fcb 0xb8,0xf1,0xb1,0xfc,0xfc,0xe9,0x8c,0xec
+	fcb 0x86,0xf9,0xb5,0xf7,0xcd,0xbc,0x84,0xe6
+	fcb 0x8c,0xfc,0x81,0xe4,0xbc,0xe4,0x4f,0xfc
+	fcb 0x8c,0xfc,0xae,0xe7,0xbd,0xfc,0xdc,0xfc
+	fcb 0xf4,0xe8,0x9f,0xec,0xea,0xfc,0xef,0x6c
+	fcb 0x20,0x82,0xa4,0x40,0xa8,0x8c,0xac,0x08
+	fcb 0x60,0x82,0xa1,0x95,0xe0,0x30,0x60,0x80
+	fcb 0x64,0x48,0x20,0x04,0x20,0x84,0xa4,0x82
+	fcb 0xa0,0x04,0x20,0x94,0x44,0xa0,0xe0,0x80
+	fcb 0x04,0xc8,0x2c,0x82,0x24,0x04,0x30,0xb8
+	fcb 0x24,0x00,0x20,0xa0,0xa4,0x82,0xa0,0x80
+	fcb 0x84,0x81,0x2c,0x84,0x20,0x80,0x24,0x8c
+	fcb 0x80,0x80,0x24,0x02,0x64,0xa8,0x24,0x88
+	fcb 0xed,0xbd,0xd1,0xff,0xb4,0xe4,0xaa,0xec
+	fcb 0x80,0xf1,0x8c,0xed,0x89,0xac,0xb6,0xfc
+	fcb 0x6e,0xfd,0xae,0xed,0x89,0xec,0xb6,0xec
+	fcb 0xae,0xfd,0xee,0xf0,0x9f,0x7e,0x9f,0xfe
+	fcb 0xd9,0xec,0xae,0xed,0xc6,0xec,0xfe,0x7d
+	fcb 0xbc,0xfc,0xb9,0xac,0xda,0xfc,0xa5,0xbd
+	fcb 0xcc,0xfd,0xad,0xe6,0xae,0xf4,0xcd,0xf4
+	fcb 0xf2,0xed,0x84,0x78,0xcc,0xec,0xab,0x74
+	fcb 0xa4,0x94,0x20,0x84,0x20,0x00,0xa0,0x00
+	fcb 0xa4,0x05,0x28,0x0c,0x24,0x04,0x24,0x00
+	fcb 0xa0,0x84,0x80,0x80,0x18,0x80,0x24,0x0c
+	fcb 0xe0,0x88,0x04,0x8a,0x2c,0x88,0x0c,0x84
+	fcb 0x00,0x80,0xe0,0x04,0x20,0xa1,0x20,0x85
+	fcb 0x20,0x90,0x80,0x9c,0x24,0xc0,0xe0,0x8d
+	fcb 0xa0,0x80,0x20,0x82,0xa0,0xa2,0x20,0x40
+	fcb 0x80,0x82,0x10,0xb8,0x00,0x84,0x60,0x92
+	fcb 0xdf,0xef,0xd1,0xec,0xa4,0xec,0xc9,0xfd
+	fcb 0xe6,0xad,0xc6,0xe5,0xd4,0xfd,0x9a,0xed
+	fcb 0xae,0xe4,0xac,0xbc,0x9f,0xec,0x8a,0xed
+	fcb 0x0f,0xe5,0x8f,0xec,0xd7,0xe4,0xac,0xec
+	fcb 0xce,0xef,0x9e,0xf4,0xd7,0xe4,0xcf,0xf5
+	fcb 0xce,0xf4,0xe6,0x6c,0x81,0xec,0x9b,0xee
+	fcb 0x9f,0x7c,0xbc,0xf7,0xcc,0x6d,0xfe,0xef
+	fcb 0x8e,0x6e,0xef,0xbd,0xbe,0xbd,0x8f,0xe4
+	fcb 0xa0,0x04,0x20,0xe0,0xb4,0x82,0xb4,0x82
+	fcb 0x20,0x8c,0xb0,0x90,0xb0,0x90,0xb8,0x84
+	fcb 0x24,0x90,0x6a,0x86,0x28,0x84,0xa0,0xa8
+	fcb 0x24,0xcf,0xb8,0x88,0xa0,0xa0,0xb1,0x81
+	fcb 0x10,0xb6,0xe0,0x98,0xc8,0xb4,0x34,0xaf
+	fcb 0x34,0x00,0xb0,0x82,0x20,0x90,0xe4,0xac
+	fcb 0x28,0x84,0x84,0x88,0x24,0xac,0xac,0xa4
+	fcb 0x25,0x98,0x20,0xa0,0x20,0x80,0x32,0x00
+	fcb 0xae,0xec,0x8d,0xbd,0x9f,0xf7,0xff,0xa1
+	fcb 0xca,0xbe,0x8d,0x7c,0x8e,0x74,0xef,0xec
+	fcb 0xd4,0xf5,0x9e,0xb8,0x8e,0x35,0xc6,0xe4
+	fcb 0x90,0xed,0xed,0xfc,0x8c,0x25,0xbe,0xa4
+	fcb 0xfc,0x6c,0x89,0xee,0xec,0xad,0xae,0x78
+	fcb 0xee,0xec,0xad,0xed,0xad,0xec,0xbc,0xbd
+	fcb 0x2e,0x76,0xae,0xec,0x8e,0xbd,0xef,0xfd
+	fcb 0xac,0xec,0xef,0xb5,0xbe,0xa4,0xbf,0xe8
+	fcb 0x04,0x00,0x24,0x08,0x04,0x84,0x24,0x80
+	fcb 0x28,0x82,0x60,0x04,0x24,0x94,0x28,0x00
+	fcb 0x2c,0x84,0x20,0x80,0xb5,0x86,0x30,0x04
+	fcb 0x23,0x84,0xa0,0x80,0xa0,0x06,0x24,0xad
+	fcb 0xa4,0x80,0xa6,0x86,0x80,0x00,0xe0,0x80
+	fcb 0x66,0x90,0x20,0x8c,0x00,0x8c,0x04,0x82
+	fcb 0xa4,0x46,0x00,0x01,0x20,0x98,0xa0,0x88
+	fcb 0x20,0x2a,0x24,0xe0,0x00,0x08,0x64,0x02
+	fcb 0x8d,0xa5,0xb5,0xe5,0xad,0xf7,0xcd,0xf4
+	fcb 0xa8,0x29,0xbc,0x64,0xf8,0xec,0xad,0xae
+	fcb 0xa8,0xf5,0x8c,0xa7,0xe7,0xe5,0xa9,0xf4
+	fcb 0xf4,0xfd,0x94,0xed,0x5c,0xe4,0xc0,0xbe
+	fcb 0x8c,0xfd,0xcd,0xa4,0x94,0xff,0xa5,0xec
+	fcb 0xfc,0xe5,0xac,0xe4,0xae,0xbd,0x9d,0xbd
+	fcb 0xa8,0xec,0x84,0x68,0xc9,0xad,0x8e,0xac
+	fcb 0xea,0xed,0x8f,0xec,0xbf,0xaf,0xf7,0xed
+	fcb 0x24,0x91,0xa0,0x04,0xb4,0x04,0x82,0x90
+	fcb 0xac,0x08,0xb0,0xa0,0xc0,0x08,0x34,0xa0
+	fcb 0x65,0x88,0x73,0x80,0x20,0x80,0x2c,0x04
+	fcb 0x20,0x84,0x21,0x26,0x20,0x94,0x00,0x20
+	fcb 0xa4,0x96,0xa4,0x80,0xb0,0x84,0x24,0x82
+	fcb 0x25,0x86,0xa0,0x00,0x7c,0x30,0xa2,0x25
+	fcb 0x24,0x9e,0xa0,0x88,0x20,0x80,0x20,0x00
+	fcb 0x20,0xa9,0x20,0xa2,0xc0,0xb2,0xa1,0x0e
+	fcb 0xae,0xec,0xa8,0xee,0xac,0xf8,0xfa,0xb4
+	fcb 0xa4,0xfe,0xfc,0xf4,0x1c,0xed,0xae,0xf4
+	fcb 0xd7,0xf8,0xfd,0xed,0x8e,0xfe,0xdc,0xe8
+	fcb 0xfe,0xed,0xfc,0xed,0x9f,0xfc,0x9c,0xed
+	fcb 0xb0,0xe7,0xbe,0xfe,0x84,0xe4,0xa7,0xfe
+	fcb 0xad,0xe4,0xbc,0x64,0x8d,0xbf,0xaf,0xfd
+	fcb 0xaa,0x2c,0xcd,0xed,0x8f,0xe4,0xfc,0xbd
+	fcb 0xbf,0xef,0xe5,0xed,0xbf,0xfe,0xe5,0xfd
+	fcb 0x84,0x82,0xa4,0x83,0xa4,0x08,0xa0,0x80
+	fcb 0x00,0x84,0x30,0x86,0x08,0x20,0xb0,0x90
+	fcb 0x14,0xb4,0xa0,0x80,0x20,0x90,0xa4,0x88
+	fcb 0xec,0x80,0xa4,0x84,0xa0,0x84,0x28,0x80
+	fcb 0xb4,0x81,0xf0,0xa0,0xe4,0x80,0x00,0x84
+	fcb 0x34,0xb1,0xe4,0x80,0x24,0x5d,0x20,0xd2
+	fcb 0x44,0x83,0xb0,0x88,0x20,0x14,0x30,0xbc
+	fcb 0x20,0xa0,0xc4,0x9d,0x68,0x00,0xa0,0x20
+	fcb 0xcf,0xec,0xaa,0x66,0xb8,0x75,0x9e,0xfc
+	fcb 0xfe,0xb4,0xbc,0xff,0xac,0xfd,0x9a,0xbc
+	fcb 0xba,0xec,0x8e,0xf4,0xec,0xfc,0x96,0xfd
+	fcb 0xd2,0xea,0x84,0xfc,0xae,0xe4,0xe5,0xfd
+	fcb 0xbd,0xec,0xdc,0xac,0xa5,0xb0,0xcf,0xec
+	fcb 0x7a,0xb5,0xe4,0xea,0xef,0xec,0xa4,0xfe
+	fcb 0xe5,0xff,0xf8,0xbc,0x86,0xe4,0xff,0xe5
+	fcb 0xaf,0x6c,0xee,0xec,0xee,0x6c,0x2a,0x6c
+	fcb 0x28,0xa0,0x64,0x84,0xb4,0x92,0x04,0x94
+	fcb 0x80,0x00,0xb8,0x0c,0x20,0x88,0xa0,0x84
+	fcb 0xa0,0x40,0xb0,0x00,0xa0,0x84,0xa0,0xca
+	fcb 0x00,0x14,0x24,0xc0,0xa0,0x64,0x24,0x88
+	fcb 0x00,0x18,0xed,0x88,0x28,0x80,0xa1,0x80
+	fcb 0x00,0x85,0x20,0x80,0xa4,0x34,0x00,0x04
+	fcb 0x24,0xa4,0xac,0x8c,0x34,0x88,0x2c,0x04
+	fcb 0x24,0x84,0x60,0x88,0xa0,0xa0,0xa0,0x9c
+	fcb 0xb9,0xf4,0x97,0xec,0x68,0xad,0xe4,0xf0
+	fcb 0xf4,0xec,0xcb,0xfc,0xa8,0xf5,0xfd,0x3e
+	fcb 0xfc,0xee,0x9d,0xec,0x5e,0xfc,0x9c,0xf6
+	fcb 0x80,0xed,0xa2,0xe4,0xad,0xb6,0xbf,0xf4
+	fcb 0xed,0xfe,0xb3,0xfc,0xdc,0xb5,0xb3,0xed
+	fcb 0xef,0xfc,0xbf,0xfc,0xbc,0xfe,0xea,0xf4
+	fcb 0xc5,0xe4,0x89,0xfc,0x7c,0xbd,0xde,0xfd
+	fcb 0x87,0xe4,0x9e,0xec,0xaf,0xe4,0xfe,0xe4
+	fcb 0x34,0xc6,0x30,0x26,0x24,0x80,0x20,0x1c
+	fcb 0xb4,0x04,0xb4,0x28,0x24,0x98,0x20,0x00
+	fcb 0xa4,0xa4,0xa0,0x80,0x21,0x48,0xb9,0x24
+	fcb 0x20,0x80,0x28,0x00,0x20,0x80,0x84,0x1e
+	fcb 0x60,0xbc,0x28,0x88,0xac,0x74,0xe0,0x04
+	fcb 0x24,0xa6,0x00,0x20,0x70,0x85,0xa0,0x89
+	fcb 0x30,0x0b,0xa0,0x80,0x20,0x10,0xa0,0x14
+	fcb 0x24,0x04,0x20,0x82,0xa0,0x80,0x35,0xa0
+	fcb 0xee,0xbc,0xbe,0xfd,0xbe,0xb9,0x89,0xe4
+	fcb 0xfd,0x3d,0x13,0xe4,0x9e,0xec,0x8d,0xec
+	fcb 0xde,0xfc,0x8e,0xe5,0x8f,0xf4,0xbe,0xff
+	fcb 0xe6,0xe6,0x8c,0xe6,0xcd,0xae,0xee,0xed
+	fcb 0xfe,0xec,0xdc,0xec,0x8e,0xfc,0x96,0xfd
+	fcb 0xa6,0xfc,0xce,0xcd,0xbe,0xfe,0xee,0xfc
+	fcb 0x9e,0xf4,0xee,0x6e,0xcf,0xed,0xee,0xe0
+	fcb 0xfc,0xee,0xae,0xa0,0xfd,0xed,0xa6,0x6c
+	fcb 0xa8,0x04,0x20,0x00,0x30,0x80,0xa0,0x90
+	fcb 0x20,0x80,0x60,0x00,0x20,0x82,0x90,0x40
+	fcb 0x24,0x10,0x04,0x00,0x84,0x00,0x24,0x18
+	fcb 0xe0,0x00,0x00,0x02,0x20,0xb4,0x24,0x00
+	fcb 0x22,0x80,0x04,0x04,0xa0,0x80,0x84,0x0a
+	fcb 0x28,0x14,0xa0,0x80,0x00,0x86,0x40,0x86
+	fcb 0x20,0x90,0x10,0x30,0x84,0x84,0x00,0x00
+	fcb 0x74,0x80,0x30,0x00,0x20,0x08,0x20,0x80
+	fcb 0xfb,0xfd,0xc9,0xe6,0x91,0xfd,0xc8,0xee
+	fcb 0xb4,0x7c,0xbe,0xec,0x89,0xec,0xbd,0xfc
+	fcb 0xa5,0xfd,0xd9,0xec,0x8a,0xfd,0xae,0xec
+	fcb 0xad,0xfc,0xae,0xec,0x8d,0xec,0x8f,0xf4
+	fcb 0xbf,0x6d,0xac,0xbd,0xea,0xed,0xaf,0xac
+	fcb 0xfd,0xfc,0xea,0xfd,0xf0,0xf9,0xb3,0xee
+	fcb 0x8e,0xe4,0xfd,0xec,0xff,0xe0,0x8e,0xe4
+	fcb 0xfd,0xad,0xdc,0x6c,0xa0,0xe4,0x8e,0xe4
+	fcb 0x28,0x00,0xb4,0x00,0x22,0x00,0xb4,0x00
+	fcb 0x6c,0x00,0xa4,0x1b,0xb2,0x9c,0x20,0x84
+	fcb 0x24,0xc4,0x24,0xa8,0xa0,0x80,0x64,0x88
+	fcb 0x80,0xac,0x30,0x85,0x20,0x9c,0x74,0xf2
+	fcb 0x88,0x88,0x38,0x80,0x2c,0xa0,0x20,0x04
+	fcb 0xb8,0x80,0x24,0x90,0xa8,0xf8,0xbc,0x88
+	fcb 0x20,0x20,0xa0,0xe0,0x6c,0x80,0x00,0xe8
+	fcb 0x20,0x80,0x24,0xc0,0x23,0x9c,0x24,0x82
+	fcb 0xb5,0xe0,0xa4,0xed,0x8e,0xe4,0xa9,0xfc
+	fcb 0xf8,0xee,0xce,0xfc,0x89,0xe4,0x98,0xf5
+	fcb 0xa1,0xec,0xa1,0xe0,0xb8,0xec,0xd0,0xfc
+	fcb 0xcf,0xf9,0xae,0xec,0x8a,0xfd,0x6b,0x6e
+	fcb 0x94,0xa8,0xb8,0xe4,0xce,0xa6,0x8c,0xf4
+	fcb 0xee,0xbd,0x8d,0xec,0xed,0xf4,0xcf,0x6c
+	fcb 0x99,0x6c,0xc8,0xf9,0xf9,0xa5,0xb6,0x79
+	fcb 0x8c,0xc1,0xe4,0xf5,0xaa,0x24,0xf7,0x64
+	fcb 0x24,0xa8,0xa4,0x80,0xa0,0x96,0x20,0x09
+	fcb 0x20,0x18,0xa8,0x08,0xb0,0xc0,0x7c,0xcd
+	fcb 0x24,0xdc,0x20,0x98,0x64,0x84,0xe0,0x82
+	fcb 0x34,0xa0,0xea,0x88,0x60,0xc4,0x70,0xe8
+	fcb 0x30,0x06,0xe5,0x1c,0x20,0x84,0x20,0x9c
+	fcb 0xa0,0x80,0xa0,0x1c,0xa8,0x80,0x88,0x22
+	fcb 0x24,0x80,0x24,0xb0,0xe4,0x14,0xe4,0x80
+	fcb 0xe0,0x86,0x00,0xd6,0x8c,0x80,0xb8,0xab
+	fcb 0xaf,0xa2,0x84,0xe8,0x86,0x2f,0x8a,0xf5
+	fcb 0xd4,0xff,0x86,0xef,0x8e,0xf4,0xc8,0x6c
+	fcb 0xf5,0xf4,0x4c,0xf4,0xe8,0x74,0x04,0xee
+	fcb 0xee,0xe0,0x26,0x2c,0x9f,0xec,0x90,0xe5
+	fcb 0xbc,0xe5,0xf8,0xe0,0xfb,0xf4,0xb4,0xed
+	fcb 0x4e,0xe4,0xe6,0xec,0x8c,0xe4,0xbf,0xed
+	fcb 0x9f,0xe0,0xcc,0x7c,0xbf,0xed,0x9d,0xed
+	fcb 0xad,0xf8,0xaf,0x64,0xef,0xed,0xed,0xe4
+	fcb 0xa0,0x8c,0x20,0x95,0x30,0x38,0xa0,0x84
+	fcb 0x64,0x80,0xe0,0x76,0x2c,0x20,0xb4,0x04
+	fcb 0x3f,0xb1,0xa4,0x24,0x24,0x80,0x24,0xa9
+	fcb 0x31,0x97,0xac,0x28,0x64,0x50,0xa0,0x04
+	fcb 0x38,0x80,0xb4,0x8e,0x20,0xcc,0xbc,0x38
+	fcb 0x64,0x8c,0xa0,0x90,0xe4,0xa0,0x64,0x99
+	fcb 0x64,0xaf,0x24,0xe5,0x60,0x80,0xa4,0x3c
+	fcb 0x2c,0x8e,0xb4,0xbc,0xa4,0xcc,0x24,0xcc
+                endc