NEW AUTO 3,1 .LIST OFF .OP 65C02 .OR $2000 .TF lib/libblkdev *-------------------------------------- .INB INC/MACROS.I .INB INC/A2OSX.I .INB INC/MLI.I .INB INC/IO.D2.I *-------------------------------------- TRACK16.LEN .EQ $19F8 (6648) bytes *-------------------------------------- TRACK16.GAP1 .EQ 64+8 *Address field = D5AA96 + 4x2 + DEAAEB = 14 TRACK16.GAP2 .EQ 6 *Data field = D5AAAD + 342 + CS + DEAAEB = 349 TRACK16.GAP3 .EQ 42 *-------------------------------------- TRACK9.LEN .EQ $19F8 (6648) bytes *-------------------------------------- TRACK9.GAP1 .EQ 51 *Address field = D5AA96 + 4x2 + DEAAEB = 14 TRACK9.GAP2 .EQ 6 *Data field = D5AAAD + 342 + 342 + CS + DEAAEB = 691 TRACK9.GAP3 .EQ 42 *-------------------------------------- Status.PrvDrvOff .EQ $80 Waiting old drive stop spinning Status.DrvOn .EQ $81 Waiting target drive spin Status.seek .EQ $82 target drive seeking *-------------------------------------- ZPPtr1 .EQ ZPLIB ZPPtr2 .EQ ZPLIB+2 ZPPtr3 .EQ ZPLIB+4 ZPPtr4 .EQ ZPLIB+6 *-------------------------------------- * File Header (16 Bytes) *-------------------------------------- CS.START cld jmp (.1,x) .DA #$61 6502,Level 1 (65c02) .DA #1 BIN Layout Version 1 .DA 0 .DA CS.END-CS.START .DA 0 .DA 0 .DA 0 *-------------------------------------- * Relocation Table *-------------------------------------- .1 .DA LIB.LOAD .DA LIB.UNLOAD .DA GetProDOSCatSize .DA BuildProDOSCat .DA D2MoveHead .DA D2TrkRead16s .DA D2TrkWrite16s .DA D2TrkReadNIB .DA D2TrkWriteNIB L.TrkWriter .DA TrkWriter L.ProDOS.Boot .DA ProDOS.Boot .DA 0 *-------------------------------------- LIB.LOAD LIB.UNLOAD clc rts */-------------------------------------- * # GetProDOSCatSize * Compute space needed for ProDOS Catalog * ## C * int getprodoscatsize (short int options, short int catsize, int devsize ); * ## ASM * **In:** * PUSHW = DevSize (in 512b blocks) * PUSHB = Catalog Size (in blocks) * PUSHB = Options * ## RETURN VALUE * X=BlockCount (max 22) * Y,A=BufSize (max $4400) *\-------------------------------------- GetProDOSCatSize >PULLB VolDirHdr.Options >PULLB VolDirHdr.CatSize >PULLW VolDirHdr.TB GetProDOSCatSize.I lda VolDirHdr.TB Get DevSizeLo clc for now, no partial bitmap blk to add tay DevSize is xxxxxxxx00000000 ? beq .1 sec .1 lda VolDirHdr.TB+1 Get DevSizeHI bit #$0f DevSize is xxxx000000000000 ? beq .2 sec .2 php lsr lsr lsr lsr plp inc +1 (ProDOS) inc +1 (SOS) adc VolDirHdr.CatSize +x (VolDir) tax X = Total blocks needed for header (used) asl A = Total pages needed to build catalog. rts */-------------------------------------- * # BuildProDOSCat * **In:** * PUSHW = DevSize (in 512b blocks) * PUSHB = Catalog Size (in blocks) * PUSHB = Options * PUSHW = VolName (PSTR) * PUSHW = DstBuf (Zero filled) * Blk0 : ProDOS.BootBlk * Blk1 : SOS.BootBlk * Blk2...n : Volume Directory * Blkn+1.. : Volume Bitmap (4096/Blk) * max devSize = 65535 -> max 16 Bitmap Blk * absolute MAX DstBuf size= * 7 for Disk II(280blk),3.5(1600),3.5HD(2880) * 22 for 32mb Hardisk... *\-------------------------------------- BuildProDOSCat >PULLW ZPPtr1 DstBuf >PULLW ZPPtr2 VolName >PULLB VolDirHdr.Options >PULLB VolDirHdr.CatSize inc inc sta VolDirHdr.BMPtr >PULLW VolDirHdr.TB ldx #3 .1 lda DATELO,x sta VolDirHdr.CT,x dex bpl .1 * Blk 0 : ProDOS Boot Code >LDYA L.ProDOS.Boot >STYA ZPPtr3 ldy #0 ldx #2 2 pages .2 lda (ZPPtr3),y sta (ZPPtr1),y iny bne .2 inc ZPPtr3+1 inc ZPPtr1+1 dex bne .2 * Blk 1 : (SOS boot code) inc ZPPtr1+1 inc ZPPtr1+1 * Blk 2 : First Directory Block * ldy #0 stz VolDirHdr.Prev * stz VolDirHdr.Prev+1 always 0 lda #3 next block ldx VolDirHdr.CatSize dex bne .30 txa .30 sta VolDirHdr.next * stz VolDirHdr.next+1 * stz VolDirHdr.VER * stz VolDirHdr.MVER .3 lda (ZPPtr2),y beq .39 iny cmp #'a' bcc .38 cmp #'z'+1 bcs .38 eor #$20 pha lda LC.BitMap,y cpy #8 bcs .31 tsb VolDirHdr.VER bra .32 .31 tsb VolDirHdr.MVER .32 lda #$80 tsb VolDirHdr.VER pla .38 sta VolDirHdr.Name,y cpy #15 bne .3 .39 tya * and #$0f make sure 15 bytes max ora #$F0 Volume Directory Header sta VolDirHdr.Name ldy #VolDirHdr.size-1 .4 lda VolDirHdr,y sta (ZPPtr1),y dey bpl .4 * Blk 3...n : additional Directory Blocks lda #3 Actual Block ID ldy #2 next blk ptr .41 inc ZPPtr1+1 inc ZPPtr1+1 Next Block dex bmi .40 dec Previous Blk ID sta (ZPPtr1) inc inc next blk id phx plx bne .42 txa .42 sta (ZPPtr1),y bra .41 * BitMap Blocks : 0=Used 1=free .40 jsr GetProDOSCatSize.I X=blk used for boot/dir/bitmap lda VolDirHdr.TB eor #$ff sta Count lda VolDirHdr.TB+1 eor #$ff sta Count+1 ldy #0 .50 lda #%10000000 .5 dex bmi .8 inc Count bne .6 inc Count+1 .6 lsr bne .5 iny bne .50 .7 lda #%10000000 .8 inc Count bne .81 inc Count+1 bne .81 clc rts .81 pha eor (ZPPtr1),y sta (ZPPtr1),y pla lsr bne .8 iny bne .7 inc ZPPtr1+1 bra .7 */-------------------------------------- *\-------------------------------------- D2MoveHead >PULLB MoveTo >PULLB MoveFrom >PULLB DrvSlt jsr CheckDiskII bcs .9 .9 rts */-------------------------------------- *\-------------------------------------- D2TrkRead16s */-------------------------------------- * # D2TrkWrite16s * Write a track (16 sectors) * **In:** * PUSHB = DSSS0000 * PUSHB = TrackNum * 4 : 0->136+ * PUSHW = Ptr to 16*256 buffer * ## RETURN VALUE * CC : success * CS : A = Error * A=0, currently starting/seeking... *\-------------------------------------- D2TrkWrite16s >PULLW ZPPtr1 >PULLB TrkNum >PULLB DrvSlt >LDYAI TRACK16.LEN+1 >SYSCALL2 getmem bcs .9 >STYA ZPPtr2 stx TrkBuf lda #254 sta VolNum stz SectNum ldy #TRACK16.GAP1 jsr PutSyncBytePtr2 .1 jsr PutAddrHeadPtr2 jsr HeaderCheckSum ldy #3 .2 lda Checksum,y jsr PutByte44Ptr2 dey bpl .2 jsr PutTailPtr2 ldy #TRACK16.GAP2 jsr PutSyncBytePtr2 jsr PutDataHeadPtr2 jsr PutData jsr PutTailPtr2 ldy #TRACK16.GAP3 jsr PutSyncBytePtr2 inc ZPPtr1+1 inc SectNum lda SectNum cmp #16 bne .1 lda TrkBuf >SYSCALL2 FreeMem clc .9 rts */-------------------------------------- *\-------------------------------------- D2TrkReadNIB */-------------------------------------- * # D2TrkWriteNIB * Write a track (NIBBLE) * **In:** * PUSHW = Ptr to NIBBLE buffer (0 ended) * PUSHB = TrackNum * 4 : 0->140+ * PUSHB = DSSS0000 * ## RETURN VALUE * CC : success * CS : A = Error * A=0, currently starting/seeking... *\-------------------------------------- D2TrkWriteNIB >PULLB DrvSlt >PULLB TrkNum >PULLW ZPPtr1 lda Status Lib is busy....? beq .10 lda DrvSlt cmp DrvSltInUse resume previous access ? .10 lda DEVNUM last drive accessed by ProDOS and #$F0 only DSSS pha jsr CheckDiskII was it a DISK II ? bcs .1 no, no need to check if spinning pla pha jsr DrvSpinCheck bcc .1 not spinning....continue pla sta IO.D2.DrvOff,x lda #Status.PrvDrvOff jmp SetStatusAndExit .1 pla cmp DrvSlt * beq lda DrvSlt jsr DrvTrkSelect bcs .9 ldy #TrkWriter.Size * clc .9 rts *-------------------------------------- SetStatusAndExit sta Status ldy DrvSlt sty DrvSltInUse clc rts *-------------------------------------- * A=DSSS0000 * Y=target Track Number * 4 *-------------------------------------- DrvTrkSelect jsr DrvSelect clc rts *-------------------------------------- * A=DSSS0000 *-------------------------------------- CheckDiskII and #$70 only 0SSS lsr lsr lsr ora #$C0 make Cn sta .2+2 ldx #3 4 bytes to check .1 ldy DiskII.OFS,x .2 lda $C000,y Self Modified cmp DiskII.SIG,x bne .9 dex bpl .1 clc all bytes match, Disk II rts .9 lda #MLI.E.NODEV sec rts *-------------------------------------- * A=DSSS0000 *-------------------------------------- DrvSpinCheck jsr DrvSelect ldy #0 lda IO.D2.RData,x .1 cmp IO.D2.RData,x bne .8 spinning dey bne .1 clc CC:not spinning rts .8 sec rts *-------------------------------------- * A=DSSS0000 *-------------------------------------- DrvSelect pha and #$70 tax pla asl adc #IO.D2.DrvSel1 sta .1+1 .1 lda IO.D2.DrvSel1,x Drv 1/2 select lda IO.D2.ReadMode,x Make sure readmode rts *-------------------------------------- PutSyncBytePtr2 lda #$7f .1 jsr PutBytePtr2 dey bne .1 rts *-------------------------------------- PutAddrHeadPtr2 ldy #2 .1 lda ADDR.Head,y jsr PutBytePtr2 dey bpl .1 rts *-------------------------------------- PutDataHeadPtr2 ldy #2 .1 lda DATA.Head,y jsr PutBytePtr2 dey bpl .1 rts *-------------------------------------- PutTailPtr2 ldy #2 .1 lda TAIL,y jsr PutBytePtr2 dey bpl .1 rts *-------------------------------------- HeaderCheckSum lda VolNum eor TrkNum eor SectNum sta Checksum rts *-------------------------------------- PutData stz Checksum lda ZPPtr1 ldy ZPPtr1+1 clc adc #86 bcc .1 iny clc .1 sta ZPPtr3 sty ZPPtr3+1 adc #86 bcc .2 iny .2 sta ZPPtr4 sty ZPPtr4+1 ldy #85 .3 lda (ZPPtr1),y and #3 tax lda XRW.XX000000,x pha lda (ZPPtr3),y and #3 tax pla ora XRW.00XX0000,x pha lda (ZPPtr4),y and #3 tax pla ora XRW.0000XX00,x eor Checksum sta Checksum tax lda FC2Nib,x jsr PutBytePtr2 dey bpl .3 ldy #0 .4 lda (ZPPtr3),y and #$FC eor Checksum sta Checksum tax lda FC2Nib,x jsr PutBytePtr2 iny bne .4 ldx Checksum lda FC2Nib,x jsr PutBytePtr2 rts *-------------------------------------- PutByte44Ptr2 pha rol jsr .1 pla .1 ora #$AA *-------------------------------------- PutBytePtr2 sta (ZPPtr2) inc ZPPtr2 bne .8 inc ZPPtr2+1 .8 rts *-------------------------------------- *-------------------------------------- CS.END *-------------------------------------- * TrkWriter * X = Slot Cn * ZPPtr1 = Ptr To NibbleBuf *-------------------------------------- TrkWriter .PH $200 TrkWriter.Start lda IO.D2.ReadMode,x lda IO.D2.ReadProt,x bmi .9 Write protected php sei ldy #0 .1 lda (ZPPtr1),y (5) as NibbleBuf is page aligned, no page crossing beq .8 (2)(3 if Z) END OF TRACK * nobody will never try to write 00000000, right? cmp #$80 (2) if CC, it is a sync byte ora #$80 (2) make sure Bit7 high sta IO.D2.WriteMode,x (5) ora IO.D2.WShift,x (4) keep C unmodified iny (2) bne .2 (2)(3 if nz) inc ZPPtr1+1 (5) bcs .1 (2)(3 if cs) regular 32us byte * 32us Byte,next page : 5+2 (beq failed) +2+2+5+4+2+2 (bne failed) + 5 + 3 (bcs succeeded) = 32 nop (2) Sync 40us byte : add 8 cycles nop (2) nop (2) bra .1 (3) * 40us Byte,next page : 5+2 (beq failed) +2+2+5+4+2+2 (bne failed) + 5 + 2 (bcs failed) +2+2+2+3 = 40 .2 nop (2) nop (2) bcs .1 (2)(3 if cs) regular 32us byte * 32us Byte,same page : 5+2 (beq failed) +2+2+5+4+2+3 (bne succeeded) + 2 +2 + 3 (bcs succeeded) = 32 nop (2) Sync 40us byte : add 8 cycles nop (2) nop (2) bra .1 (3) * 40us Byte,same page : 5+2 (beq failed) +2+2+5+4+2+2 (bne failed) + 5 + 2 (bcs failed) +2+2+2+3 = 40 .8 pha (3) make sure 32us elapsed before switching to read mode (beq(3)+pha(3)=beq(2)+cmp(2)+ora(2)) lda IO.D2.ReadMode,x close write mode lda IO.D2.RData,x pla from pha (3) plp clc rts .9 lda #$2B Write Protected sec rts TrkWriter.Size .EQ *-TrkWriter.Start .EP *-------------------------------------- ADDR.Head .HS 96AAD5 DATA.Head .HS ADAAD5 TAIL .HS EBAADE *-------------------------------------- Nib2FC .HS 0004 .HS FFFF .HS 080C .HS FF .HS 101418 XRW.XX000000 .HS 008040C0FFFF used in fast prenib as lookup for 2-bit quantities. .HS 1C20 .HS FFFFFF .HS 24282C3034 .HS FFFF .HS 383C4044484C .HS FF .HS 5054585C606468 XRW.00XX0000 .HS 00201030 used in fast prenib. endmrks .HS DEAAEB table using 'unused' nibbles ($C4,$C5,$C6,$C7) .HS FFFFFFFF .HS 6C .HS FF .HS 707478 .HS FFFFFF .HS 7C .HS FFFF .HS 8084 .HS FF .HS 888C9094989CA0 XRW.0000XX00 .HS 0008040C used in fast prenib. .HS FF .HS A4A8AC .HS FF .HS B0B4B8BCC0C4C8 .HS FFFF .HS CCD0D4D8DCE0 .HS FF .HS E4E8ECF0F4F8FC *-------------------------------------- dnibl2 .HS 00 dnibl3 .HS 00 dnibl4 .HS 00 FC2Nib .HS 96 .HS 02000097 .HS 0100009A .HS 0300009B .HS 0002009D .HS 0202009E .HS 0102009F .HS 030200A6 .HS 000100A7 .HS 020100AB .HS 010100AC .HS 030100AD .HS 000300AE .HS 020300AF .HS 010300B2 .HS 030300B3 .HS 000002B4 .HS 020002B5 .HS 010002B6 .HS 030002B7 .HS 000202B9 .HS 020202BA .HS 010202BB .HS 030202BC .HS 000102BD .HS 020102BE .HS 010102BF .HS 030102CB .HS 000302CD .HS 020302CE .HS 010302CF .HS 030302D3 .HS 000001D6 .HS 020001D7 .HS 010001D9 .HS 030001DA .HS 000201DB .HS 020201DC .HS 010201DD .HS 030201DE .HS 000101DF .HS 020101E5 .HS 010101E6 .HS 030101E7 .HS 000301E9 .HS 020301EA .HS 010301EB .HS 030301EC .HS 000003ED .HS 020003EE .HS 010003EF .HS 030003F2 .HS 000203F3 .HS 020203F4 .HS 010203F5 .HS 030203F6 .HS 000103F7 .HS 020103F9 .HS 010103FA .HS 030103FB .HS 000303FC .HS 020303FD .HS 010303FE .HS 030303FF *-------------------------------------- LC.BitMap .HS 80402010080402018040201008040201 *-------------------------------------- ProDOS.Boot .HS 01.38.b0.03.4c.32.a1.86.43.c9.03.08.8a.29.70.4a .HS 4a.4a.4a.09.c0.85.49.a0.ff.84.48.28.c8.b1.48.d0 .HS 3a.b0.0e.a9.03.8d.00.08.e6.3d.a5.49.48.a9.5b.48 .HS 60.85.40.85.48.a0.63.b1.48.99.94.09.c8.c0.eb.d0 .HS f6.a2.06.bc.1d.09.bd.24.09.99.f2.09.bd.2b.09.9d .HS 7f.0a.ca.10.ee.a9.09.85.49.a9.86.a0.00.c9.f9.b0 .HS 2f.85.48.84.60.84.4a.84.4c.84.4e.84.47.c8.84.42 .HS c8.84.46.a9.0c.85.61.85.4b.20.12.09.b0.68.e6.61 .HS e6.61.e6.46.a5.46.c9.06.90.ef.ad.00.0c.0d.01.0c .HS d0.6d.a9.04.d0.02.a5.4a.18.6d.23.0c.a8.90.0d.e6 .HS 4b.a5.4b.4a.b0.06.c9.0a.f0.55.a0.04.84.4a.ad.02 .HS 09.29.0f.a8.b1.4a.d9.02.09.d0.db.88.10.f6.29.f0 .HS c9.20.d0.3b.a0.10.b1.4a.c9.ff.d0.33.c8.b1.4a.85 .HS 46.c8.b1.4a.85.47.a9.00.85.4a.a0.1e.84.4b.84.61 .HS c8.84.4d.20.12.09.b0.17.e6.61.e6.61.a4.4e.e6.4e .HS b1.4a.85.46.b1.4c.85.47.11.4a.d0.e7.4c.00.20.4c .HS 3f.09.26.50.52.4f.44.4f.53.20.20.20.20.20.20.20 .HS 20.20.a5.60.85.44.a5.61.85.45.6c.48.00.08.1e.24 .HS 3f.45.47.76.f4.d7.d1.b6.4b.b4.ac.a6.2b.18.60.4c .HS bc.09.a9.9f.48.a9.ff.48.a9.01.a2.00.4c.79.f4.20 .HS 58.fc.a0.1c.b9.50.09.99.ae.05.88.10.f7.4c.4d.09 .HS aa.aa.aa.a0.d5.ce.c1.c2.cc.c5.a0.d4.cf.a0.cc.cf .HS c1.c4.a0.d0.d2.cf.c4.cf.d3.a0.aa.aa.aa.a5.53.29 .HS 03.2a.05.2b.aa.bd.80.c0.a9.2c.a2.11.ca.d0.fd.e9 .HS 01.d0.f7.a6.2b.60.a5.46.29.07.c9.04.29.03.08.0a .HS 28.2a.85.3d.a5.47.4a.a5.46.6a.4a.4a.85.41.0a.85 .HS 51.a5.45.85.27.a6.2b.bd.89.c0.20.bc.09.e6.27.e6 .HS 3d.e6.3d.b0.03.20.bc.09.bc.88.c0.60.a5.40.0a.85 .HS 53.a9.00.85.54.a5.53.85.50.38.e5.51.f0.14.b0.04 .HS e6.53.90.02.c6.53.38.20.6d.09.a5.50.18.20.6f.09 .HS d0.e3.a0.7f.84.52.08.28.38.c6.52.f0.ce.18.08.88 .HS f0.f5.bd.8c.c0.10.fb.00.00.00.00.00.00.00.00.00 *-------------------------------------- * Block 2 : First DIR block *-------------------------------------- VolDirHdr VolDirHdr.Prev .BS 2 pointer to previous block VolDirHdr.Next .BS 2 pointer to next block VolDirHdr.Name .BS 16 .HS 00.00.00.00.00.00.00.00 VolDirHdr.CT .BS 4 Creation time VolDirHdr.VER .BS 1 VolDirHdr.MVER .BS 1 .HS C3.27.0D access/EL/EPB .DA 0 File Count=0 (only VDH) VolDirHdr.BMPtr .BS 2 bitmap pointer (Block 2..n are Volume directory) VolDirHdr.TB .BS 2 Total Blocks VolDirHdr.size .EQ *-VolDirHdr *-------------------------------------- VolDirHdr.Options .BS 1 VolDirHdr.CatSize .BS 1 *-------------------------------------- DiskII.OFS .HS 010305FF DiskII.SIG .HS 20000300 *-------------------------------------- DrvSlt .BS 1 TrkBuf .BS 1 MoveFrom .BS 1 MoveTo .BS 1 Checksum .BS 1 SectNum .BS 1 TrkNum .BS 1 VolNum .BS 1 *-------------------------------------- Status .BS 1 DrvSltInUse .BS 1 Count .BS 2 *-------------------------------------- MAN SAVE USR/SRC/LIB/LIBBLKDEV.S ASM