NEW
  AUTO 3,1
*--------------------------------------
dcmd 			.EQ $42 				disk command (=1 for read)
unit 			.EQ $43 				(16*slot)+(128*(drive-1))
buff 			.EQ $44 				ram address
blok 			.EQ $46 				disk address
dent 			.EQ $48 				device call entry address
idxl 			.EQ $4a 				pointer to low page of index block
idxh 			.EQ $4c 				pointer to high page of index block
idxp 			.EQ $4e 				index byte pointer

iobuff 			.EQ $60
* the following are for disk ii only
dbuf 			.EQ $26
BB.Slotn0 		.EQ $2b
oddbits 		.EQ $3c
sector 			.EQ $3d

BB.RetryCnt		.EQ $40
BB.TargetTrk	.EQ $41

BB.CurrentQTrack	.EQ $50
BB.TargetQTrack	.EQ $51

BB.HdrPtr		.EQ $52

BB.Hdr			.EQ $54
BB.HdrTrk		.EQ $55
BB.HdrVol		.EQ $56
BB.Hdr96		.EQ $57

nbuf1 			.EQ $300
dnib 			.EQ $2d6

clrscrn 		.EQ $fc58
scrn 			.EQ $5b6
sosid 			.EQ $c00
entlen 			.EQ sosid+$23
kernel 			.EQ $2000
*--------------------------------------
				.PH $800
xboot 			.DA #1
				sec 					apple iii enters xboot 'ora $38'
*				bcs BB.AppleII			branch if not apple iii native mode
				bcc *
*--------------------------------------
*BB.AppleIII	lda #$9f 				make apple iii boot using block 1
*				pha 					the return address is $a000
*				lda #$ff
*				pha

*				inc
*				tax						ldx #0

*				inc 					lda #1 (read block 1)

*				jmp $f479
*--------------------------------------
BB.AppleII		stx unit 				save unit number
				cmp #$03 				for disk ii
				php 					save result, it may be irrelevant
				txa 					find out if disk ii
				and #$70 				strip drive # if any
				lsr
				lsr						get slot address
				lsr
				lsr
				ora #$c0
				sta dent+1
				ldy #$ff 				look at last byte
				sty dent

				plp 					restore carry (if disk ii & sect 0&2 read)

				iny 					make y=0
				lda (dent),y 			get device entry addr
				bne ndsk2 				branch if not disk ii (16 sector)

				bcs isdsk2 				branch if it is disk ii, but block 0 read

				lda #3 					make rom read only sector 2
				sta xboot 				to complete block 0
				inc sector 				was = 1

				lda dent+1 				do rts to re-enter rom
				pha
				lda #$5b
				pha
				rts 					go read sector 2 into $900
*--------------------------------------
isdsk2 			sta BB.HdrTrk			A=0, make sure previous track =0
				sta dent 				and dent points at beginning of slot

				ldy #$63 				move code from card to ram

mvboot 			lda (dent),y
				sta zzstart-$5e,y
				iny
				cpy #$eb 				have we moved enough?
				bne mvboot

				ldx #mods.cnt			now modify code to handle errors.

modboot 		ldy mods-1,x
				lda chgs-1,x
				sta zzstart,y

				cpx #8
				bcs .1

				lda endcode-1,x
				sta zzzend-1,x

.1				dex
				bne modboot

				lda #BB.Hdr
				sta BB.HdrPtr
				stx BB.HdrPtr+1			X=0

				lda /BB.ReadBlock 		reset device entry
				sta dent+1 				to point at disk ii routines.
				lda #BB.ReadBlock 		get low addr (must be <$80)
*--------------------------------------
ndsk2 			sta dent 				save low adr of device call entry.

				ldy #0

				sty iobuff				y=0
				sty idxl
				sty idxh 
				sty idxp
				sty blok+1

				iny						y=1
				sty dcmd 				set read command.

				iny						y=2
				sty blok 				to read directory blocks

				lda #$c 				2-5 at $c00
				sta iobuff+1
				sta idxl+1

rddir 			jsr goread 				call read block routine.
				bcs bterr2 				give up on error.

				inc iobuff+1
				inc iobuff+1
				inc blok
				lda blok 				have all directory blocks been read?
				cmp #6
				bcc rddir 				loop if not.
*--------------------------------------
				lda #4 					begin look-up with first entry past header.
				.HS 2C					BIT ABS
nxdent 			lda idxl

nxdent1 		clc
				adc entlen 				bump to next directory entry.
				tay 					save in y for now.
				bcc nxdent2 			branch if not a page cross.

				inc idxl+1
				lda idxl+1 				check for new block.
				lsr 					if even then new block.
				bcs nxdent2

				cmp #$a 				have all file names been compared?
				beq booterr				branch if no pro.kernel.

				ldy #4 					else, begin at block beginning.

nxdent2 		sty idxl

				ldy #6

lookpro 		lda (idxl),y 			look for matching name.
				cmp BB.ProDOS,y
				bne nxdent 				branch if no match.

				dey
				bpl lookpro

*				ldy #$10 				get file type & index block addr.
*				lda (idxl),y
*				cmp #S.FI.T.SYS			is it a system file?
*				bne booterr
*				iny

				ldy #$11

				lda (idxl),y
				sta blok
				iny
				lda (idxl),y
				sta blok+1

				lda #0 					now set up to read kernel.
				sta idxl

				ldy #$1e 				read index block at $1e00 and
				sty idxl+1 				kernel at $2000
				sty iobuff+1
				iny
				sty idxh+1
*--------------------------------------
rdkernl 		jsr goread 				read index block.
bterr2 			bcs booterr

				inc iobuff+1
				inc iobuff+1

				ldy idxp 				get index pointer
				inc idxp 				bump for next time.
				lda (idxl),y
				sta blok
				lda (idxh),y 			high disk addr.
				sta blok+1
				ora (idxl),y 			if both=0 then done.
				bne rdkernl 			branch if more to read.

				jmp kernel 				go execute kernel code.
*--------------------------------------
booterr			jsr clrscrn 			clear video
				ldy #BB.MSG.ERR.Len-1

.1	 			lda BB.MSG.ERR,y
				sta scrn,y
				dey
				bpl .1

				jmp $ff69
*--------------------------------------
goread 			lda iobuff
				sta buff
				lda iobuff+1
				sta buff+1
				jmp (dent)
*--------------------------------------
mods 			.DA #mod1,#mod2,#mod3,#mod4,#mod5,#mod6,#mod7,#mod8,#mod8+1,#mod9
mods.cnt		.EQ *-mods
chgs 			.DA #chg1,#chg2,#chg3,#chg4,#chg5,#chg6,#chg7,#$91,#BB.HdrPtr,#BB.HdrTrk

endcode 		ldx BB.Slotn0
				clc
				rts

				jmp BB.Seek
*--------------------------------------
BB.MSG.ERR		.AS -"BOOT ERROR"
BB.MSG.ERR.Len	.EQ *-BB.MSG.ERR
BB.ProDOS 		.DA	#$26				$20 = storage type + 6 = "PRODOS" len
				.AS "PRODOS"
*--------------------------------------
BB.ReadBlock	lda blok 				figure out track & sector.
				and #7 					strip track for now.
				cmp #4
				and #3
				php
				asl
				plp
				rol						now we have the first sector of block.
				sta sector

				lda blok+1 				get high block #
				lsr 					shift hi addr to carry.
				lda blok 				now figure track #
				ror
				lsr
				lsr
				sta BB.TargetTrk
*--------------------------------------
				lda buff+1
				sta dbuf+1

				ldx BB.Slotn0
				lda IO.D2.DrvOn,x

				jsr BB.Seek 			go read sector.

				inc dbuf+1 				bump address
				inc sector
				inc sector 				and sector #
				bcs .9	 				branch if error.

				jsr BB.Seek

.9	 			ldy IO.D2.DrvOff,x
				rts 					return error status in carry.
*--------------------------------------
BB.Wait100usecA	phx						(3)

.1				ldx #20					(2)

.2 				dex 					(2)
				bne .2					(3)

				dec						(2)
				bne .1					(3)
				
				plx						(4)

				rts						(6)
*--------------------------------------
BB.Trk2Qtrk		asl						x2
				sta .1+1

				bit BB.HdrVol
				bpl .1					x4
				bvs .1					> $C0 ? (VOL=254)
				
				lsr						x3

.1				adc #$ff				SELF MODIFIED

BB.Trk2Qtrk.RTS rts
*--------------------------------------
BB.Seek			lda BB.HdrTrk			get track we're on
				jsr BB.Trk2Qtrk
				sta BB.CurrentQTrack

				lda BB.TargetTrk
				jsr BB.Trk2Qtrk
				sta BB.TargetQTrack

				lda BB.CurrentQTrack
				cmp	BB.TargetQTrack
				beq BB.Read

				bit #1
				bne .1

				jsr .20					we are on 0/4 or 2/4 track
				bra .9					no wait, next operation will be phy/plx/Ph0On,y
				
.1				cmp	BB.TargetQTrack		we are on 1/4 or 3/4
				
				bcs .2					if CS, C > T, must move out
				
				inc						CC: C < T, ON next PH

				.HS B0					BCS

.2				dec						CS: C > T, ON prev PH

				sta BB.CurrentQTrack

				bra .6					Ph ON to go to 0/4 or 2/4, then wait
*--------------------------------------
.20				and #6
				ora BB.Slotn0
				tay
				lda IO.D2.Ph0On,y
				rts
*--------------------------------------
.3				bcs	.4					if CS, C > T, must move out

				inc						CC: C < T, ON next PH

				.HS B0					BCS

.4				dec						CS: C > T, ON prev PH

				sta BB.CurrentQTrack

				bit #1
				bne .5					we must go to 1/4 or 3/4

				lda IO.D2.Ph0Off,x		we must go to 0/4 or 2/4 : Off Prev Ph
				bra .8					go wait....
				
.5				phy						we must go on 1/4 or 3/4
				plx						Y already ON, -> X for Ph0Off,x
				
				bcs	.6					if CS, C > T, must move out

				inc						CC: C < T, ON next PH

.6				jsr .20					now X and Y on

.8				lda #IO.D2.SeekTimeB
				jsr BB.Wait100usecA		...wait...

.9				lda BB.CurrentQTrack
				cmp	BB.TargetQTrack
				bne .3

				lda #0
				jsr BB.Wait100usecA

				lda IO.D2.Ph0Off,y

				ldy BB.Slotn0
				lda IO.D2.DrvOn,y
				
				lda IO.D2.Ph0Off,x
				
				lda IO.D2.DrvOn,y				
*--------------------------------------
BB.Read 		ldx BB.Slotn0

				stz BB.RetryCnt
				php

tryread 		plp 					fix stack.

rdhead 			sec 					anticipate error.
				inc BB.RetryCnt			if = 0 then give up!
				beq BB.Trk2Qtrk.RTS		branch if can't fine/read sector.

				clc 					indicate reading header.

				ldy #0					Retry cnt waiting D5
				
rddata 			php 					carry set if reading sector.

rd0 			iny
				beq tryread
*--------------------------------------
* from zzstart to zzend code is moved from rom and modified to match this code...
*--------------------------------------
zzstart 		.EQ *

rd1 			lda IO.D2.RData,x		read a byte from the state machine.
				bpl rd1 				loop until ready.

				.DUMMY

rd1a 			eor #$d5 				mark 1?
mod1 			.EQ *-zzstart+1
				bne rd0 				branch if not.

chg1 			.EQ rd0-*
rd2 			lda IO.D2.RData,x
				bpl rd2

				cmp #$aa 				mark 2?
				bne rd1a
				nop 					waste a little time.

rd3 			lda IO.D2.RData,x
				bpl rd3

				cmp #$96 				header mark 3?
				beq rdhd1 				branch if it is.

				plp 					were we looking for data mark 3?
mod2 			.EQ *-zzstart+1
				bcc rdhead 				branch if not.

chg2 			.EQ rdhead-*
				eor #$ad 				data mark 3?
				beq rddt1 				go read data field if true...

mod3 			.EQ *-zzstart+1
rdhd0 			bne rdhead 				otherwise, start over.

chg3 			.EQ rdhead-*

rdhd1 			ldy #3 					read in trk,sect,&volume #.

mod8 			.EQ *-zzstart
rdhd2 			sta (BB.HdrPtr),y		save last result in .. , BB.HdrTrk , BB.HdrVol , ..

rdhd3 			lda IO.D2.RData,x
				bpl rdhd3

				rol
				sta oddbits 			save odd bits (7,5,3,1)

rdhd4 			lda IO.D2.RData,x
				bpl rdhd4

				and oddbits 			combine even and odd to form value.
				dey
				bne rdhd2 				read in next pair.

				plp
				cmp sector 				last byte formed is sector#

mod4 			.EQ *-zzstart+1
				bne rdhead 				branch if target sector not found.

chg4 			.EQ rdhead-*

mod9 			.EQ *-zzstart+1
				lda BB.HdrTrk			previous result is track #
				cmp BB.TargetTrk		is desired track found?

mod5 			.EQ *-zzstart+1
				bne goseek 				re-seek if mismatch.

chg5a 			.EQ *
mod6 			.EQ *-zzstart+1
				bcs rddata 				branch if proper track always.
chg6 			.EQ rddata-*
*--------------------------------------
rddt1 			ldy #$56 				read 2 bit groupings first.
rddt1a 			sty oddbits

rddt2 			ldy IO.D2.RData,x
				bpl rddt2

				eor dnib,y 				denibblize using table left from boot rom.
				ldy oddbits 			save in nbuf1
				dey
				sta nbuf1,y
				bne rddt1a 				loop until all 86 groups are read.

rddt3 			sty oddbits 			now count up for 6-bit groups.

rddt4 			ldy IO.D2.RData,x
				bpl rddt4

				eor dnib,y
				ldy oddbits 			save result to specified buffer.
				sta (dbuf),y
				iny
				bne rddt3 				loop for 256 bytes.

rdchk 			ldy IO.D2.RData,x 		now verify checksum...
				bpl rdchk

				eor dnib,y 				must be equal...
mod7 			.EQ *-zzstart+1
				bne rdhd0 				branch if error.

chg7 			.EQ rdhd0-*
				ldy #0 					make y=0

nxttwo 			ldx #$56 				now combine 2-bit group with 6 bit group

twobit 			dex 					all done with this group?
				bmi nxttwo 				branch if so.

				lda (dbuf),y
				lsr nbuf1,x
				rol
				lsr nbuf1,x
				rol
				sta (dbuf),y
				iny
				bne twobit
*--------------------------------------
zzzend 			ldx BB.Slotn0
				clc 					indicate good read.
				rts

chg5 			.EQ *-chg5a
goseek 			jmp BB.Seek
				.ED
*--------------------------------------
				.LIST ON
BB.End			.EQ *
BB.Free			.EQ $a00-*
				.BS BB.Free
				.LIST OFF
				.EP
*--------------------------------------
MAN
SAVE usr/src/lib/libblkdev.s.bb
LOAD usr/src/lib/libblkdev.s
ASM
