FASTCO ;		* * * * * * * * * * * * *
 ;		*  PROGRAM BY KIM WATT  *
 ;		* BREEZE COMPUTING INC. *
 ;		*     P.O. BOX  1013    *
 ;		* BERKLEY, MICH.  48072 *
 ;		*    (313)  288-9422    *
 ;		* * * * * * * * * * * * *
 ;
 ;
 	ORG	7000H		;HIGHER MEMORY
 DISPLY	POP	HL		;DATA POINTER ON STACK
 LOOPA	LD	A,(HL)		;GET A BYTE
 	INC	HL		;POINT TO NEXT
 	OR	A		;SET FLAGS
 	JR	Z,DONE1		;TERMINATOR FOUND
 	CALL	33H		;DISPLAY THE BYTE
 	JR	LOOPA		;DO IT AGAIN
 DONE1	PUSH	HL		;SAVE RETURN ADDRESS
 	RET			;GO TO IT
 STRING	DEFS	40H		;255 BYTE STRING BUFFER
 LENGTH	DEFB	0		;LENGTH OF INPUT STRING
 REQLEN	DEFB	0		;REQUESTED LENGTH
 CHAR	DEFB	0		;LAST INPUT CHARACTER
 NEWST	XOR	A
 	LD	(LENGTH),A	;ZERO THE LENGTH
 	LD	HL,(4020H)	;GET START CURSOR POSIT
 	LD	DE,STRING	;FOR SHIFT LEFT ARROW
 	JR	LOOP15		;BACK TO ROUTINE
 GETSTR	LD	HL,(4020H)	;GET CURSOR POSITION
 	LD	DE,STRING	;POINT TO INPUT STRING
 	LD	A,B		;GET REQUESTED LENGTH
 	LD	(REQLEN),A	;SAVE IT
 LOOP15	LD	A,20H		;SPACE
 	LD	(DE),A		;SPACE INTO BUFFER
 	LD	(HL),A		;SPACE INTO VIDEO
 	INC	DE
 	INC	HL		;    TYPED INTO
 	DJNZ	LOOP15		;NEXT SPACE
 	XOR	A		;ZERO THE ACCUMULATOR
 	LD	(LENGTH),A	;INITIALIZE LENGTH
 	LD	HL,STRING	;SET POINTER TO BEGINNING
 ;					OF BUFFER AREA
 	LD	DE,(4020H)	;GET CURSOR POSITION
 SCAN	LD	A,8FH		;CURSOR CHARACTER
 	LD	(DE),A		;CURSOR ON
 	LD	BC,4FFH		;DELAY COUNT
 LOOP1	DEC	BC		;START COUNT
 	PUSH	BC		;SAVE COUNT
 	PUSH	DE		;MUST SAVE
 	CALL	2BH		;ROM KEYBOARD SCAN
 	POP	DE		;RESTORE
 	POP	BC		;RESTORE COUNT
 	OR	A		;SET FLAGS
 	JP	NZ,GOTONE	;IF KEY WAS PRESSED
 	LD	A,B		;TEST <BC> REG. FOR
 	OR	C		;   ZERO VALUE
 	JR	NZ,LOOP1	;GO BACK IF NOT DONE
 	LD	A,20H		;CURSOR CHARACTER
 	LD	(DE),A		;CURSOR OFF
 	LD	BC,4FFH		;DELAY COUNT
 LOOP2	DEC	BC		;START COUNT
 	PUSH	BC		;SAVE COUNT
 	PUSH	DE		;MUST SAVE
 	CALL	2BH		;ROM KEYBOARD SCAN
 	POP	DE		;RESTORE
 	POP	BC		;RESTORE COUNT
 	OR	A		;SET FLAGS
 	JP	NZ,GOTONE	;NEW KEY IF <ACC> >< 0
 	LD	A,B		;GET VALUE OF B
 	OR	C		;ANY BITS ON ?
 	JR	NZ,LOOP2	;NEXT LOOP
 	JR	SCAN		;DO IT AGAIN
 ;  KEY PRESSED IS IN <A> REG.
 GOTONE	LD	(CHAR),A	;SAVE INPUT CHARACTER
 	CP	0DH		;IS IT A CARRIAGE RETURN
 	JP	Z,DONE		;GO IF IT IS
 	CP	8		;IS IT A BACKSPACE
 	JR	Z,BCKSPA	;SEE IF IT'S OK
 	CP	18H		;SHIFT LEFT ARROW
 	JR	Z,NEWST		;INITIALIZE IF YES
 	CP	20H		;SEE IF A NON-ALPHA KEY
 	JP	C,SCAN		;   WAS PRESSED
 	LD	A,(REQLEN)	;GET REQUESTED LENGTH
 	LD	B,A		;GIVE VALUE TO <B> REG.
 	LD	A,(LENGTH)	;GET CURRENT LENGTH
 	CP	B		;COMPARE VALUES
 	JR	NC,SCAN		;TOO MANY CHARACTERS
 ;  HERE THE NEW KEY IS DISPLAYED AND STORED IN <STRING>
 	LD	A,(CHAR)	;RESTORE INPUT CHARACTER
 	LD	(DE),A		;PUT IT ON VIDEO
 	LD	(HL),A		;PUT IT IN BUFFER
 	INC	DE		;INCREMENT <HL> AND <DE>
 	INC	HL		;    TABLE POINTERS
 	LD	A,(LENGTH)	;GET LENGTH
 	INC	A		;ADD 1
 	LD	(LENGTH),A	;SAVE VALUE
 	JR	SCAN		;GET NEXT KEY
 BCKSPA	LD	A,(LENGTH)	;GET CURRENT LENGTH
 	OR	A		;SET FLAGS
 	JR	Z,SCAN		;NO CHARACTERS IN BUFFER
 	DEC	A		;SUBTRACT 1
 	LD	(LENGTH),A	;NEW LENGTH
 	LD	A,20H		;CURSOR OFF CHAR.
 	LD	(DE),A		;CURSOR OFF
 	LD	(HL),A		;PUT SPACE IN BUFFER
 	DEC	HL		;DECREMENT BOTH
 	DEC	DE		;    TABLE POINTERS
 	JR	SCAN		;GET ANOTHER KEY
 DONE	LD	A,20H		;ASCII - SPACE
 	LD	(DE),A		;CURSOR OFF
 	LD	(HL),0DH	;CARRIAGE RETURN
 	LD	A,(LENGTH)	;GET LENGTH
 	LD	B,A		;GIVE TO B REG.
 	LD	A,(STRING)	;GET FIRST INPUT CHAR.
 	LD	HL,STRING	;POINT TO BUFFER
 	RET			;ALL DONE
 HEXCV	LD	C,A		;PASS TO C REG.
 	SRL	A		;SHIFT TO UPPER NIBBLE
 	SRL	A
 	SRL	A
 	SRL	A
 	CALL	TESTA		;CONVERT TO ASCII
 	LD	H,A		;PASS TO H FOR RETURN
 	LD	A,C		;GET ORIGINAL
 	AND	0FH		;GET LOW DIGIT
 	CALL	TESTA		;CONVERT TO ASCII
 	LD	L,A		;PASS TO L REG.
 	RET			;DONE
 TESTA	ADD	A,30H		;ADD CONVERSION FACTOR
 	CP	3AH		;TEST FOR 0-9
 	JP	M,TESTB		;GO IF 0-9
 	ADD	A,7		;ADJUST FOR LETTER
 TESTB	RET			;DONE
 ENTRY	DI			;DISABLE INTERRUPTS
 	LD	SP,7000H	;BELOW PROGRAM
 	CALL	DISPLY		;MESSAGE
 	DEFW	1F1CH		;CLEAR SCREEN
 	DEFM	'-BREEZE SPECIAL DISK COPY UTILITY-'
 	DEFW	0D0DH
 	DEFM	'ENTER SOURCE DRIVE ? '
 	DEFB	0
 	LD	B,1
 	CALL	GETSTR
 	SUB	30H
 	JP	C,ENTRY		;BAD INPUT
 	CP	4
 	JP	NC,ENTRY	;BAD INPUT
 	LD	(SRCDR),A	;SAVE SOURCE DRIVE
 	CALL	DISPLY
 	DEFB	0DH
 	DEFM	'ENTER DESTINATION DRIVE ? '
 	DEFB	0
 	LD	B,1
 	CALL	GETSTR
 	SUB	30H
 	JP	C,ENTRY
 	CP	4
 	JP	NC,ENTRY
 	LD	(DESDR),A	;SAVE DESTINATION DRIVE
 	CALL	DISPLY
 	DEFW	0D0DH
 	DEFM	'HOW MANY TRACKS TO COPY (HEX) ? '
 	DEFB	0
 	LD	B,2
 	CALL	GETSTR
 	CALL	VALUE		;GET VALUE OF INPUT
 	LD	A,C		;GET THE VALUE
 	OR	A		;SET THE FLAGS
 	JP	Z,ENTRY		;NO TRACKS TO COPY
 	LD	(TRAKS),A	;SAVE # OF TRACKS
 	LD	A,(SRCDR)	;GET SOURCE DRIVE
 	SLA	A		;ADJUST TO BITS 3-5
 	SLA	A
 	SLA	A
 	OR	0C7H
 	LD	(HOPE1+1),A	;PASS TO SET COMMAND
 	LD	A,(DESDR)	;GET DESTINATION DRIVE
 	SLA	A		;ADJUST BITS
 	SLA	A
 	SLA	A
 	OR	0C7H
 	LD	(HOPE2+1),A	;PASS TO SET COMMAND
 	XOR	A		;ZERO IT FIRST
 HOPE1	SET	0,A		;SET DRIVE BIT
 	LD	(SRCDR),A	;PASS TO RAM
 	XOR	A		;ZERO IT AGAIN
 HOPE2	SET	0,A		;SET DRIVE BIT
 	LD	(DESDR),A	;PASS TO RAM
 	JP	COPY		;DO IT
 TEMPST	DEFS	10H		;TEMPORARY STORAGE
 VALUE	LD	A,(HL)		;GET 1'ST CHAR.
 	INC	HL		;POINT TO NEXT
 	CP	0DH		;NO INPUT ?
 	JP	Z,BADINP	;NO GOOD
 	SUB	30H		;REMOVE ASCII
 	JP	C,BADINP	;NO GOOD
 	CP	0AH		;BIGGER THAN 9 ?
 	JP	C,NOADJ		;DON'T ADJUST
 	SUB	7		;ADJUST FOR LETTER
 NOADJ	CP	10H		;BIGGER THAN 1 HEX DIGIT?
 	JP	NC,BADINP	;NO GOOD
 	LD	C,A		;SAVE IN CASE OF ONE CHAR
 	SLA	A		;SHIFT TO UPPER NIBBLE
 	SLA	A
 	SLA	A
 	SLA	A
 	LD	(TEMPST),A	;SAVE FOR A MINUTE
 	LD	A,(HL)		;GET IT
 	INC	HL		;POINT TO NEXT
 	CP	0DH		;ONE DIGIT SUPPLIED ?
 	RET	Z		;	YES IF ZERO
 	CP	2CH		;COMMA ?
 	RET	Z		;	YES IF ZERO
 	CP	2DH		;DASH ?
 	RET	Z		;	YES IF ZERO
 	SUB	30H		;REMOVE ASCII
 	JP	C,BADINP	;NO GOOD
 	CP	0AH		;BIGGER THAN 9 ?
 	JP	C,NOADJ2	;DON'T ADJUST
 	SUB	7		;ADJUST FOR LETTER
 NOADJ2	CP	10H		;BIGGER THAN 1 HEX DIGIT?
 	JP	NC,BADINP	;NO GOOD
 	LD	C,A		;PASS TO C REG.
 	LD	A,(TEMPST)	;GET LAST CHAR.
 	ADD	A,C		;ADD 'EM
 	LD	C,A		;GIVE IT BACK
 	LD	A,(HL)		;PASS BACK TERMINATOR
 	INC	HL		;POINT TO NEXT BYTE
 	RET			;DONE WITH IT
 BADINP	LD	C,0		;NO VALUE
 	DEC	HL		;POINT TO BAD POINT
 	RET			;DONE
 SRCDR	DEFB	0		;SOURCE DRIVE
 DESDR	DEFB	0		;DESTINATION DRIVE
 TRAKS	DEFB	0		;# OF TRACKS TO COPY
 COUNT	DEFB	0		;CURRENT COPY TRACK
 COPY 	LD	A,(SRCDR)	;GET SOURCE DRIVE
 	LD	(37E1H),A	;SELECT DRIVE
 	LD	BC,0		;1 SECOND DELAY
 	CALL	60H		;ROM LOOP
 	LD	A,(37ECH)	;GET STATUS BYTE
 	LD	HL,NOTRDY	;NOT READY MESSAGE
 	BIT	7,A		;NOT READY BIT
 	JP	NZ,ERROR	;NO GOOD
 	LD	BC,00CDH	;TIME LOOP
 	LD	HL,NOSYS	;NO SYSTEM IN DRIVE MESS.
 LOOPAA	DEC	BC		;DECREMENT COUNT
 	LD	A,B
 	OR	C		;IS IT ZERO YET ?
 	JP	Z,ERROR		;ENOUGH TESTING
 	LD	A,(37ECH)	;STATUS BYTE
 	AND	02H		;BIT 1
 	JR	NZ,LOOPAA	;STILL NOT THERE IF NZ
 	LD	BC,199DH	;ANOTHER TRICKY COUNT
 	LD	HL,NODOOR	;DOOR NOT CLOSED MESSAGE
 LOOPAB	DEC	BC
 	LD	A,B
 	OR	C		;FLAGS ARE NOW SET
 	JP	Z,ERROR		;DONE TESTING
 	LD	A,(37ECH)	;GET STATUS
 	AND	02H		;BIT 1
 	JR	Z,LOOPAB	;READY TO NOT READY ?
 	LD	DE,0
 	LD	BC,00BAH
 	LD	HL,NODISK	;NO DISK IN DRIVE MESS.
 LOOPAC	DEC	BC
 	LD	A,B
 	OR	C
 	JP	Z,ERROR		;JUMP TO ERROR DISPLAY
 	INC	DE		;COUNTER FOR DIAGNOSTIC
 	LD	A,(37ECH)	;GET STATUS
 	AND	02H		;BIT 1 AGAIN
 	JR	NZ,LOOPAC	;TRY AGAIN
 	LD	BC,1720H	;ANOTHER DELAY LOOP
 	LD	HL,NODOOR	;DOOR NOT CLOSED MESS.
 LOOPAD	DEC	BC
 	LD	A,B
 	OR	C		;FLAGS NOW SET
 	JP	Z,ERROR		;ENOUGH !
 	INC	DE		;BUMP COUNT
 	LD	A,(37ECH)	;GET STATUS BYTE
 	AND	02H		;BIT 1 STILL
 	JR	Z,LOOPAD	;MORE
 	LD	HL,0EACBH	;TRICKY !
 	ADD	HL,DE		;COMPARE
 	LD	HL,HARDSC	;HARD SECTORED MESSAGE
 	JP	NC,ERROR	;BAD BAD BAD
 ; IF WE MADE IT THIS FAR NOTHING IS WRONG
 ;	TIME TO RESTORE THE DRIVE
 	LD	A,(SRCDR)	;GET THE SOURCE DRIVE
 	LD	(37E1H),A	;RESELECT THE DRIVE
 	LD	A,0BH		;RESTORE BYTE
 	LD	(37ECH),A	;GIVE IT TO CONTROLLER
 LOOPAE	LD	A,(SRCDR)
 	LD	(37E1H),A	;KEEP RESELECTING
 	LD	A,(37ECH)	;GET STATUS
 	RRCA			;BIT 0
 	JR	C,LOOPAE	;WAIT TILL READY
 	LD	HL,NOTINS	;NOT IN SYSTEM MESSAGE
 	LD	A,(37ECH)	;GET STATUS
 	BIT	2,A		;HEAD OVER TRACK 0 ?
 	JP	Z,ERROR		;NO IT ISN'T
 	LD	A,0D0H		;FORCE INTERRUPT
 	LD	(37ECH),A	;GIVE IT TO CONTROLLER
 ; SOURCE DRIVE IS NOW READY - LET'S CHECK THE OTHER DRIVE
 	LD	A,(SRCDR)	;GET SOURCE DRIVE
 	LD	B,A		;SAVE IT HERE
 	LD	A,(DESDR)	;GET DESTINATION DRIVE
 	CP	B		;ARE THEY THE SAME ?
 	JP	Z,SINGLE	;SINGLE DRIVE COPY
 ; GOTTA TEST THE DESTINATION DRIVE NOW !
 	LD	A,(DESDR)	;GET DESTINATION DRIVE
 	LD	(37E1H),A	;SELECT THE DRIVE
 	LD	BC,0		;DELAY LOOP
 	CALL	60H		;DO IT
 	LD	A,(37ECH)	;GET STATUS BYTE
 	LD	HL,NOTRDY	;NOT READY MESS.
 	BIT	7,A		;TEST FOR IT
 	JP	NZ,ERROR	;BAD
 	LD	HL,WRPTC	;DISKETTE WRITE PROT.
 	BIT	6,A
 	JP	NZ,ERROR	;CAN'T HAVE THAT !
 	LD	BC,00CDH
 	LD	HL,NOSYS
 LOOPBA	DEC	BC
 	LD	A,B
 	OR	C
 	JP	Z,ERROR
 	LD	A,(37ECH)
 	AND	02H
 	JR	NZ,LOOPBA
 	LD	BC,199DH
 	LD	HL,NODOOR
 LOOPBB	DEC	BC
 	LD	A,B
 	OR	C
 	JP	Z,ERROR
 	LD	A,(37ECH)
 	AND	02H
 	JR	Z,LOOPBB
 	LD	DE,0
 	LD	BC,00BAH
 	LD	HL,NODISK
 LOOPBC	DEC	BC
 	LD	A,B
 	OR	C
 	JP	Z,ERROR
 	INC	DE
 	LD	A,(37ECH)
 	AND	02H
 	JR	NZ,LOOPBC
 	LD	BC,1720H
 	LD	HL,NODOOR
 LOOPBD	DEC	BC
 	LD	A,B
 	OR	C
 	JP	Z,ERROR
 	INC	DE
 	LD	A,(37ECH)
 	AND	02H
 	JR	Z,LOOPBD
 	LD	HL,0EACBH
 	ADD	HL,DE
 	LD	HL,HARDSC
 	JP	NC,ERROR
 ; SO GOOD SO FAR
 ;	TIME TO RESTORE
 	LD	A,(DESDR)	;GET DESTINATION DRIVE
 	LD	(37E1H),A	;SELECT IT
 	LD	A,0BH		;RESTORE BYTE
 	LD	(37ECH),A	;GIVE TO CONTROLLER
 LOOPBE	LD	A,(DESDR)
 	LD	(37E1H),A	;RESELECT TILL READY
 	LD	A,(37ECH)	;GET STATUS
 	RRCA			;SHIFT OUT BIT 0
 	JR	C,LOOPBE	;WAIT SOME MORE
 	LD	HL,NOTINS
 	LD	A,(37ECH)
 	BIT	2,A
 	JP	Z,ERROR		;NOT IN SYSTEM
 	LD	A,0D0H		;RESET CONTROLLER LATCHES
 	LD	(37ECH),A
 ; DESTINATION DRIVE IS NOW READY
 	XOR	A		;ZERO THE ACCUMULATOR
 	LD	(COUNT),A	;CURRENT TRACK TO COPY
 	CALL	DISPLY
 	DEFW	0D0DH
 	DEFB	0
 COPYLP	CALL	DISPLY		;SHOW WHICH TRACK
 	DEFB	1DH		;BEGINNING OF LINE
 	DEFM	'COPYING TRACK '
 	DEFB	0
 	LD	A,(COUNT)	;GET COUNT
 	CALL	HEXCV		;CONVERT TO ASCII
 	PUSH	HL
 	LD	A,H		;GET HIGH NIBBLE
 	CALL	33H		;DISPLAY IT
 	POP	HL		;RESTORE IT
 	LD	A,L		;LOW NIBBLE
 	CALL	33H		;NOW IT'S ON DISPLY
 	CALL	READ		;READ 10 SECTORS
 	LD	HL,BADRD	;BAD READ MESSAGE
 	JP	NZ,ERROR
 	LD	A,(TRAKS)	;GET REQUEST
 	LD	B,A
 	LD	A,(COUNT)
 	CP	B
 	CALL	C,STEP		;STEP IN IF NOT LAST
 	CALL	FORMAT		;FORMAT THE TRACK FIRST
 	LD	HL,BADFMT	;BAD FORMAT MESSAGE
 	JP	NZ,ERROR
 	CALL	WRITE		;WRITE 10 SECTORS
 	LD	HL,BADWR
 	JP	NZ,ERROR
 	LD	A,(TRAKS)
 	LD	B,A
 	LD	A,(COUNT)
 	CP	B
 	CALL	C,STEP		;STEP IF NOT LAST TRACK
 	LD	A,(COUNT)	;GET COUNT BACK
 	INC	A		;ADD 1
 	LD	(COUNT),A	;SAVE IT
 	LD	B,A		;GIVE IT TO B
 	LD	A,(TRAKS)	;GET REQUESTED NUMBER
 	CP	B		;COMPARE THEM
 	JP	NC,COPYLP	;DO IT AGAIN
 COPYDN	CALL	DISPLY		;TELL THE USER
 	DEFW	0D0DH
 	DEFM	'COPY IS COMPLETE'
 	DEFB	0DH
 	DEFM	'1.  RESTART PROGRAM'
 	DEFB	0DH
 	DEFM	'2.  EXIT UTILITY'
 	DEFB	0DH
 	DEFB	0
 BAD1	LD	B,1
 	CALL	GETSTR
 	CP	31H
 	JP	Z,ENTRY
 	CP	32H
 	JP	Z,0
 	JR	BAD1
 ERROR	PUSH	HL		;SAVE MESSAGE POINTER
 	CALL	DISPLY
 	DEFW	0D0DH
 	DEFM	'AN ERROR HAS BEEN DETECTED !'
 	DEFB	0DH
 	DEFB	0
 	POP	HL
 	CALL	SHOWIT		;SHOW THE ERROR
 	CALL	DISPLY
 	DEFB	0DH
 	DEFM	'<R>ESTART PROGRAM OR <T>RY AGAIN ? '
 	DEFB	0
 BAD2	LD	B,1
 	CALL	GETSTR
 	CP	'R'
 	JP	Z,ENTRY
 	CP	'T'
 	JP	Z,COPY
 	JR	BAD2
 SHOWIT	LD	A,(HL)
 	INC	HL
 	CP	3
 	RET	Z
 	CALL	33H		;DISPLAY THE BYTE
 	JR	SHOWIT		;AGAIN
 NOTRDY	DEFM	'DRIVE IS NOT READY.'
 	DEFB	3
 NOTINS	DEFM	'DRIVE NOT IN SYSTEM.'
 	DEFB	3
 NOSYS	DEFM	'NO SYSTEM IN DRIVE.'
 	DEFB	3
 NODOOR	DEFM	'DOOR NOT CLOSED.'
 	DEFB	3
 NODISK	DEFM	'NO DISK IN DRIVE.'
 	DEFB	3
 HARDSC	DEFM	'DISK IS HARD SECTORED.'
 	DEFB	3
 WRPTC	DEFM	'DESTINATION DISK IS WRITE PROTECTED.'
 	DEFB	3
 STEP	LD	A,5BH		;STEP IN BYTE
 	LD	(37ECH),A	;GIVE TO CONTROLLER
 	PUSH	BC
 	POP	BC
 	PUSH	BC
 	POP	BC
 STPWAT	LD	A,(37ECH)	;GET STATUS
 	RRCA			;SHIFT BIT 0
 	JR	C,STPWAT	;WAIT SOME MORE
 	RET			;COMMAND COMPLETE
 FORMAT	LD	HL,5D00H	;FORMAT BUFFER
 	LD	DE,INFO		;SECTOR INFORMATION
 	LD	B,0EH		;POST INDEX GAP
 	CALL	FILLFF		;FILL WITH 0FFH
 FMTLP	LD	B,6		;LOOP FOR 10 SECTORS
 	LD	C,0		;SYNC FIELD
 	CALL	FILL
 	LD	C,0FEH
 	CALL	ONE		;ID ADDRESS MARK BYTE
 	LD	A,(COUNT)	;GET CURRENT TRACK
 	LD	C,A		;GIVE TO C REG.
 	CALL	ONE		;LOAD ONE BYTE
 	LD	C,0		;HEAD NUMBER
 	CALL	ONE
 	LD	A,(DE)		;GET SECTOR INFO
 	LD	C,A
 	CALL	ONE
 	LD	C,1		;SECTOR SIZE (256 BYTES)
 	CALL	ONE
 	LD	C,0F7H		;WRITE CRC CHARACTER
 	CALL	ONE
 	LD	C,0FFH		;POST INDEX GAP
 	CALL	ONE
 	LD	B,0BH
 	CALL	FILLFF		;POST ID GAP
 	LD	B,6
 	LD	C,0		;SYNC FIELD
 	CALL	FILL
 	LD	A,(MARK)	;TYPE OF DATA MARK
 	LD	C,A
 	CALL	ONE
 	LD	B,0		;256 BYTES OF DATA
 	LD	C,0E5H		;EMPTY SECTOR DATA
 	CALL	FILL
 	LD	C,0F7H		;CRC GENERATOR
 	CALL	ONE
 	LD	C,0FFH
 	CALL	ONE
 	LD	B,0BH		;POST DATA GAP
 	CALL	FILLFF
 	INC	DE
 	LD	A,(DE)		;GET SECTOR INFO
 	INC	A		;DONE WITH LOAD BUFFER?
 	JR	NZ,FMTLP	;NOPE !
 	LD	B,5BH		;END OF DATA GAP
 	CALL	FILLFF
 ; NOW ITS TIME TO WRITE THE TRACK
 	CALL	FMTIT		;TRY IT ONCE
 	RET	Z		;SUCCESSFUL
 FMTIT	LD	A,(DESDR)	;DESTINATION DRIVE
 	LD	(37E1H),A	;SELECT IT
 	LD	BC,5D00H	;DATA BUFFER
 	LD	HL,37ECH	;COMMAND REGISTER
 	LD	(HL),0F4H	;WRITE TRACK COMMAND
 	LD	DE,37EFH	;DATA TRANSFER
 	PUSH	BC
 	POP	BC
 	PUSH	BC
 	POP	BC
 	NOP			;SAVE FOR LATER
 	JR	HOLD		;IS CONTROLLER READY?
 HOLDIT	RRCA			;SHIFT BIT 0
 	JP	NC,NOHOLD	;DONE WITH COMMAND
 HOLD	LD	A,(HL)		;GET STATUS BYTE
 	BIT	1,A		;READY FOR BYTE ?
 	JR	Z,HOLDIT	;NOT READY IN ZERO
 	LD	A,(BC)		;GET BYTE FROM BUFFER
 	LD	(DE),A		;GIVE TO CONTROLLER
 	INC	BC		;NEXT BUFFER BYTE
 	JR	HOLD		;ANY MORE ?
 NOHOLD	LD	A,(HL)		;GET STATUS
 	LD	(HL),0D0H	;FORCE INTERRUPT
 	BIT	2,A		;ANY DATA LOST ?
 	LD	HL,TOFAST	;TRANSFER TOO FAST MESS.
 	JP	NZ,ERROR
 	LD	HL,0A300H
 	ADD	HL,BC
 	EX	DE,HL
 	LD	HL,0F413H
 	ADD	HL,DE
 	LD	HL,TOSLOW	;TRANSFER TOO SLOW MESS.
 	JP	NC,ERROR
 	LD	HL,0F397H
 	ADD	HL,DE
 	LD	HL,TOFAST	;TOO FAST MESSAGE
 	JP	C,ERROR
 	RET			;WHEW - MADE IT !
 FILLFF	LD	C,0FFH		;FILL BYTE
 FILL	CALL	ONE		;LOAD ONE BYTE
 	DJNZ	FILL		;KEEP GOING
 	RET
 ONE	LD	(HL),C		;STORE INTO BUFFER
 	INC	HL		;POINT TO NEXT
 	RET
 GETMRK	LD	B,0A8H
 	LD	C,0FBH
 	AND	60H		;ONLY BITS 5,6
 	CP	0		;STANDARD ID
 	JP	Z,OKMARK	;GOT IT
 	LD	B,0A9H
 	LD	C,0F9H
 	CP	20H
 	JP	Z,OKMARK
 	LD	B,0AAH
 	LD	C,0FAH
 	CP	40H
 	JP	Z,OKMARK
 	LD	B,0ABH
 	LD	C,0F8H
 	CP	60H
 	JP	Z,OKMARK
 	LD	HL,PRMERR	;PROGRAM ERROR
 	JP	ERROR
 OKMARK	LD	A,B
 	LD	(MARKER+1),A	;TYPE OF WRITE OPERATION
 	LD	A,C
 	LD	(MARK),A	;TYPE OF DATA MARK
 	RET			;DONE
 MARK	DEFB	0
 PRMERR	DEFM	'PROGRAM ERROR HAS OCCURED'
 	DEFB	3
 INFO	DEFB	0
 	DEFB	5
 	DEFB	1
 	DEFB	6
 	DEFB	2
 	DEFB	7
 	DEFB	3
 	DEFB	8
 	DEFB	4
 	DEFB	9
 	DEFB	0FFH
 BADRD	DEFM	'DISKETTE READ OPERATION FAULT'
 	DEFB	3
 BADWR	DEFM	'DISKETTE WRITE OPERATION FAULT'
 	DEFB	3
 BADFMT	DEFM	'FORMAT OPERATION WRITE FAULT'
 	DEFB	3
 FIXDAT	PUSH	DE		;SAVE INFO POINTER
 	LD	E,0		;256 DATA BYTES
 FIXLP	LD	A,(BC)		;GET DATA BYTE
 	LD	(HL),A		;SAVE INTO BUFFER
 	INC	BC
 	INC	HL
 	DEC	E
 	JR	NZ,FIXLP
 	POP	DE		;RESTORE
 	RET
 READ	LD	BC,8000H	;BUFFER FOR DATA
 	LD	HL,0AH		;10 SECTORS TO READ
 	PUSH	BC
 	PUSH	HL		;SAVE 'EM ON THE STACK
 	LD	E,0		;SECTOR 0
 AGAIN	LD	A,(COUNT)	;GET CURRENT TRACK
 	LD	D,A		;GIVE IT TO D
 	CALL	READA		;READ A SECTOR
 	LD	HL,BADRD	;BAD READ
 	JP	NZ,ERROR	;ERROR DETECTED
 	POP	HL		;GET LOOP COUNT
 	DEC	L		;REDUCE COUNT
 	JR	Z,DONERD	;DONE READING
 	PUSH	HL		;RESAVE IT
 	INC	E		;NEXT SECTOR POINTER
 	LD	A,E		;PASS TO ACCUMULATOR
 	SUB	0AH		;10 SECTORS
 	JP	NZ,AGAIN	;NOT DONE
 	LD	E,A		;SECTOR COUNT -10
 	INC	D		;NEXT TRACK
 	JP	AGAIN		;GET NEXT SECTOR
 DONERD	POP	BC		;RELEASE LOAD POINT
 	LD	A,(37ECH)	;GET STATUS
 	CALL	GETMRK		;PLACE DATA MARKERS
 	RET			;DONE WITH READ
 READA	PUSH	BC		;SAVE POINTER
 	CALL	READB		;READ THE SECTOR
 	POP	HL		;GET LOAD POINTER
 	RET	Z		;SUCCESSFUL
 	LD	B,H		;TRY ONE MORE TIME
 	LD	C,L		;	IF BAD READ
 READB	LD	(37EEH),DE	;TRACK/SECTOR
 	LD	A,(SRCDR)	;GET SOURCE DRIVE
 	LD	(37E1H),A	;	DRIVE 0
 	PUSH	AF
 	POP	AF
 	LD	HL,37ECH	;COMMAND REGISTER
 	LD	(HL),1BH	;SEEK BYTE
 	PUSH	AF
 	POP	AF
 	PUSH	AF
 	POP	AF
 TESTBZ	LD	A,(HL)		;GET STATUS
 	RRCA			;COMMAND IN PROGRESS ?
 	JP	C,TESTBZ	;NOT DONE
 	LD	(HL),88H	;READ SECTOR BYTE
 	PUSH	DE		;SAVE TRACK/SECTOR
 	LD	DE,37EFH	;DATA TRANSFER ADDRESS
 	PUSH	BC
 	POP	BC
 	JR	BZTEST		;WAIT FOR OK TO CONTINUE
 TEST	RRCA			;BIT 0 SET IF BUSY
 	JP	NC,TEST1	;DONE WITH COMMAND
 BZTEST	LD	A,(HL)		;GET STATUS BYTE
 	BIT	1,A		;VALID DATA PRESENT ?
 	JP	Z,TEST		;GUESS NOT
 	LD	A,(DE)		;GET NEW BYTE
 	LD	(BC),A		;PUT IT IN BUFFER
 	INC	BC		;POINT TO NEXT
 	JP	BZTEST		;ANY MORE ?
 TEST1	LD	A,(HL)		;GET RESULT
 	BIT	2,A		;DATA LOST ?
 	POP	DE		;RESTORE TRACK/SECTOR
 	RET	Z		;EVERYTHING OK
 	LD	(HL),0D0H	;FORCE INTERRUPT
 	RET			;BACK ANYWAY
 WRITE	LD	BC,8000H	;BUFFER FOR DATA
 	LD	HL,0AH		;10 SECTORS TO WRITE
 	PUSH	HL		;SAVE ON STACK
 	LD	E,0		;SECTOR 0
 MORE	LD	A,(COUNT)	;GET CURRENT TRACK
 	LD	D,A		;GIVE IT TO D
 	LD	(37EEH),DE	;SELECT TRACK/SECTOR
 	LD	A,(DESDR)	;GET DESTINATION DRIVE
 	LD	(37E1H),A	;	DRIVE 0
 	CALL	WRITEA		;WRITE A SECTOR
 	LD	HL,BADWR	;BAD WRITE DETECTED
 	JP	NZ,ERROR	;DIDN'T WORK
 	POP	HL		;GET COUNT
 	DEC	L		;DECREMENT COUNTER
 	JP	Z,DONEWR	;DONE WRITING
 	PUSH	HL		;PUT IT BACK ON STACK
 	INC	E		;INCREMENT SECTOR
 	LD	A,E		;PASS TO ACCUMULATOR
 	SUB	0AH		;10 SECTORS/TRACK
 	JP	NZ,MORE		;NOT DONE
 	LD	E,A		;SECTOR COUNT -10
 	INC	D		;NEXT TRACK
 	JP	MORE		;DO IT SO MORE
 DONEWR	LD	A,(37ECH)	;GET STATUS
 	BIT	2,A		;DATA LOST DURING XFER ?
 	LD	HL,BADWR	;BAD WRITE MESSAGE
 	JP	NZ,ERROR	;TOO BAD
 	RET			;DONE WRITING
 WRITEA	PUSH	BC		;SAVE IT
 	CALL	WRITEB		;WRITE SECTOR
 	POP	HL		;CURRENT LOAD POSITION
 	RET	Z		;SUCCESSFUL
 	LD	B,H		;TRY ONCE MORE
 	LD	C,L		;	IF BAD READ
 WRITEB	LD	(37EEH),DE	;TRACK/SECTOR TO WRITE
 	LD	HL,37ECH	;COMMAND REGISTER
 	LD	A,(DESDR)	;RESELECT DESTINATION DR.
 	LD	(37E1H),A
 	LD	(HL),1BH	;SEEK BYTE
 	PUSH	AF
 	POP	AF
 	PUSH	AF
 	POP	AF
 BYTEST	LD	A,(HL)		;GET STATUS
 	RRCA			;SHIFT OUT BIT 0
 	JP	C,BYTEST	;NOT FOUND YET
 MARKER	LD	(HL),0A9H	;WRITE SECTOR BYTE
 ;  A9 = READ PROTECTED  A8 = DATA MARK  AA = DELETED DATA
 	PUSH	DE		;SAVE TRACK/SECTOR
 	LD	DE,37EFH	;DATA TRANSFER ADDRESS
 	PUSH	BC
 	POP	BC
 	PUSH	BC
 	POP	BC
 	JP	TESTBY		;WAIT TILL READY
 TESTZ	RRCA			;SHIFT BIT 0
 	JP	NC,TESTX	;DONE WITH COMMAND
 TESTBY	LD	A,(HL)		;GET STATUS
 	BIT	1,A		;READY FOR DATA ?
 	JP	Z,TESTZ		;WAIT SOME MORE
 	LD	A,(BC)		;GET BYTE FROM BUFFER
 	LD	(DE),A		;PASS TO CONTROLLER
 	INC	BC		;NEXT BYTE IN BUFFER
 	JP	TESTBY		;WAIT FOR READY
 TESTX	LD	A,(HL)		;CLEAR LATCH
 	BIT	2,A		;DATA LOST ?
 	POP	DE		;RESTORE TRACK/SECTOR
 	RET	Z		;DONE WITH SECTOR
 	LD	(HL),0D0H	;FORCE INTERRUPT
 	RET			;DISK ERROR
 TOFAST	DEFM	'DATA TRANSFER TOO FAST'
 	DEFB	3
 TOSLOW	DEFM	'DATA TRANSFER TOO SLOW'
 	DEFB	3
 	END	ENTRY
