; Little Red Reader/Writer utility package by Craig Bruce, 31-Jan-1992 ; Written for C= Hacking Net-Magazine; for C-128, 1571, 1581 ; Upgraded for FD-2000/4000 High Density MS-DOS disks, 08-Mar-1994 ; Upgraded to clean up errors and add aborting, 16-May-1996 .org $5400 .obj "@0:lrr.bin" ;====jump table and parameters interface ==== jmp initPackage ;() jmp msDir ;( msDevice, msType ) : .AY=dirAddr, .X=direntCount jmp msRead ;( msDevice, msType, startCluster, lenML,.A=trans,.X=cbmLfn ) jmp msWrite ;( msDevice, msType, writeDirent, .A=trans, .X=cbmLfn ) jmp msFlush ;( msDevice, msType ) jmp msDelete ;( writeDirent ) jmp msFormat ;( msDevice, msType, .A=low/highDensity ) jmp msBytesFree ;( ) : .AYX=bytesFree jmp cbmCopy ;( .A=inLfn, .X=outLfn ) jmp cbmDirent ;( .A=lfn ) .byte $cb,134 ;identification (location pk+30) errno .buf 1 ;0=ok,1-15=msdos,16-19=internal,20-30=cbm msDevice .buf 1 msType .buf 1 ;$00=1571, $ff=1581 or FD-2000/4000 startCluster .buf 2 lenML .buf 2 ;length medium and low bytes writeDirent .buf 2 ;pointer to dirent cdirBlocks .buf 2 ;cbm dirent blocks cdirType .buf 1 ;cbm dirent filetype cdirFlen .buf 1 ;cbm dirent filename length cdirName .buf 16 ;cbm dirent filename ;====global declaraions==== kernelListen = $ffb1 kernelSecond = $ff93 kernelUnlsn = $ffae kernelAcptr = $ffa2 kernelCiout = $ffa8 kernelSpinp = $ff47 kernelChkin = $ffc6 kernelChkout = $ffc9 kernelClrchn = $ffcc kernelChrin = $ffcf kernelChrout = $ffd2 kernelGetin = $ffe4 st = $90 ciaClock = $dd00 ciaFlags = $dc0d ciaData = $dc0c clusterBlockCount .buf 1 ;1 or 2 fatBlocks .buf 1 ;up to 9 rootDirBlocks .buf 1 ;up to 14 rootDirEntries .buf 1 ;up to 224 totalSectors .buf 2 ;up to 2880 firstFileBlock .buf 1 firstRootDirBlock .buf 1 fileClusterCount .buf 2 lastFatEntry .buf 2 bufCylinder .buf 1 bufSide .buf 1 fatDirty .buf 1 dirDirty .buf 14 ;flag for each directory block formatParms .buf 1 sectorsPerTrack .byte 9 ;default, up to 18 .buf 4 sectorsPerCyl .byte 18 ;default, up to 36 ;====test routines==== msFormat = * lda #$0e sta $ff00 jsr mountDisk lda #0 ;cylinder ldx #0 ;side jsr readTrack lda #trackbuf sta 1024 sty 1025 rts ;====hardware level==== sendU0 = * ;( .A=burstCommandCode ) : .CS=err pha lda #0 sta st lda msDevice jsr kernelListen lda #$6f jsr kernelSecond lda #"u" jsr kernelCiout bit st bmi sendU0Error lda #"0" jsr kernelCiout pla jsr kernelCiout bit st bmi sendU0Error clc rts sendU0Error = * lda #25 ;device not present error sta errno sec rts toggleClock = * lda ciaClock eor #$10 sta ciaClock rts serialWait = * lda #$08 - bit ciaFlags beq - rts getBurstByte = * jsr serialWait ldx ciaData jsr toggleClock txa rts mountDisk = * ;() : .CS=err lda #%00011010 jsr sendU0 bcc + rts + jsr kernelUnlsn bit st bmi sendU0Error clc jsr kernelSpinp bit ciaFlags jsr toggleClock jsr getBurstByte and #$0f sta errno cmp #2 bcs mountExit ldy #0 - jsr getBurstByte sta formatParms,y iny cpy #6 bcc - lda sectorsPerTrack asl sta sectorsPerCyl ;** set interleave to 4 if 1571, don't bother for other drives bit msType bmi mountExit lda #%00001000 jsr sendU0 bcc + rts + lda #4 jsr kernelCiout jsr kernelUnlsn clc mountExit = * rts bufptr = 2 secnum = 4 readTrack = * ;( .A=cylinder, .X=side ) : trackbuf, .CS=err pha txa and #$01 asl asl asl asl bit msType bpl + eor #$10 + jsr sendU0 pla bcc + rts + jsr kernelCiout ;cylinder number lda #1 ;start sector number jsr kernelCiout lda sectorsPerTrack ;sector count jsr kernelCiout jsr kernelUnlsn sei clc jsr kernelSpinp bit ciaFlags jsr toggleClock lda #trackbuf sta bufptr+0 sty bufptr+1 lda #0 sta secnum - bit msType bmi + jsr get1571BufPtr + jsr readSector bcs trackExit inc secnum lda secnum cmp sectorsPerTrack bcc - jsr toggleClock clc trackExit = * cli rts get1571BufPtr = * lda #trackbuf adc bufptr1571,x sta bufptr+1 rts bufptr1571 = * .byte 0,8,16,6,14,4,12,2,10 readSector = * ;( bufptr ) : .CS=err jsr getBurstByte and #$0f sta errno cmp #2 bcc + rts + ldx #2 ldy #0 readByte = * lda #$08 - bit ciaFlags beq - lda ciaClock eor #$10 sta ciaClock lda ciaData sta (bufptr),y iny bne readByte inc bufptr+1 dex bne readByte clc rts oldClock = 5 writeSector = * ;( bufptr, .A=cylinder, .X=side, .Y=sector ) : .CS=err pha sty secnum txa and #$01 asl asl asl asl ora #$02 bit msType bpl + eor #$10 + jsr sendU0 pla bcc + rts + jsr kernelCiout ;track number lda secnum ;sector number jsr kernelCiout lda #1 ;sector count jsr kernelCiout jsr kernelUnlsn sei lda #$40 sta oldClock sec jsr kernelSpinp ;set for burst output sei bit ciaFlags ldx #2 ldy #0 writeByte = * lda ciaClock cmp ciaClock bne writeByte eor oldClock and #$40 beq writeByte lda (bufptr),y sta ciaData lda oldClock eor #$40 sta oldClock lda #8 - bit ciaFlags beq - iny bne writeByte inc bufptr+1 dex bne writeByte clc jsr kernelSpinp bit ciaFlags jsr toggleClock jsr serialWait ldx ciaData jsr toggleClock txa and #$0f sta errno cmp #2 cli rts ;====logical-sector level==== initPackage = * lda #$0e sta $ff00 lda #$ff sta bufCylinder sta bufSide ldx #13 - sta dirDirty,x dex bpl - sta fatDirty clc rts sectorSave = 5 readBlock = * ;( .A=cylinder,.X=side,.Y=sector ) : .AY=blkPtr,.CS=err cmp bufCylinder bne readBlockPhysical cpx bufSide bne readBlockPhysical dey tya asl clc adc #>trackbuf tay lda #clusterBuf stx 7 ldx clusterBlockCount jmp copyBlocks writeLogicalBlock = * ;( .AY=logicalBlockNumber, bufptr ) : .CS=err jsr convertLogicalBlockNum cmp bufCylinder bne + cpx bufSide bne + pha lda #$ff sta bufCylinder sta bufSide pla + jsr writeSector rts writeClusterSave .buf 2 writeCluster = * ;( .AY=clusterNumber, clusterBuf ) : .CS=err jsr convertClusterNum ldx #clusterBuf stx bufptr+1 sta writeClusterSave+0 sty writeClusterSave+1 jsr writeLogicalBlock bcc + rts + lda clusterBlockCount cmp #2 bcs + rts + lda writeClusterSave+0 ldy writeClusterSave+1 clc adc #1 bcc + iny + jsr writeLogicalBlock rts ;====MS-DOS format level==== bootBlock = 2 msDir = * ;( .A=forceMount ) : .AY=dirbuf, .X=dirEntries, .CS=err ldx #$0e stx $ff00 cmp #$d0 bne + jsr mountDisk bcc + rts ;** get parameters from boot sector + lda #0 ldy #0 jsr convertLogicalBlockNum jsr readBlock bcc + rts + sta bootBlock+0 sty bootBlock+1 ldy #13 ;get cluster size lda (bootBlock),y sta clusterBlockCount cmp #3 bcc + invalidParms = * lda #17 ;invalid disk parms error sta errno sec rts + ldy #16 ;check FAT replication count, must be 2 lda (bootBlock),y cmp #2 bne invalidParms ldy #22 ;get FAT size in sectors, max of 9 lda (bootBlock),y sta fatBlocks cmp #10 bcs invalidParms ldy #17 ;get directory size lda (bootBlock),y sta rootDirEntries cmp #225 bcs invalidParms lsr lsr lsr lsr sta rootDirBlocks ldy #19 ;get total sector count lda (bootBlock),y sta totalSectors+0 iny lda (bootBlock),y sta totalSectors+1 ldy #24 ;check sectors per track, must be 18 or fewer lda (bootBlock),y cmp #19 bcs invalidParms ldy #26 lda (bootBlock),y cmp #2 ;check number of sides, must be 2 bne invalidParms ldy #14 ;check number of boot sectors, must be 1 lda (bootBlock),y cmp #1 bne invalidParms ;** get derived parameters lda fatBlocks ;first root directory sector asl clc adc #1 sta firstRootDirBlock clc ;first file sector adc rootDirBlocks sta firstFileBlock lda totalSectors+0 ;number of file clusters ldy totalSectors+1 sec sbc firstFileBlock bcs + dey + sta fileClusterCount+0 sty fileClusterCount+1 lda clusterBlockCount cmp #2 bne + lsr fileClusterCount+1 ror fileClusterCount+0 + clc lda fileClusterCount+0 adc #2 sta lastFatEntry+0 lda fileClusterCount+1 adc #0 sta lastFatEntry+1 ;** load FAT lda #fatbuf sta 6 sty 7 lda #1 ldy #0 ldx fatBlocks jsr copyBlocks bcc + rts ;** load actual directory + lda #dirbuf sta 6 sty 7 lda firstRootDirBlock ldy #0 ldx rootDirBlocks jsr copyBlocks bcc + rts + lda #dirbuf ldx rootDirEntries clc rts entryAddr = 2 entryWork = 4 entryBits = 5 entryData0 = 6 entryData1 = 7 entryData2 = 8 locateFatEntry = * ;( .AY=fatEntryNumber ) : entryAddr, entryBits1 sta entryBits ;** divide by two sty entryAddr+1 lsr entryAddr+1 ror ;** times three sta entryWork ldx entryAddr+1 asl rol entryAddr+1 clc adc entryWork sta entryAddr txa adc entryAddr+1 sta entryAddr+1 ;** add base, get data clc lda entryAddr adc #fatbuf sta entryAddr+1 ldy #2 - lda (entryAddr),y sta entryData0,y dey bpl - rts getFatEntry = * ;( .AY=fatEntryNumber ) : .AY=fatEntryValue jsr locateFatEntry lda entryBits and #1 bne + ;** case 1: first 12-bit cluster lda entryData1 and #$0f tay lda entryData0 rts ;** case 2: second 12-bit cluster + lda entryData1 ldx #4 - lsr entryData2 ror dex bne - ldy entryData2 rts fatValue = 9 setFatEntry = * ;( .AY=fatEntryNumber, (fatValue) ) jsr locateFatEntry lda fatValue+1 and #$0f sta fatValue+1 lda entryBits and #1 bne + ;** case 1: first 12-bit cluster lda fatValue sta entryData0 lda entryData1 and #$f0 ora fatValue+1 sta entryData1 jmp setFatExit ;** case 2: second 12-bit cluster + ldx #4 - asl fatValue rol fatValue+1 dex bne - lda fatValue+1 sta entryData2 lda entryData1 and #$0f ora fatValue sta entryData1 setFatExit = * ldy #2 - lda entryData0,y sta (entryAddr),y dey bpl - sty fatDirty rts dirtyDirent = * ;( writeDirent ) sec lda writeDirent+0 sbc #dirbuf lsr and #$0f tax lda #$ff sta dirDirty,x rts delCluster = 14 msDelete = * ;( writeDirent ) ldy #$0e sty $ff00 lda writeDirent+0 ldy writeDirent+1 sta 2 sty 3 lda #$e5 ldy #0 sta (2),y ldy #26 lda (2),y sta delCluster+0 iny lda (2),y sta delCluster+1 - lda delCluster+1 cmp #12 ;cluster number high byte bcc + jmp dirtyDirent + tay lda delCluster jsr getFatEntry pha tya pha lda #0 sta fatValue+0 sta fatValue+1 lda delCluster+0 ldy delCluster+1 jsr setFatEntry pla sta delCluster+1 pla sta delCluster jmp - flushBlock = 14 flushCountdown = $60 flushRepeats = $61 flushDirIndex = $61 msFlush = * ;( msDevice, msType ) : .CS=error lda #$0e sta $ff00 lda fatDirty beq flushDirectory lda #0 sta fatDirty ;** flush fat lda #2 sta flushRepeats lda #1 sta flushBlock masterFlush = * lda fatBlocks sta flushCountdown lda #fatbuf sta bufptr sty bufptr+1 - lda flushBlock ldy #0 jsr writeLogicalBlock bcc + rts + inc flushBlock dec flushCountdown bne - dec flushRepeats bne masterFlush ;** flush directory flushDirectory = * lda firstRootDirBlock sta flushBlock lda rootDirBlocks sta flushCountdown lda #0 sta flushDirIndex lda #dirbuf sta bufptr+0 sty bufptr+1 - ldx flushDirIndex lda dirDirty,x beq + lda #0 sta dirDirty,x lda flushBlock ldy #0 jsr writeLogicalBlock dec bufptr+1 dec bufptr+1 + inc flushBlock inc flushDirIndex inc bufptr+1 inc bufptr+1 dec flushCountdown bne - clc rts bfFatEntry = 14 bfBlocks = $60 msBytesFree = * ;( ) : .AYX=fileBytesFree ldy #$0e sty $ff00 lda #2 ldy #0 sta bfFatEntry+0 sty bfFatEntry+1 sty bfBlocks+0 sty bfBlocks+1 - lda bfFatEntry+0 ldy bfFatEntry+1 jsr getFatEntry sty 2 ora 2 bne + inc bfBlocks+0 bne + inc bfBlocks+1 + inc bfFatEntry bne + inc bfFatEntry+1 + lda bfFatEntry+0 cmp lastFatEntry+0 lda bfFatEntry+1 sbc lastFatEntry+1 bcc - ldx clusterBlockCount - asl bfBlocks rol bfBlocks+1 dex bne - lda #0 ldy bfBlocks+0 ldx bfBlocks+1 rts ;====file-copy level==== transMode = 14 lfn = 15 cbmDataPtr = $60 cbmDataLen = $62 cluster = $64 copyFileCluster = * ;( cluster, lfn, transMode ) : .CS=err lda cluster+0 ldy cluster+1 jsr readCluster bcc + rts + lda #clusterBuf sta cbmDataPtr+0 sty cbmDataPtr+1 lda #0 sta cbmDataLen+0 lda clusterBlockCount asl sta cbmDataLen+1 ;**get next cluster lda cluster+0 ldy cluster+1 jsr getFatEntry sta cluster+0 sty cluster+1 cpy #12 ;cluster number high byte bcc copyFileClusterData lda lenML sta cbmDataLen lda #$01 ldx clusterBlockCount cpx #1 beq + lda #$03 + and lenML+1 bne + ldx lenML beq copyFileClusterData + sta cbmDataLen+1 copyFileClusterData = * jsr commieOut rts cbmDataLimit = $66 commieOut = * ;( cbmDataPtr, cbmDataLen ) : .CS=err ldx lfn bne + clc rts + jsr kernelChkout bcc commieOutMore commieError = * clc adc #20 sec sta errno rts commieOutMore = * lda #255 ldx cbmDataLen+1 bne + lda cbmDataLen + sta cbmDataLimit ldy #0 - lda (cbmDataPtr),y bit transMode bpl + tax lda transBuf,x beq commieNext + jsr kernelChrout commieNext = * iny cpy cbmDataLimit bne - clc lda cbmDataPtr adc cbmDataLimit sta cbmDataPtr bcc + inc cbmDataPtr+1 + sec lda cbmDataLen sbc cbmDataLimit sta cbmDataLen bcs + dec cbmDataLen+1 + lda cbmDataLen ora cbmDataLen+1 bne commieOutMore jsr kernelClrchn clc rts testAbort = * jsr kernelGetin bne + clc rts + cmp #"a" bne testAbort lda #16 ;abort error sta errno sec rts msRead = * ;( cluster, lenML, .A=transMode, .X=lfn ) : .CS=err ldy #$0e sty $ff00 sta transMode stx lfn lda startCluster+0 ldy startCluster+1 sta cluster+0 sty cluster+1 jmp + - jsr testAbort bcs ++ jsr copyFileCluster bcc + rts + lda cluster+1 cmp #12 ;cluster number high byte bcc - clc + rts inLfn = $50 generateLf = $51 cbmDataMax = $52 reachedEof = $54 prevSt = $55 commieInInit = * ;( .A=transMode, .X=inLfn ) sta transMode stx inLfn lda #0 sta generateLf sta reachedEof sta prevSt rts commieIn = * ;( cbmDataPtr++, cbmDataMax ) : cbmDataLen, .CS=err, .Z=eof lda #0 sta cbmDataLen sta cbmDataLen+1 ldx reachedEof beq + lda #0 clc rts + ldx inLfn jsr kernelChkin bcc commieInMore jmp commieError commieInMore = * lda #255 ldx cbmDataMax+1 bne + lda cbmDataMax + sta cbmDataLimit ldy #0 - jsr commieInByte bcc + rts + beq + sta (cbmDataPtr),y iny cpy cbmDataLimit bne - + sty cbmDataLimit clc lda cbmDataPtr adc cbmDataLimit sta cbmDataPtr bcc + inc cbmDataPtr+1 + clc lda cbmDataLen adc cbmDataLimit sta cbmDataLen bcc + inc cbmDataLen+1 + sec lda cbmDataMax sbc cbmDataLimit sta cbmDataMax bcs + dec cbmDataMax+1 + lda reachedEof bne + lda cbmDataMax ora cbmDataMax+1 bne commieInMore + jsr kernelClrchn lda cbmDataLen ora cbmDataLen+1 clc rts commieInByte = * ;( ) : .A=char, .CS=err, .Z=eof, reachedEof ;** check for already past eof lda reachedEof beq + brk ;** check for generated linefeed + lda generateLf beq + lda #0 sta generateLf lda #$0a clc rts ;** check for eof + lda prevSt and #$40 beq + lda #$ff sta reachedEof lda #0 clc rts ;** read actual character + jsr kernelChrin ldx st stx prevSt bcc + pha jsr kernelClrchn pla jmp commieError ;** translate if necessary + bit transMode bpl + tax lda transBufToAscii,x beq commieInByte cmp #$0d bne + sta generateLf ;** exit + ldx #$ff clc rts firstFreeFatEntry = $5a allocateFatEntry = * ;( ) : .AY=fatEntry, .CS=err - lda firstFreeFatEntry cmp lastFatEntry lda firstFreeFatEntry+1 sbc lastFatEntry+1 bcc + lda #19 ;disk full err sta errno rts + lda firstFreeFatEntry ldy firstFreeFatEntry+1 jsr getFatEntry sty 2 ora 2 bne + lda firstFreeFatEntry ldy firstFreeFatEntry+1 clc rts + inc firstFreeFatEntry bne - inc firstFreeFatEntry+1 jmp - msFileLength = $5c ;(3 bytes) msWriteCluster = * ; (*) : .CS=err ;** get a new cluster jsr allocateFatEntry bcc + rts ;** make previous fat entry point to new cluster + sta fatValue sty fatValue+1 lda cluster ora cluster+1 beq + lda cluster ldy cluster+1 ldx fatValue stx cluster ldx fatValue+1 stx cluster+1 jsr setFatEntry jmp msClusterNew + lda writeDirent ldy writeDirent+1 sta 2 sty 3 ldy #26 lda fatValue sta (2),y sta cluster iny lda fatValue+1 sta (2),y sta cluster+1 ;** make new fat entry point to null msClusterNew = * lda #$ff ldy #$0f sta fatValue sty fatValue+1 lda cluster ldy cluster+1 jsr setFatEntry ;** write new cluster data + lda cluster ldy cluster+1 jsr writeCluster bcc + rts ;** add cluster length to file length + clc lda msFileLength adc cbmDataLen sta msFileLength lda msFileLength+1 adc cbmDataLen+1 sta msFileLength+1 bcc + inc msFileLength+2 + clc rts msWrite = * ;( msDevice, msType, writeDirent, .A=trans, .X=cbmLfn ) :.CS=err ldy #$0e sty $ff00 ;** initialize jsr commieInInit lda #0 sta cluster sta cluster+1 sta firstFreeFatEntry+1 sta msFileLength sta msFileLength+1 sta msFileLength+2 lda #2 sta firstFreeFatEntry ;** copy cluster from cbm file - jsr testAbort bcc + rts + lda #clusterBuf sta cbmDataPtr sty cbmDataPtr+1 lda clusterBlockCount asl tay lda #0 sta cbmDataMax sty cbmDataMax+1 jsr commieIn bcc + rts + beq + jsr msWriteCluster bcc - rts ;** wrap up after writing - set file length, dirty flag, exit. + lda writeDirent ldy writeDirent+1 sta 2 sty 3 ldx #0 ldy #28 - lda msFileLength,x sta (2),y iny inx cpx #3 bcc - jsr dirtyDirent clc rts ;===== commodore file level ===== cbmCopyTrans .buf 1 cbmCopy = * ;( .A=inLfn, .X=outLfn, .Y=outAscToCbmTranslationFlag ) sty cbmCopyTrans ldy #$0e sty $ff00 stx lfn tax lda #0 jsr commieInInit - jsr testAbort bcs + lda #clusterBuf sta cbmDataPtr+0 sty cbmDataPtr+1 lda #<1024 ldy #>1024 sta cbmDataMax+0 sty cbmDataMax+1 jsr commieIn bcs + beq + lda #clusterBuf sta cbmDataPtr+0 sty cbmDataPtr+1 lda cbmCopyTrans sta transMode jsr commieOut lda #0 sta transMode bcs + jmp - + rts cbmDirent = * ;( .A=lfn ) ldy #$0e sty $ff00 tax jsr kernelChkin bcc ++ cdirErr = * + lda #0 sta cdirFlen sta cdirBlocks sta cdirBlocks+1 rts ;** get block count + jsr cdirGetch jsr cdirGetch jsr cdirGetch sta cdirBlocks jsr cdirGetch sta cdirBlocks+1 ;** look for filename lda #0 sta cdirFlen - jsr cdirGetch cmp #34 beq + cmp #"b" bne - jsr kernelClrchn rts ;** get filename + ldy #0 - jsr cdirGetch cmp #34 beq + sta cdirName,y iny bne - + sty cdirFlen - jsr cdirGetch cmp #" " beq - sta cdirType - jsr cdirGetch cmp #0 bne - jsr kernelClrchn rts cdirGetch = * jsr kernelChrin bcs + bit st bvs + rts + pla pla jsr kernelClrchn jmp cdirErr ;===== data ===== transBuf = * ;0 1 2 3 4 5 6 7 8 9 a b c d e f .byte $00,$00,$00,$00,$00,$00,$00,$00,$14,$09,$0d,$00,$93,$00,$00,$00 ;0 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;1 .byte $20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$2a,$2b,$2c,$2d,$2e,$2f ;2 .byte $30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3a,$3b,$3c,$3d,$3e,$3f ;3 .byte $40,$c1,$c2,$c3,$c4,$c5,$c6,$c7,$c8,$c9,$ca,$cb,$cc,$cd,$ce,$cf ;4 .byte $d0,$d1,$d2,$d3,$d4,$d5,$d6,$d7,$d8,$d9,$da,$5b,$5c,$5d,$5e,$5f ;5 .byte $c0,$41,$42,$43,$44,$45,$46,$47,$48,$49,$4a,$4b,$4c,$4d,$4e,$4f ;6 .byte $50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$5a,$db,$dc,$dd,$de,$df ;7 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;8 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;9 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;a .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;b .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;c .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;d .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;e .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;f transBufToAscii = * ;0 1 2 3 4 5 6 7 8 9 a b c d e f .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$09,$00,$00,$00,$0d,$00,$00 ;0 .byte $00,$00,$00,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;1 .byte $20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$2a,$2b,$2c,$2d,$2e,$2f ;2 .byte $30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3a,$3b,$3c,$3d,$3e,$3f ;3 .byte $40,$61,$62,$63,$64,$65,$66,$67,$68,$69,$6a,$6b,$6c,$6d,$6e,$6f ;4 .byte $70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$7a,$5b,$5c,$5d,$5e,$5f ;5 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;6 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;7 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;8 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;9 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;a .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;b .byte $60,$41,$42,$43,$44,$45,$46,$47,$48,$49,$4a,$4b,$4c,$4d,$4e,$4f ;c .byte $50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$5a,$7b,$7c,$7d,$7e,$7f ;d .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;e .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7e ;f ;====bss storage (size=22,016 bytes)==== bss = * trackbuf = bss+0 ;(9216) ;room for 18 x 512-byte sectors clusterBuf = bss+9216 ;(1024) ;2 sectors fatbuf = bss+10240 ;(4608) ;9 sectors dirbuf = bss+14848 ;(7168) ;14 sectors = 224 dirents bssEnd = bss+22016