NEW
  AUTO 3,1
* disk ii driver. object code = xrw_0
* $5300-5A00 moved to language card bank 1 at $D000
*--------------------------------------
blockio			cld						$D8 to flag language card bank 1 (main)
				jsr rsetphse
				lda q7l,x				turn off write enable
				nop
				nop
				jsr docheck
				bcs L5334				branch if block # is out of range
				ldy #$05
L5310 			asl
				rol	ibtrk
				dey
				bne L5310
				asl
				bcc L531C
				ora #$10				adjust for upper 4 bits of track
L531C 			lsr
				lsr
				lsr
				lsr
				pha						save sector # across call
				jsr regrwts
				pla
				bcs L5330				if error
				inc buf+1
				adc #$02
				jsr regrwts				get 2nd half of block
				dec buf+1
L5330  			lda ibstat
				rts	
L5334 			lda #$27				i/o error
				sec
				rts

* read/write a track/sector

regrwts			ldy #$01				retry count
				sty seekcnt				only one recalibrate per call
				sta ibsect
				lda unitnum				get slot # for this operation
				and #$70
				sta A2L

* make sure other drives in other slots are stopped

				jsr chkprev

* now check if the motor is on, then start it

				jsr chkdrv
				php						save test results
				lda #$E8
				sta montimeh
				lda unitnum				determine drive 1 or 2.
				cmp iobpdn	   			same drive used before ?
				sta iobpdn	   			save it for next time.
				php		  				keep results of compare.
				asl 					get drive # into carry.
				lda motoron,x	  		turn on the drive.
				bcc L5362				branch if drive 1 selected.
				inx		  				select drive 2.

L5362 			lda drv0en,x
				plp		  				was it the same drive ?
				beq L5372				yes.
				plp		  				indicate drive off by setting z-flag.
				ldy #$07	   			150ms delay before stepping.
L536B  			jsr mswait
				dey
				bne L536B
				php						now zero flag set.
L5372  			lda A4L					make sure this command needs seeking.
				beq L537C				branch if status check.
				lda ibtrk				get destination track
				jsr myseek	   			and go to it.

* now at desired track. was the motor already on ?

L537C  			plp						was motor on ?
				bne L538E				if so, don't wait.

* motor was off, wait for it to speed up

L537F  			lda #$01				wait 100us for each count in montime
				jsr mswait
				lda montimeh
				bmi L537F				count up to 0000

* motor should be up to speed,
* if it looks stopped then the drive is not present

				jsr chkdrv				is drive present ?
				beq hndlerr	  			branch if no drive

* now check: if it is not the format disk command,
* locate the correct sector for this operation

L538E  			lda A4L					get command #
				beq L53FD				if 0 then status command
				lsr						set carry = 1 for read, 0 for write.
				bcs L5398				must prenibblize for write
				jsr prenib16
L5398  			ldy #$40				64 retries
				sty retrycnt
L539D  			ldx A2L					get slot #.
				jsr rdadr16				read next address field.
				bcc L53BE				branch if read ok.
L53A4  			dec retrycnt	   		one less chance.
				bpl L539D				branch to retry.
				lda #$27	   			anticipate a bad drive error.
				dec seekcnt	  			can only recalibrate once.
				bne hndlerr
				lda curtrk
				pha		  				save track
				asl
				adc #$10	   			pretend track is 8 > curtrk
				ldy #$40
				sty retrycnt	   		reset retries to 64 max.
				bne L53CC				always.

* have now read an address field. make sure this is
* the correct track, sector and volume.

L53BE  			ldy track				check track
				cpy curtrk
				beq L53D5				ok

* recalibrating from this track

				lda curtrk				preserve destination track
				pha
				tya
				asl 
L53CC  			jsr settrk
				pla
				jsr myseek
				bcc L539D				always taken, go recalibrate

* drive is on right track, check volume mismatch

L53D5  			lda sect				is this the right sector ?
				cmp ibsect
				bne L53A4	 			no, try another sector.
				lda A4L	 				read or write ?
				lsr	   					the carry will tell.
				bcc L53F4				branch if write
				jsr read16
				bcs L53A4				if bad read
				
L53E7  			lda #$00
				.HS	D0					bne branch never taken (skip 1 byte)
hndlerr			sec
				sta ibstat	   			error #
				ldx A2L					slot offset
				lda motoroff,x	 		turn off
				rts
L53F4  			jsr write16				write nibbles
statdne			bcc L53E7				if no errors.
				lda #$2B	   			disk write protected.
				bne hndlerr	  			always
L53FD  			ldx A2L
				lda q6h,x				test for write protected
				lda q7l,x
				rol		 				write protect-->carry-->bit 0=1
				lda q6l,x				keep in read mode
				jmp statdne
myseek			asl						assume two phase stepper
				sta track				save destination track * 2
				jsr alloff				turn all phases off to be sure.
				jsr drvindx				get index to previous track
				lda iobpdn,x	   		for current drive.
				sta curtrk	   			current position.
				lda track				where to go next.
				sta iobpdn,x
				jsr seek				move head there
alloff			ldy #$03	   			turn off all phases before returning.
L5427  			tya		  				(send phase in acc)
				jsr clrphase			carry clear, phases should be turned off
				dey
				bpl L5427
				lsr curtrk				divide back down
				clc
				rts

* fast seek subroutine
*
* on entry:
*	x = slot# times $10
*  acc = desired half-track (single phase)
* curtrk = current halftrack
*
* on exit:
*  a,y = uncertain
*	x = undisturbed
*  curtrk & trkn = final halftrack.
*	  prior = prior halftrack if seek was required.
*  montimel,h are incremented by the # of 100us quantums required by
*	   seek for motor on time overlap.
*
* variables used: curtrk, trkn, countn, prior, A2L, montimel, montimeh

seek			sta trkn				save target track.
				cmp curtrk	   			on desired track ?
				beq setphase			yes, energize phase and return
				lda #$00
				sta trkcnt	   			half track count.
L5440  			lda curtrk	   			save curtrk for delayed turnoff
				sta prior
				sec
				sbc trkn	   			delta-tracks.
				beq L5483				branch if curtrk = destination
				bcs mvout				move out, not in.
				eor #$FF	   			calculate tracks to go.
				inc curtrk	   			increment current track (in).
				bcc L545A				always taken.
mvout  			adc #$FE				calculate tracks to go.
				dec curtrk	   			decrement current track (out).
L545A 			cmp trkcnt
				bcc L5462				and 'tracks moved'
				lda trkcnt
L5462  			cmp #$09
				bcs L5468				if trkcnt > 8 then leave y alone (y=8)
				tay						else set acceleration index in y
				sec
L5468  			jsr setphase
				lda ontable,y			for 'ontime'
				jsr mswait	   			(100us intervals)
				lda prior
				clc		  				for phaseoff
				jsr clrphase	  		turn off prior phase
				lda offtable,y	 		then wait 'offtime'
				jsr mswait	   			(100us intervals)
				inc trkcnt	   			count of 'tracks moved'
				bne L5440				always taken
L5483  			jsr mswait	   			settle 25 msec

				clc		  				set for phase off

setphase 		lda curtrk	  			get current track
clrphase 		and #$03	   			mask for 1 of 4 phases
				rol						double for phaseon/off index
				ora A2L
				tax
				lda phaseoff,x			turn on/off one phase
				ldx A2L					restore x reg
				rts		  				and return

* 7-bit to 6-bit 'deniblize' table (16-sector format)
*
* valid codes are $96 to $FF only. codes with more than one pair of
* adjacent zeroes or with no adjacent ones (except bit 7) are excluded.
*
* nibles in the ranges of $A0-$A3, $C0-$C7, $E0-$E3 are used for
* other tables since no valid nibles are in these ranges.

dnibl			.HS 0004FFFF080CFF10	aligned to page boundary minus $96
				.HS 1418
twobit3			.HS 008040C0FFFF		used in fast prenib as lookup for 2-bit quantities.
				.HS 1C20FFFFFF24282C
				.HS 3034FFFF383C4044
				.HS 484CFF5054585C60
				.HS 6468
twobit2			.HS 00201030			used in fast prenib.
endmrks			.HS DEAAEBFF	  		table using 'unused' nibbles ($C4,$C5,$C6,$C7)
				.HS FFFFFF6CFF70
				.HS 7478FFFFFF7CFFFF
				.HS 8084FF888C909498
				.HS 9CA0
twobit1			.HS 0008040CFFA4		used in fast prenib.
				.HS A8ACFFB0B4B8BCC0
				.HS C4C8FFFFCCD0D4D8
				.HS DCE0FFE4E8ECF0F4
				.HS F8FC

* 6-bit to 2-bit conversion tables:
*
* dnibl2 abcdef-->0000FE
* dnibl3 abcdef-->0000DC
* dnibl4 abcdef-->0000BA

* origin = $D200 (page boundary)
* page align the following tables:

dnibl2			.HS 00
dnibl3			.HS 00
dnibl4			.HS 00

* 6-bit to 7-bit nibl conversion table
*
* codes with more than one pair of adjacent zeroes
* or with no adjacent ones (except B7) are excluded.

nibl			.HS 960200
				.HS 00970100009A0300
				.HS 009B0002009D0202
				.HS 009E0102009F0302
				.HS 00A6000100A70201
				.HS 00AB010100AC0301
				.HS 00AD000300AE0203
				.HS 00AF010300B20303
				.HS 00B3000002B40200
				.HS 02B5010002B60300
				.HS 02B7000202B90202
				.HS 02BA010202BB0302
				.HS 02BC000102BD0201
				.HS 02BE010102BF0301
				.HS 02CB000302CD0203
				.HS 02CE010302CF0303
				.HS 02D3000001D60200
				.HS 01D7010001D90300
				.HS 01DA000201DB0202
				.HS 01DC010201DD0302
				.HS 01DE000101DF0201
				.HS 01E5010101E60301
				.HS 01E7000301E90203
				.HS 01EA010301EB0303
				.HS 01EC000003ED0200
				.HS 03EE010003EF0300
				.HS 03F2000203F30202
				.HS 03F4010203F50302
				.HS 03F6000103F70201
				.HS 03F9010103FA0301
				.HS 03FB000303FC0203
				.HS 03FD010303FE0303
				.HS 03FF

* nibl buffer 'nbuf2' must be on a page boundary !!!

nbuf2			.BS 86		 			nibl buffer for read/write of low 2-bits of each byte.
ibtrk			.HS 00
ibsect			.HS 00
ibstat			.HS 00
iobpdn			.HS 00
curtrk			.HS 00
				.HS 00000000000000		for slots 1 thru 7
				.HS 00000000000000		drives 1 & 2
retrycnt 		.HS 00
seekcnt			.HS 00
trkcnt			.EQ	*					halftracks moved count.
countn			.EQ	*					'must find' count.
last			.HS 00		   			'odd bit' nibls.
csum			.HS 00					used for address header cksum
csstv			.HS 00
sect			.HS 00
track			.EQ	*
montimel 		.HS 00
montimeh 		.HS 00					also 'volume'
prior			.HS 00
trkn			.HS 00

* phase on, off time tables
* in 100 usec intervals (seek)

ontable			.HS 013028
				.HS 24201E1D1C1C
offtable 		.HS 702C
				.HS 26221F1E1D1C1C

* mswait subroutine
*
* delays a specified number of 100 usec intervals for motor timing.
* on entry: acc holds number of 100 usec intervals to delay.
* on exit: acc = 0, x = 0,  y = unchanged, carry set.
* montimel, montimeh are incremented once per 100 usec interval
* for motor on timing.

mswait			ldx #$11				delay 86 usec
.1  			dex
				bne .1
				inc montimel
				bne .2
				inc montimeh
.2  			sec
				sbc #$01
				bne mswait
				rts

* read address field subroutine (16-sector format)
*
* reads volume, track and sector.
* on entry: x = slot# times $10, read mode (q6l,q7l)
* on exit: carry set if error, else if no error:
*	acc=$AA, y=0, x=unchanged, carry clear,
*	ccstv contains chksum,sector,track & volume read.
* uses temps: count,last,csum & 4 bytes at ccstv
* expects: original 10-sector normal density nibls (4-bit) odd bits then even.
* observe 'no page cross' warnings on some branches !!!

rdadr16			ldy #$FC
				sty countn				'must find' count
L569D  			iny
				bne L56A5				low order of count.
				inc countn	   			(2k nibles to find address mark
				beq rderr	  			 else error)
L56A5  			lda q6l,x				read nibl
				bpl L56A5				*** no page cross ***
L56AA 			cmp #$D5	 			address mark 1 ?
				bne L569D
				nop		 				 nibl delay
L56AF 			lda q6l,x
				bpl L56AF				*** no page cross ***
				cmp #$AA	   			address mark 2 ?
				bne L56AA				if not, is it address mark 1 ?
				ldy #$03	   			index for 4 byte read
L56BA  			lda q6l,x
				bpl L56BA				*** no page cross ***
				cmp #$96	   			address mark 3 ?
				bne L56AA				if not, is it address mark 1
				sei		  				no interrupts until address is tested.
				lda #$00	   			init checksum
L56C6  			sta csum
L56C9  			lda q6l,x				read 'odd bit' nibl
				bpl L56C9				*** no page cross ***
				rol		 				align odd bits, '1' into lsb.
				sta last	   			save them.
L56D2  			lda q6l,x				read 'even bit' nibl
				bpl L56D2				*** no page cross ***
				and last	   			merge odd and even bits.
				sta csstv,y	  			store data byte.
				eor csum
				dey
				bpl L56C6				loop on 4 data bytes.
				tay		  				if final checksum non-zero,
				bne rderr				then error.
L56E6  			lda q6l,x				first bit-slip nibl
				bpl L56E6				*** no page cross ***
				cmp #$DE
				bne rderr
				nop		  				delay
L56F0  			lda q6l,x				second bit-slip nible
				bpl L56F0				*** no page cross ***
				cmp #$AA
				bne rderr
				clc						normal read ok
				rts
rderr  			sec
				rts

* read subroutine (16-sector format)
*
* reads encoded bytes into nbuf1 and nbuf2.
* first reads nbuf2 high to low, then nbuf1 low to high.
* on entry: x=slot# times $10, read mode (q6l,q7l)
* on exit: carry set if error, else if no error:
*	acc=$AA, x=unchanged, y=0, carry clear.
* observe 'no page cross' on some branches !!

read16			txa						get slot #
				ora #$8C	   			prepare mods to read routine.
				sta rd4+1				warning: the read routine is
				sta rd5+1				self modified !!
				sta rd6+1
				sta rd7+1
				sta rd8+1
				lda buf					modify storage addresses also
				ldy buf+1
				sta ref3+1
				sty ref3+2
				sec
				sbc #$54
				bcs L571F				branch if no borrow
				dey
L571F  			sta ref2+1
				sty ref2+2
				sec
				sbc #$57
				bcs L572B				branch if no borrow
				dey
L572B  			sta ref1+1
				sty ref1+2
				ldy #$20				32 tries to find
L5733  			dey
				beq L576D				branch if can't find data header marks
L5736  			lda q6l,x
				bpl L5736
L573B  			eor #$D5	   			1st data mark
				bne L5733
				nop		  				delay
L5740  			lda q6l,x
				bpl L5740
				cmp #$AA	   			2nd data mark.
				bne L573B				if not, check for 1st again
				nop
L574A  			lda q6l,x
				bpl L574A
				cmp #$AD	   			3rd data mark
				bne L573B				if not, check for data mark 1 again
				ldy #$AA
				lda #$00
L5757  			sta pcl					use z-page for keeping checksum
rd4				ldx q6l+$60	  			warning: self modified
				bpl rd4
				lda dnibl-$96,x
				sta nbuf2-$AA,y	  		save the two-bit groups in nbuf.
				eor pcl					update checksum.
				iny		  				next position in nbuf.
				bne L5757				loop for all $56 two-bit groups.
				ldy #$AA	  			now read directly into user buffer.
				bne rd5					always taken.
L576D  			sec		  				error
				rts
ref1			sta $1000,y				warning: self modified
rd5				ldx q6l+$60				warning: self modified
				bpl rd5
				eor dnibl-$96,x	  		get actual 6-bit data from dnib table.
				ldx nbuf2-$AA,y	  		get associated two-bit pattern
				eor dnibl2,x	   		and combine to form whole byte.
				iny
				bne ref1				loop for $56 bytes.
				pha		  				save for now, no time to store...
				and #$FC	   			strip low bits.
				ldy #$AA	   			prepare for next $56 bytes
				
rd6				ldx q6l+$60	  			warning: self modified
				bpl rd6
				eor dnibl-$96,x
				ldx nbuf2-$AA,y
				eor dnibl3,x
ref2			sta $1000,y				warning: self modified
				iny
				bne rd6					loop unil this group of $56 read

rd7				ldx q6l+$60	  			warning: self modified
				bpl rd7
				and #$FC
				ldy #$AC				last group is $54 long
L57A5  			eor dnibl-$96,x
				ldx nbuf2-$AC,y
				eor dnibl4,x	   		combine to form full byte
ref3			sta $1000,y				warning: self modified

rd8				ldx q6l+$60				warning: self modified
				bpl rd8
				iny
				bne L57A5
				and #$FC
				eor dnibl-$96,x	  		checksum ok ?
				bne L57CC				error if not.
				ldx A2L					test end marks.
L57C2  			lda q6l,x
				bpl L57C2
				cmp #$DE
				clc
				beq L57CD				branch if good trailer
L57CC  			sec
L57CD  			pla		 				place last byte into user buffer
				ldy #$55
				sta (buf),y
				rts

* set the slot dependent track location

settrk			jsr drvindx				get index to drive #
				sta iobpdn,x
				rts

* determine if motor is stopped
*
* if stopped, controller's shift register will not be changing.
* return y = 0 and zero flag set if it is stopped.

chkdrv			ldx A2L
chkdrv0			ldy #$00				init loop counter.
.1  			lda q6l,x				read the shift register.
				jsr ckdrts				delay
				pha
				pla		  				more delay.
				cmp q6l,x				has shift reg changed ?
				bne ckdrts				yes, motor is moving.
				lda #$28	   			anticipate error.
				dey		  				no, dec retry counter
				bne .1					and try 256 times.
ckdrts			rts

drvindx			pha		  				preserve acc across call
				lda A4L+1
				lsr
				lsr
				lsr
				lsr
				cmp #$08
				and #$07
				rol
				tax		  				index to table.
				pla		  				restore acc
				rts

* write subroutine (16 sector format)
*
* writes data from nbuf1 and buf. first nbuf2, high to low then direct
* from (buf), low to high. assumes 1 usec cycle time. self modified code !!
*
* on entry: x = slotnum times 16
*
* on exit: carry set if error (write protect violation).
*	if no error, acc=uncertain, x=unchanged, y=0, carry clear.

write16			sec						anticipate write protect error
				lda q6h,x
				lda q7l,x				sense write protect flag
				bpl L580C
				jmp wexit				exit if write protected

* timing is critical. a one micro-second cycle time is assumed.
* number in () is how many micro-seconds per instruction or subroutine

L580C  			lda nbuf2
				sta pcl
				lda #$FF   				sync data.
				sta q7h,x				(5) goto write mode
				ora q6l,x				(4)
				ldy #$04   				(2) for five nibls
				nop	  					(2)
				pha	  					(3)
				pla	 					(4)
wsync  			pha	  					(3) exact timing.
				pla	  					(4) exact timing.
				jsr wnibl7   			(13,9,6) write sync.
				dey	  					(2)
				bne wsync				(3-) must not cross page !
				lda #$D5   				(2) 1st data mark
				jsr wnibl9   			(15,9,6)
				lda #$AA   				(2) 2nd data mark
				jsr wnibl9  			(15,9,6)
				lda #$AD   				(2) 3rd data mark
				jsr wnibl9   			(15,9,6)
				tya	  					(2) zero checksum
				ldy #$56   				(2) nbuf2 index
				bne L583D				(3) branch always

* total time in this write byte loop must = 32us !!!

L583A  			lda nbuf2,y  			(4) prior 6-bit nibl
L583D  			eor nbuf2-1,y  			(5) xor with current
				tax	  					(2) index to 7-bit nibl
				lda nibl,x   			(4) must not cross page boundary
				ldx A2L					(3) restore slot index
				sta q6h,x				(5) store encoded byte
				lda q6l,x				(4) handshake
				dey	  					(2)
				bne L583A				(3-) must not cross page boundary

* end of write byte loop

				lda pcl					(3) get prior nibl (from nbuf2)
wrefd1			ldy #$00   				(2) warning: load value modified by prenib.
wrefa1			eor $1000,y 			(4) warning: address modified by prenib.
				and #$FC   				(2) strip low 2 bits
				tax	  					(2) index to nibl table
				lda nibl,x   			(4)
wrefd2			ldx #$60   				(2) warning: value modified by prenib.
				sta q6h,x				(5) write nibl
				lda q6l,x				(4) handshake
wrefa2			lda $1000,y  			(4) prior nibl. warning: address modified by prenib.
				iny	  					(2) all done with this page ?
				bne wrefa1				(3-) loop until page end.
				lda pch					(3) get next (precalculated & translated) nibl.
				beq L58C0				(2+) branch if code written was page aligned.
				lda A2H					(3) get byte address of last byte to be written.
				beq L58B3				(2+) branch if only 1 byte left to write.
				lsr						(2) test for odd or even last byte (carry set/clear)
				lda pch					(3) restore nibl to acc.
				sta q6h,x				(5)
				lda q6l,x				(4)
				lda A1L					(3) = byte 0 of 2nd page xor'd with byte 1 if
				nop	  					(2) above test set carry.
				iny	  					(2) y=1
				bcs L5899				(2+) branch if last byte to be odd.
wrefa3			eor $1100,y  			(4) warning: address modified by prenib.
				and #$FC   				(2) strip low 2 bits.
				tax		 				(2) index to nibl table
				lda nibl,x   			(4) get nibl
wrefd3			ldx #$60   				(2) restore slot index. warning: modified by prenib
				sta q6h,x				(5)
				lda q6l,x				(4)
wrefa4			lda $1100,y  			(4) warning: modified by prenib
				iny	  					(2) got prior nibl, point to next
wrefa5			eor $1100,y  			(4) warning: modified by prenib
L5899  			cpy A2H					(3) set carry if this is the last nibl
				and #$FC   				(2) strip low 2 bits
				tax	  					(2)
				lda nibl,x   			(4)
wrefd4			ldx #$60   				(2) restore slot. warning: modified by prenib
				sta q6h,x				(5)
				lda q6l,x				(4)
wrefa6			lda $1100,y 			(4) get prior nibl. warning: modified by prenib
				iny	  					(2)
				bcc wrefa3				(3-) branch if not the last.
				bcs L58B1				(3) waste 3 cycles, branch always.
L58B1  			bcs L58C0				(3) branch always.
L58B3  			lda	>pch   				(4) absolute reference to zero page
				sta q6h,x				(5)
				lda q6l,x				(4)
				pha	  					(3) waste 14 micro-seconds total
				pla	  					(4)
				pha	  					(3)
				pla	  					(4)
L58C0  			ldx A1H					(3) use last nibl (anded with $FC) for checksum
				lda nibl,x   			(4)
wrefd5			ldx #$60   				(2) restore slot. warning: modified by prenib
				sta q6h,x				(5)
				lda q6l,x				(4)
				ldy #$00   				(2) set y = index end mark table.
				pha	  					(3) waste another 11 micro-seconds
				pla	  					(4)
				nop	 					(2)
				nop	  					(2)
L58D3  			lda endmrks,y  			(4) dm4, dm5, dm6 and turn off byte.
				jsr wnibl				(15,6) write it
				iny	  					(2)
				cpy #$04   				(2) have all end marks been written ?
				bne L58D3				(3) if not.
				clc	  					(2,9)
wexit			lda q7l,x				out of write mode
				lda q6l,x				to read mode.
				rts	  					return from write.

* 7-bit nibl write subroutines

wnibl9			clc						(2) 9 cycles, then write.
wnibl7			pha	  					(3) 7 cycles, then write.
				pla	  					(4)
wnibl			sta q6h,x				(5) nibl write
				ora q6l,x				(4) clobbers acc, not carry
				rts	  					(6)

* preniblize subroutine (16 sector format)
*
* converts 256 bytes of user data in (buf) into 6 bit nibls in nbuf2.
* high 6 bits are translated directly by the write routines.
*
* on entry: buf is 2-byte pointer to 256 bytes of user data.
*
* on exit: a,x,y undefined. write routine modified to do direct conversion
*	of high 6 bits of user's buffer data.

prenib16 		lda buf					self-modify the addresses because of
				ldy buf+1				the fast timing required.
				clc		  				all offsets are minus $AA.
				adc #$02	  			the highest set is buf+$AC.
				bcc L58FA				branch if no carry,
				iny		  				otherwise add carry to high address.
L58FA 			sta prn3+1	   			self mod 3
				sty prn3+2
				sec
				sbc #$56				middle set is buf+$56.
				bcs L5906				branch if no borrow,
				dey		  				otherwise deduct from high.
L5906  			sta prn2+1				self mod 2
				sty prn2+2
				sec
				sbc #$56				low set is exactly buf
				bcs L5912
				dey
L5912  			sta prn1+1				self mod 1
				sty prn1+2
				ldy #$AA				count up to 0.
prn1			lda $1000,y				warning: self modified. get byte from lowest group.
				and #$03	   			strip high 6 bits.
				tax		  				index to 2 bit equivalent.
				lda twobit1,x
				pha		  				save pattern
prn2			lda $1056,y				warning: self modified. get byte from middle group.
				and #$03
				tax
				pla		  				restore pattern.
				ora twobit2,x	  		combine 2nd group with 1st.
				pha		  				save new pattern.
prn3			lda $10AC,y				warning: self modified. get byte from highest group.
				and #$03
				tax
				pla		  				restore new pattern
				ora twobit3,x	  		and form final nibl.
				pha
				tya
				eor #$FF
				tax
				pla
				sta nbuf2,x	  			save in nibl buffer.
				iny		  				inc to next set.
				bne prn1				loop until all $56 nibls formed.
				ldy buf					now prepare data bytes for write16 subr.
				dey		  				prepare end address.
				sty A2H
				lda buf
				sta wrefd1+1			warning: the following storage addresses
				beq L595F				starting with 'wref' are refs into code
				eor #$FF	   			space, changed by this routine.
				tay		  				index to last byte of page in (buf).
				lda (buf),y	  			pre-niblize the last byte of the page
				iny		  				with the first byte of the next page.
				eor (buf),y
				and #$FC
				tax
				lda nibl,x	   			get disk 7-bit nible equivalent.
L595F  			sta pch
				beq L596F				branch if data to be written is page
				lda A2H					aligned. check if last byte is even
				lsr						or odd address. shift even/odd -> carry.
				lda (buf),y				if even, then leave intact.
				bcc L596D				branch if odd.
				iny		  				if even, then pre-xor with byte 1.
				eor (buf),y
L596D  			sta A1L					save result for write routine.
L596F  			ldy #$FF	   			index to last byte of data to write.
				lda (buf),y	  			to be used as a checksum.
				and #$FC	   			strip extra bits
				sta A1H					and save it.
				ldy buf+1				now modify address references to
				sty wrefa1+2	   		user data.
				sty wrefa2+2
				iny
				sty wrefa3+2
				sty wrefa4+2
				sty wrefa5+2
				sty wrefa6+2
				ldx A2L					and lastly, index references to
				stx wrefd2+1	   		controller.
				stx wrefd3+1
				stx wrefd4+1
				stx wrefd5+1
				rts
chkprev			eor iobpdn				same slot as last ?
				asl
				beq L59BD
				lda #$01
				sta montimeh
L59A6  			lda iobpdn
				and #$70
				tax
				beq L59BD				branch if no previous ever (boot only).
				jsr chkdrv0	  			check if previous drive running.
				beq L59BD				branch if stopped.
				lda #$01	   			delay
				jsr mswait
				lda montimeh
				bne L59A6
L59BD  			rts
rsetphse 		lda unitnum				get unit number.
				and #$7F	  			mask off high bit.
				tax

* clear all the phases and force read mode

				lda phaseoff+0,x		make sure all motor phases are off.
				lda phaseoff+2,x
				lda phaseoff+4,x
				lda phaseoff+6,x
				rts
docheck			lda A4L					command #.
				cmp #$04	   			is the command allowed ?
				bcs L59E6				if not.
				lda bloknml
				ldx bloknml+1
				stx ibtrk				calculate block's track and sector.
				beq L59E8				branch if block # is in range,
				dex		  				else test further.
				bne L59E6				taken if bad range.
				cmp #$18	   			must be < $118
				bcc L59E8				then ok.
L59E6  			sec		  				error.
				rts
L59E8  			clc
				rts						end of obj xrw_0

				.HS 0000				pad bytes to $D6EC (pathbuf-$14)

* variables used by mli for smartport interface

spstatlist 		.HS 00000000			ref pathbuf-$14 smartport status list buffer
spunit			.HS 0000000000000000	ref pathbuf-$10smartport unit numbers
				.HS 0000000000000000

* pathname buffer starts at this page boundary (pathbuf = $D700)
*--------------------------------------
MAN
SAVE usr/src/prodos.203/prodos.s.xrw
LOAD usr/src/prodos.203/prodos.s
ASM
