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/LIBBLKDEV.I
*--------------------------------------
* NIBBLE track len = $1A00 (6656) bytes
*--------------------------------------
GAP1			.EQ 48
GAP2			.EQ 6
GAP3			.EQ 27
*--------------------------------------
Status.PrvDrvOff	.EQ $80				Waiting old drive stop spinning
Status.DrvOn		.EQ $81				Waiting target drive spin
Status.seek			.EQ $82				target drive seeking
*--------------------------------------
D2Ph0Off		.EQ $C080
D2Ph0On			.EQ $C081
D2Ph1Off		.EQ $C082
D2Ph1On			.EQ $C083
D2Ph2Off		.EQ $C084
D2Ph2On			.EQ $C085
D2Ph3Off		.EQ $C086
D2Ph3On			.EQ $C087
D2DrvOff		.EQ $C088
D2DrvOn			.EQ $C089

D2DrvSel1		.EQ $C08A
D2DrvSel2		.EQ $C08B

D2WShift		.EQ $C08C				W
D2WLoad			.EQ $C08D				W
D2RData			.EQ $C08C				R
D2ReadProt		.EQ $C08D				R

D2ReadMode		.EQ $C08E				R
D2WriteMode		.EQ $C08F				W
*--------------------------------------
ZPPtr1			.EQ ZPLIB
ZPPtr2			.EQ ZPLIB+2
ZPPtr3			.EQ ZPLIB+4
*--------------------------------------
*			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 D2TrkR16s
				.DA D2TrkRNIB
				.DA D2TrkW16s
				.DA D2TrkWNIB
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
*/--------------------------------------
*\--------------------------------------
D2TrkRNIB
*/--------------------------------------
*\--------------------------------------
D2TrkR16s
*/--------------------------------------
* # D2TrkW16s
* Write a track (16 sectors)
* **In:**
*  PUSHW = Ptr to 16*256 buffer
*  PUSHB = TrackNum * 4	: 0->140+	
*  PUSHB = DSSS0000
* ## RETURN VALUE
*  CC : success
*  CS : A = Error
*       A=0, currently starting/seeking...
*\--------------------------------------
D2TrkW16s		>PULLB DrvSlt
				>PULLB TrkNum
				>PULLW ZPPtr1

				clc
				rts
*/--------------------------------------
* # D2TrkWNIB
* 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...
*\--------------------------------------
D2TrkWNIB		>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 D2DrvOff,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				sec
				rts
*--------------------------------------
* A=DSSS0000
*--------------------------------------
DrvSpinCheck	jsr DrvSelect
				ldy #0

				lda D2RData,x
.1				cmp D2RData,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 #D2DrvSel1
				sta .1+1
.1				lda D2DrvSel1,x			Drv 1/2 select

				lda D2ReadMode,x		Make sure readmode
				rts
*--------------------------------------
CS.END
*--------------------------------------
* TrkWriter
* X = Slot Cn
* ZPPtr1 = Ptr To NibbleBuf
*--------------------------------------
TrkWriter		.PH $200

TrkWriter.Start	lda D2ReadMode,x
				lda D2ReadProt,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 D2WriteMode,x		(5)
				ora D2WShift,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 D2ReadMode,x		close write mode
				lda D2RData,x
				pla						from pha (3) 
				plp
				clc
				rts

.9				lda #$2B				Write Protected
				sec
				rts

TrkWriter.Size	.EQ *-TrkWriter.Start
				.EP
*--------------------------------------
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
TrkNum			.BS 1
*--------------------------------------
Status			.BS 1
DrvSltInUse		.BS 1
Count			.BS 2
*--------------------------------------
MAN
SAVE USR/SRC/LIB/LIBBLKDEV.S
ASM
