          .Z80
;
; FORMAT VERSION 3.1
;
; FORMAT PROGRAM FOR THE WD 1793 & WD 2793 FDISK CONTROLLER
;

FALSE	EQU	0
TRUE	EQU	NOT FALSE
CR	EQU	0DH
LF	EQU	0AH

BDOS	EQU	5			; BDOS ENTRY POINT
WBOOT	EQU	0			; WARM BOOT RETURN

;
; DISK DRIVE TYPE
;

MINI	EQU	TRUE			; SET TO TRUE FOR 5.25 IN. DISKS
FORTY8	EQU	TRUE			; SET TO TRUE FOR 48TPI DRIVES

;
; DENSITY AND SIDE INDICATORS/CODES INFORMATION
;

DD	EQU	1			; DOUBLE DENSITY FLAG
SD	EQU	0			; SINGLE DENSITY FLAG
SS	EQU	0			; SINGLE SIDED FLAG
DS	EQU	1			; DOUBLE SIDED FLAG
DDDS	EQU	0E7H			; DOUBLE DENS DOUBLE SIDED CODE
DDSS	EQU	0E6H			; DOUBLE DENS SINGLE SIDED CODE
SDSS	EQU	0E5H			; SINGLE DENSITY SINGLE SIDED CODE
DATA	EQU	0E5H			; VALUE TO FILL SECTORS WITH
RPT	EQU	099H			; REPEAT INDICATOR
ENDRPT	EQU	066H			; END OF REPEAT INDICATOR
ENDTRK	EQU	0AAH			; END OF TRAK MARKER
IDAM	EQU	0FEH			; ID ADDRESS MARK

	IF	FORTY8
MINITRKS  EQU	40			;48TPI MINI MAX TRACKS
	ELSE
MINITRKS  EQU	77			;96TPI MINI MAX TRACKS
	ENDIF

EINCHTRKS EQU	77			;8 INCH DIVE MAX TRACKS
MINISECS  EQU	4			;MINI SECTORS
DDSECÓ    EQU	8			;8 INCH DOUBLE DENSITY SECTORS
SDSECS    EQU	26			;8 INCH SINGLE DENSITY SECTORS

;
; DISK COMMANDS
;

SEEK	EQU	019H			;SEEK
WTRAK	EQU	0F4H			;WRITE TRACK
RESTORE	EQU	01H			;RESTORE
SECTRD0	EQU	082H			;READ SECTOR SIDE ZERO
SECTRD1	EQU	08AH			;READ SECTOR SIDE ONE

CMD	EQU	0CH			;COMMAND REGISTER
TRACK	EQU	CMD + 1			;TRACK REGISTER
SECT	EQU	CMD + 2			;SECTOR REGISTER
DAL	EQU	CMD + 3			;DATA PORT
WAIT	EQU	014H			;STATUS/SELECT REGISTER


          CSEG

START:
	LD	SP,START		;INITIALIZE STACK POINTERŠ	LD	DE,MSG1
	CALL	PRNT			;PRINT START MESSAGE

;
; OBTAIN DISK DRIVE NUMBER
;

RESTART:

LL:	LD	DE,MSG4
	CALL	PRNT
	CALL	CHARIN			;GET DRIVE TO BE USED
	SUB	'0'
	JR	C,LL
	CP	4
	JR	NC,LL
	LD	(DRIVENO),A		;SAVE DRIVE NUMBER
;
;OBTAIN DENSITY INFORMATION
;
	IF	MINI
	LD	A,DD
	LD	(DENS),A		;SET DOUBLE DENSITY FOR MINI
;
 	ELSE
LER:	LD	DE,MSG5
	CALL	PRNT
	CALL	CHARIN			;ASK USER DENSITY INFO
	CP	'D'
	JR	Z,DOUBLE
	CP	'S'
	JR	NZ,LER			;ERROR
	LD	A,SD			;SET SINGLE DENSITY
	JR	SDDDCNTL
;
DOUBLE:	LD	A,DD
SDDDCNTL:
	LD	(DENS),A		;SET DOUBLE DENSITY
	ENDIF
;
	LD	A,(DENS)
	CP	SD
	JR	NZ,CHEKSIDE		;GET SIDE (DOUBLE/SINGLE) INFO
	LD	A,SS
	JR	SIDECNTL		;SET SINGLE SIDED
CHEKSIDE:
	LD	DE,MSG6
	CALL	PRNT
	CALL	CHARIN			;ASK USER IF SINGLE OR DOUBLE SIDED
	CP	'S'
	JR	NZ,CHEKDS
	LD	A,SS
	JR	SIDECNTL		;SET SINGLE SIDED
ŠCHEKDS:	CP	'D'
	JR	NZ,CHEKSIDE
	LD	A,DS
SIDECNTL:
	LD	(SIDED),A
;
ERR:	LD	DE,MSG7
	CALL	PRNT			;SEE IF SYS TRAKS ONLY
	CALL	CHARIN
	CP	'N'
	JR	Z,CONTINUE
	CP	'Y'
	JR	NZ,ERR
	LD	A,(DENS)
	CP	SD
	JR	NZ,ONETRK		;SET MAX TRAKS TO ONE FOR DOUBLE DENS
	LD	A,2			;SET TO TWO FOR SINGLE DENSITY
ONETRK:	LD	(MAXTRKS),A         
	JR	CONT1			;INDICATE SYSTEM TRACKS ONLY
;
CONTINUE:
	XOR	A
CONT1:	LD	(SYSFLAG),A         
;
;SEE IF VERIFY SHOULD BE SUPRESSED
LLL:	LD	DE,MSG77
	CALL	PRNT
	CALL	CHARIN
	CP	'N'
	JR	Z,DNTSUPRES
	CP	'Y'
	JR	NZ,LLL
	LD	A,1
	JR	LL1
DNTSUPRES:
	XOR	A
LL1:	LD	(SPFLAG),A
REDO:
;SET UP OPERATIONAL PARAMETERS
;
 	IF	MINI
	LD	A,(SIDED)
	CP	SS
	JR	Z,NDSIDED
	LD	A,DDDS			;DOUBLE SIDED CODE INFORMATION
	JR	FWD
NDSIDED:
	LD	A,DDSS			;SINGLE SIDED CODE INFORMATION
FWD:	LD	(DENSCODE),A
	LD	A,(SYSFLAG)
	OR	A
	JR	NZ,DONTCHG
	LD	A,MINITRKS
	LD	(MAXTRKS),A
DONTCHG:
	LD	A,MINISECS
	LD	(MAXSECS),AŠ	LD	IX,DDCONTROL		;LOAD IX WITH DOUBLE DENSITY CONTROL BLOCK ADDRES
	LD	(IXTRK1ON),IX		;SAVE IX POINTER
	LD	IY,MINISEQ
	LD	(IYTRK1ON),IY		;SAVE IY POINTER
	LD	IY,MINISEQ0		;SET IY TO POINT TO TRACK 0 FORMAT
	ELSE
	LD	A,(SYSFLAG)		;CHECK SYSTEM TRACKS ONLY INDICATOR
	OR	A
	JR	NZ,DONTCHNG
	LD	A,EINCHTRKS
	LD	(MAXTRKS),A
DONTCHNG:
	LD	A,(DENS)
	CP	SD			;CHECK SINGLE DENSITY
	JR	Z,NDD
	LD	IX,DDCONTROL
	LD	(IXTRK1ON),IX
	LD	IY,DDSEQ
	LD	(IYTRK1ON),IY
	LD	A,(SIDED)
	CP	SS
	JR	Z,NDSIDED
	LD	A,DDDS			;DOUBLE DENSITY DOUBLE SIDED CODE INFO
	JR	FWD1
NDSIDED:
	LD	A,DDSS			;DOUBLE DENSITY SINGLE SIDED CODE INFO
FWD1:	LD	(DENSCODE),A
;
;SET CONTROL PARMETER TO SINGLE DENSITY,EVEN IF WORKING WITH DOUBLE DENSITY
;SINCE TRACK ZERO IS ALWAYS FORMATTED SINGLE DENSITY
	LD	IX,SDCONTROL		;SET SINGLE DENSITY CONTROL
	LD	IY,SDSEQ
	JR	HERE
NDD:	LD	A,SDSS			;SINGLE DENSITY SINGLE SIDED DENS CODE

	LD	(DENSCODE),A
	LD	IX,SDCONTROL
	LD	(IXTRK1ON),IX		;SET CONTROL TO SINGLE FOR ALL TRACKS
	LD	IY,SDSEQ
	LD	(IYTRK1ON),IY		;SET SECTOR SEQUENCE ALSO TO SINGLE
HERE:	LD	A,SDSECS		;SINGLE DENSITY SECTORS
	LD	(MAXSECS),A
	ENDIF
;
;SAVE IX AND IY REGISTERS FOR TRACK ZERO DOUBLE SIDED RETRIEVE
	LD	(IX0SAVE),IX		;SAVE IX
	LD	(IY0SAVE),IY		;SAVE IY
;PROMPT USER BY ASKING TO TYPE A RETURN TO BEGIN FORMATTING
	LD	DE,MSG8
	CALL	PRNT
	LD	A,(DRIVENO)
	ADD	A,030H
	CALL	CHAROUT			;PRINT DRIVE NUMBER
	LD	DE,MSG9
	CALL	PRNTŠ	LD	C,1
	CALL	BDOS
	CP	CR
	JP	NZ,WBOOT		;GO BACK TO CPM
	CALL	CHAROUT
	LD	A,LF
	CALL	CHAROUT
;
;RESET HEAD AND DISK DRIVE STATUS REGISTERS
	CALL	RESUMESCREEN
	XOR	A
	LD	D,A			;START WITH TRACK ZERO
	LD	(SIDE),A		;SIDE ZERO
	CALL	SELSIDE			;SELECT SIDE
	LD	A,RESTORE
	CALL	PERFORM
;
;MAIN PROGRAM LOOP BASICALLY STARTS HERE
L11:	PUSH	IX
	PUSH	IY
	PUSH	DE
	LD	DE,MSG147
	CALL	PRNT
	POP	DE
	LD	A,D
	PUSH	DE
	CALL	HEXOUT
	POP	DE
	POP	IY
	POP	IX
L12:	LD	HL,BUFFER		;BUFFER TO SET UP DATA
L1:	LD	A,(IX)			;GET CONTROL
	CP	RPT			;IS IT REPEAT?
	JR	NZ,NRPT
	INC	IX
	CALL	REPEAT			;PERFORM REPEAT IF SO
	JR	L1
NRPT:	CP	ENDTRK			;IS END OF CONTROL FOR THIS TRACK ?
	JR	Z,WRITE
	CALL	PUT			;SET UP BUFFER ACCORDINGLY
	JR	L1
;
WRITE:	LD	HL,BUFFER		;SET HL TO BUILT BUFFER
	DI				;DISABLE INTERRUPTS
	CALL	WRTRAK			;WRITE THIS TRACK
	EI				;REENABLE INTERRUPTS
	IN	A,(CMD)			;CHECK FOR ERROR
	LD	(STATUS),A
	OR	A
	JP	NZ,WRERROR		;PROCEES WRITE ERROR
	LD	A,(SPFLAG)		;SEE IF READ SHOULD BE SUPRESSED
	OR	A
	JR	NZ,DONTVRFY
	CALL	RDTRK			;VERIFY BY READINGŠDONTVRFY:
	LD	A,(SIDED)
	CP	SS
	JR	Z,NOTDSIDED
	LD	A,(SIDE)
	OR	A
	JR	Z,CHNGSIDE		;CHANGE SIDE TO ONE AND WRITE OTHER SIDE
	XOR	A
	LD	(SIDE),A		;OTHERWISE RESET SIDE BACK TO ZERO
	CALL	SELSIDE			;SELECT SIDE ZERO 
SKIPTONEXT:
NOTDSIDED:
	PUSH	DE			;SAVE REG
	LD	C,11			;CHECK CONSOLE STATUS
	CALL	BDOS
	OR	A			;CHAR AVAIL.
	POP	DE			;RESTORE DE
	JR	Z,SKP			;SKIP IF NOT
	PUSH	DE			;SAVE REG
	LD	C,1			;GET CHAR
	CALL	BDOS
	CP	3			;IS IT A ^C
	POP	DE			;RESTORE DE
	JP	Z,ABORT			;IF SO ASK IF EXIT
SKP:	INC	D			;INCREMENT TRACK COUNTER
	LD	B,D
	LD	A,(MAXTRKS)
	CP	B
	JR	Z,COMPLETE		;IF MAX TRACK REACHED THEN DONE
	IF	NOT MINI
;
;SEE IF CONTROL PARAMETERS HAVE TO BE SWITCHED FROM SINGLE TO DOUBLE
;
	LD	A,D
	CP	1			;SEE IF TRACK ONE
	JR	NZ,NOTTRK1
	LD	A,(DENS)
	CP	DD			;SEE IF DOUBLE DENSITY
	JR	NZ,NOTDD
	LD	A,DDSECS		;SET MAX DOUBLE DENSITY SECTORS
	LD	(MAXSECS),A
	CALL	SELSIDE			;SELECT DOUBLE DENSITY 
NOTDD:
NOTTRK1:
	ENDIF
;
;PREPARE FOR NEXT TRACK
	LD	A,D
	OUT	(DAL),A			;SET DATA REGISTER TO PROPER TRK
	LD	A,SEEK			;SEEK TO NEXT TRACK
	CALL	PERFORM
	LD	IX,(IXTRK1ON)		;GET IX POINTER
	LD	IY,(IYTRK1ON)		;GET IY POINTER
	JP	L11
CHNGSIDE:
	LD	A,1			;SIDE ONE
	LD	(SIDE),A
	CALL	SELSIDE			;SELECT SIDE ONE
	LD	A,D
	OR	A			;TEST FOR TRACK ZERO
	JR	NZ,NOTZ
	LD	IX,(IX0SAVE)		;RETRIEVE TRACK ZERO IX
	LD	IY,(IY0SAVE)		;RETRIEVE TRACK ZERO IY
	JP	L12			;FORMAT SIDE ONE
NOTZ:	LD	IX,(IXTRK1ON)		;RESET IX
	LD	IY,(IYTRK1ON)		;RESET IYŠ	JP	L12			;FORMAT SIDE ONE
;
ABORT:	LD	DE,ABTMSG		;PRINT ABORTED MESSAGE
	CALL	PRNT
	JR	L2
;
COMPLETE:
	LD	DE,MSG10
	CALÌ	PRNT			;END OF OPERATION MESSAGE
L2:	LD	DE,MSG11
	CALL	PRNT
	CALL	CHARIN
	OR	A
	JP	Z,WBOOT
	CP	'C'
	JR	NZ,L2 
	XOR	A
	LD	(DENDNE),A		;CLEAR DENSITY WRITE FLAG

L5:	LD	DE,MSG12
	CALÌ	PRNÔ			;SEE IF THE SAME PARAMS ARE TO BE USED
	CALL	CHARIN
	OR	A
	JP	Z,REDO
	CP	'N'
	JR	NZ,L5
	JP	RESTART

;
;REPEAT SUBROUTINE BUILDS THE BUFFER FOR THE NUMBER OF SECTORS SPECIFIED
;
;

REPEAT:	LD	A,(MAXSECS)		;MAX SECTORS
	LD	C,A
	LD	(IXSAVE),IX		;SAVE IX
L6:	LD	E,(IY)			;SECTOR NUMBER IN E REGISTER
	INC	IY
LOOP1:	LD	A,(IX)
	CP	ENDRPT 			;IS IT END OF REPEAT
	JR	Z,ENDR
	CALL	PUT			;BUILD BUFFER
	JR	LOOP1
ENDR:	INC	IX
	DEC	C
	RET	Z
	LD	IX,(IXSAVE)
	JR	L6
;
;THE PUT SUBROUTINE TAKES COMMAND FROM CONTROL BUFFER AND BUILDS ACCORDINGLY
;
PUT:	LD	B,(IX)			;REPEAT COUNT
	INC	IX
	LD	A,(IX)			;DATA VALUE
	INC	IXŠ	CP	IDAM			;IS IT ID ADDRESS MARK
	JR	NZ,NOTIDAM
	LD	(HL),A			;PUT DATA
	INC	HL
	LD	(HL),D			;PUT TRACK
	INC	HL
	LD	A,(SIDE)		;SIDE
	LD	(HL),A
	INC	HL
	LD	(HL),E			;SECTOR
	INC	HL
	RET
;
NOTIDAM:
LOOP:	LD	(HL),A
	INC	HL
	DEC	B
	JR	NZ,LOOP
	CP	DATA			;SEE IF DATA VALUE
	RET	NZ
	LD	A,(SIDE)
	ADD	A,E			;GET SECTOR NUMBER
	DEC	A
	OR	D			;TRACK
	PUSH	BC
	LD	B,A
	LD	A,(DENDNE)		;WRITTEN DENSITY CODE ALREADY
	OR	B
	POP	BC
	RET	NZ			;IF TRACK 0 SECT ONE THEN SET DENS CODE
	LD	A,(DENSCODE)		;GET DENS CODE
	DEC	HL			;POINT TO THE LAST BYTE OF DATA
	LD	(HL),A			;PUT DENS CODE
	INC	HL
	LD	(DENDNE),A		;SAY DONE ONCE
	RET
;
; CHARIN SUBROUTINE INPUTS ONE CHARACTER FROM CONSOLE IN A REGISTER
CHARIN:   
	XOR	A
	LD	(IBUFF+2),A
	LD	C,10
	LD	DE,IBUFF
	LD	A,80
	LD	(DE),A
	CALL	BDOS
	LD	A,(IBUFF+2)
	CP	'a'
	JP	C,LOWER
	CP	'z'+1
	JP	NC,LOWER
	AND	05FH
LOWER:	RET
;
CHAROUT:
	LD	C,2
	LD	E,A
	CALL	BDOS
	RET
;
PRNT:Š	LD	C,9
	CALL	BDOS
	RET
;
RESUMESCREEN:
	PUSH	DE
	LD	A,(SPFLAG)
	OR	A
	JR	NZ,SPSCREEN
	LD	DE,MSG13
	CALL	PRNT
	LD	DE,MSG14
	CALL	PRNT
	LD	DE,MSG147
	CALL	PRNT
	JR	KK
SPSCREEN:
	LD	DE,MSG148
	CALL	PRNT
	LD	DE,MSG147
	CALL	PRNT
KK:
	POP	DE
	LD	A,D
	PUSH	DE
	CALL	HEXOUT
	POP	DE
	RET
;
MSGP:	DB	CR,LF,LF,'DISK ERROR: $'
;
PERFORM:
	DI
	OUT	(CMD),A
	IN	A,(WAIT)
	EI
	IN	A,(CMD)			;GET STATUS
	OR	A
;NEEDS TO BE VALIDATED
	RET
;ERROR
	PUSH	AF
	LD	DE,MSGP
	CALL	PRNT
	POP	AF
	CALL	DETERMERR
	JP	WBOOT			;BACK TO CPM
;
WRTRAK:   
	LD	A,WTRAK
	LD	C,DAL
	OUT	(CMD),A
L3:	IN	A,(WAIT)
	OR	AŠ	RET	P
;
	OUTI
	JR	L3
;
;READ VRIFY ROUTINE
;
RDTRK:	LD	(IYSAVE),IY		;SAVE IY FOR A POSSIBLE RETRY
	LD	A,(MAXSECS)		;SAVE MAX SECS
	LD	(READSECS),A
NEXTSECTOR:
	XOR	A			;RESET RETRY INDICATOR
	LD	(RTRY),A
RETRY:	LD	A,(IY)			;IY POINTS TO SECTOR UNDER VERIFICATION
	OUT	(SECT),A		;LOAD SECTOR REGISTER
	LD	A,(SIDE) 
	OR	A
	JR	Z,SIDE0			;LOAD WITH CONTROL CODE FOR SIDE ZERO
	LD	A,SECTRD1		;LOAD WITH CONTROL CODE FOR SIDE ONE
	JR	STARTRD
SIDE0:	LD	A,SECTRD0
STARTRD:
	DI				;NO OUTSIDE BOTHERING
	OUT	(CMD),A			;REQUEST READ SECTOR
NEXTBYTE:
	IN	A,(WAIT)		;WAIT FOR OPERATTION COMPLETE
	AND	080H
	JR	Z,DONESECT		;DONE WITH THIS SECTOR
;
	IN	A,(DAL)			;INPUT DATA BYTE
	JR	NEXTBYTE		;GET NEXT BYTE
;
DONESECT:
	EI				;CAN NOW BE BOTHERED AGAIN
	IN	A,(CMD)			;GET STATUS
	LD	(STATUS),A		;SAVE AWAY
	OR	A			;ERROR?
	JR	NZ,FAILED		;PROCESS ERROR CASE
	LD	A,(READSECS)
	DEC	A			;SECTOR COUNTER
	JR	Z,DONETRK
	LD	(READSECS),A
	INC	IY			;POINT TO NEXT SECTOR ID
	JR	NEXTSECTOR		;VERIFY NEXT SECTOR
;
DONETRK:
	LD	A,(RTRY)		;SEE IF ANY RETRIES PERFORMED
	OR	A
	RET	Z			;RETURN OF NORMAL CASE
	CALL	RESUMESCREEN
	RET				;RETURN
;
;PROCESS ERROR ACCORDINGLY
;
FAILED:	LD	A,(RTRY)		;INCREMENT RETRY 
	INC	A
	LD	(RTRY),A
	CP	10
	JR	C,RETRY
;
;10 RETRIES FAILED, REPORT FATAL ERROR
;
	PUSH	DE			;SAVE IT
	LD	DE,MSG19
	CALL	PRNT
	LD	A,(STATUS)
	CALÌ	DETERMERR		;PRINT APPROPRIATE ERROR
USERINTERFACE:
	LD	DE,MSG155
	CALL	PRNT
	LD	A,(SIDE)
	CALL	OUT
	LD	DE,MSG16
	CALL	PRNT               
	POP	DE
	LD	A,D			;TRACK
	PUSH	DE
	CALL	HEXOUT			;PRINT TRACK NUMBER
	LD	DE,MSG17
	CALL	PRNTŠ	LD	A,(IY)			;SECTOR
	CALL	HEXOUT			;PRINT SECTOR NUMBER
	LD	DE,MSG18
	CALL	PRNT
	LD	A,(STATUS)		;GET STATUS
	CALL	HEXOUT			;PRINT STATUS
;
;ASK USER FOR HELP TO DECIDE WHAT TO DO NEXT
;
ERRIN:	LD	DE,MSG20
	CALL	PRNT
	CALL	CHARIN
	OR	A
	JP	Z,ABORT			;EXIT OPTION
	CP	'S'			;SKIP?
	JP	Z,SKIP
	CP	'R'			;RETRY?
	JR	NZ,ERRIN
;RETRY WRITE AND THEN READ VERIFY AGAIN
	POP	DE
	CALL	RESUMESCREEN		;RESTORE SCREEN
	XOR	A
	LD	(SIDE),A		;SET SIDE TO ZERO
	CALL	SELSIDE			;SELECT SIDE,DENSTY
	LD	IY,(IYSAVE)		;RESTORE IY
	JP	WRITE			;WRITE THIS TRACK OVER
;SKIP TO NEXT TRACK
SKIP:	POP	DE
	CALL	RESUMESCREEN
	XOR	A
	LD	(SIDE),A		;RESET SIDE TO ZERO
	CALL	SELSIDE			;AND SELECT IT
	JP	SKIPTONEXT
;
;
SELSIDE:
	LD	A,(SIDE)		;GET SIDE NUMBER
	RLC	A         
	RLC	A
	LD	B,A
	LD	A,(DRIVENO)
	OR	B

	IF	MINI
	OR	018h			;SELECT DOUBLE DENSITY
;
	ELSE
	LD	B,A
	LD	A,D
	OR	A
	JR	Z,TRK0     
	LD	A,(DENS)
	CP	DD
	JR	NZ,NODD
	LD	A,08			;SELECT DOUBLE DENSITY
	JR	SESIDEŠNODD:
TRK0º	XOR	A			;SELECT SINGLE DENSITY
SESIDE:	ADD	A,B
	ENDIF

	OUT	(WAIT),A		;TELL FDC
	RET
;
;DISK WRITE ERROR
;
ERRMSG:	DB	CR,LF,'WRITE ERROR: $'
;
WRERROR:
	LD	(IYSAVE),IY
	PUSH	DE
	PUSH	AF
	LD	DE,ERRMSG
	CALL	PRNT
	POP	AF
	CALL	DETERMERR
	JP	USERINTERFACE
;
DETERMERR:
	PUSH	DE
	LÄ	B,A
	AND	80H
	JR	Z,D1
	LD	DE,MSG25
	CALL	PRNT			;DRIVE NOT READY
	JR	EXITD
D1:	LD	A,B
	AND	40H
	JR	Z,D2
	LD	DE,MSG26
	CALL	PRNT			;WRITE PROTECT
	JR	EXITD
D2:	LD	A,B
	AND	20H
	JR	Z,D3
	LD	DE,MSG27
	CALL	PRNT			;WRITE FAULT
	JR	EXITD
D3:	LD	A,B
	AND	10H
	JR	Z,D4
	LD	DE,MSG28
	CALL	PRNT			;RECORD NOT FOUND
	JR	EXITD
D4:	LD	A,B
	AND	8
	JR	Z,D5
	LD	DE,MSG29
	CALL	PRNT			;CRC ERROR
	JR	EXITD
D5:	LD	A,BŠ	AND	4
	JR	Z,D6
	LD	DE,MSG30
	CALL	PRNT
	JR	EXITD
D6:	LD	A,B
	AND	2
	JR	Z,D7
	LD	DE,MSG31		;DATA REQUEST
	CALL	PRNT
D7:
EXITD:	POP	DE
	RET
;
HEXOUT:
	PUSH	AF
	SRL	A
	SRL	A
	SRL	A
	SRL	A
	CALL	OUT
	POP	AF
OUT:	AND	0FH
	ADD	A,90H
	DAA 
	ADC	A,40H
	DAA
	CALL	CHAROUT
	RET
;
SPFLAG:	DB	0
READSECS:
	DB	0
RTRY:	DB	0
IYSAVE:	DW	0
IXSAVE:	DW	0
IXTRK1ON:
	DW	0
IYTRK1ON:
	DW	0
IX0SAVE:
	DW	0
IY0SAVE:
	DW	0
MAXTRKS:
	DB	0
MAXSECS:
	DB	0
STATUS:	DB	0
SYSFLAG:
	DB	0
SIDE:	DB	0
SIDED:	DB	0
DENS:	DB	0
DENDNE:	DB	0
DENSCODE:
	DB	0E5H
DRIVENO:
	DB	0
;
;
;
;MESSAGES
MSG:	DB	CR,LF,'FORMATTING',CR,LF,'$'
MSG1:
	IF	NOT MINI
	DB	'FMT8 3.1'
	ENDIF

	IF	MINI

	IF	FORTY8
	DB	'FMT548 3.1'
	ELSE
	DB	'FMT596 3.1'
	ENDIF

	ENDIF

	DB	CR,LF,'$'
MSG4:	DB	CR,LF,'Enter Disk Drive To Be Formatted (0-3) : $'
MSG5:	DB	CR,LF,'Enter Density, Single or Double  (S,D) : $'
MSG6:	DB	CR,LF,'Format Single or Double Sided    (S,D) : $'
MSG7:	DB	CR,LF,'Format System Tracks only        (Y,N) : $'
MSG77:	DB	CR,LF,'Supress Format Verification      (Y,N) : $'
MSG8:	DB	CR,LF,'Insert Diskett Into Drive $'
MSG9:	DB	' And Press The Return Key $'
MSG10:	DB	CR,LF,'Formatting Complete$'
MSG11:	DB	CR,LF,'Option (CR to Exit, C to Continue) : $'
MSG12:	DB	CR,LF,'Option (CR for Same Parameters, N for New Parameters) : $'
MSG13:	DB	CR,LF,LF,'                FORMATTING & VERIFYING$'
MSG14:	DB	CR,LF,   '                         TRACK',LF,'$'
MSG147:	DB	CR,      '                          $'
MSG148:	DB	CR,LF,LF,'                  FORMATTING TRACK',LF,'$'
MSG155:	DB	CR,LF,'SIDE= $'
MSG16:	DB	', TRACK= $'
MSG17:	DB	', SECTOR= $'
MSG18:	DB	', STATUS= $'
MSG19:	DB	CR,LF,LF,'FATAL READ VERIFY ERROR DETECTED: $'
MSG20:	DB	CR,LF,LF,'OPTION (CR to Exit, S to Skip, R to Retry) ? $'
;
MSG25:	DB	'DRIVE NOT READY$'
MSG26:	DB	'DISK IS WRITE PROTECTED$'ŠMSG27:	DB	'WRITE FAULT$'
MSG28:	DB	'RECORD NOT FOUND$'
MSG29:	DB	'CRC ERROR$'
MSG30:	DB	'LOST DATA$'
MSG31:	DB	'DATA REQUEST$'
ABTMSG:	DB	CR,LF,'FORMATTING ABORTED$'
;
;CONTROL STRUCTURES SECTION
;
;MINI FLOPPY WRITE SECTOR SEQUENCE CONTROL
MINISEQ0:
	DB	1,2,3,4

MINISEQ:
	DB	1,3,2,4			;FOR WRITE
	DB	1,2,3,4
;
;8 INCH FLOPPY WRITE SECTOR SEQUENCE CONTROL
;(SINGLE DENSITY)
SDSEQ:
 	DB	1,2,3,4,5,6,7,8,9,10,11,12,13
	DB	14,15,16,17,18,19,20,21,22,23,24,25,26
;FOR READ
	DB	1,3,5,7,9,11,13,15,17,19,21,23,25,2,4,6
	DB	8,10,12,14,16,18,20,22,24,26
; (DOUBLE DENSITY)
DDSEQ:	DB	1,4,7,2,5,8,3,6		;FOR WRITE
	DB	1,7,5,3,4,2,8,6		;FOR READ
;
;SINGLE DENSITY DISKETT FORMATTING CONTROL
SDCONTROL:
	DB	40,0FFH			;PRE INDEX
	DB	6,00                
	DB	1,0FCH			;INDEX MARK
	DB	26,0FFH			;GAP1 POST INDEX
	DB	RPT			;PROGRAM DESIGNED BEGINNING OF
					;A REPEAT FUNCTION
	DB	6,00			;SECTOR START ZEROS
	DB	1,0FEH			;ID ADDRESS MARK
;MISSING THREE BYTES ARE FILLED AT RUN TIME
	DB	1,00			;SECTOR LENGTH
	DB	1,0F7H			;CRC'S
	DB	11,0FFH			;POST CRC
	DB	6,00			;POST CRC
	DB	1,0FBH			;DATA ADDRESS MARK
	DB	128,0E5H		;DATA FIELD
	DB	1,0F7H			;CRC'S
	DB	27,0FFH			;POST CRC
	DB	ENDRPT			;END OF REPEAT FUNCTION
	DB	200,0FFH		;END OF TRACK GAP4Š	DB	200,0FFH		;
	DB	200,0FFH		;
	DB	168,0FFH		;
	DB	ENDTRK
;
;
;DOUBLE DENSITY DISKETT FORMATTING CONTROL
;
;       ***** MOST OF THE COMMENTS USED ABOVE APPLY HERE AS WELL *****
;
DDCONTROL:
	DB	80,04EH
	DB	12,00
	DB	3,0F6H
	DB	1,0FCH
	DB	50,04EH
	DB	RPT
	DB	12,00
	DB	3,0F5H
	DB	1,0FEH
; MISSING BYTES ARE FILLED AT RUN TIME
	DB	1,03
	DB	1,0F7H
	DB	22,04EH
	DB	12,00
	DB	3,0F5H
	DB	1,0FBH
	DB	128,0E5H
	DB	128,0E5H
	DB	0,0E5H			;0 COUNT = 256
	DB	0,0E5H
	DB	0,0E5H
	DB	1,0F7H
	DB	66,04EH
	DB	ENDRPT
	DB	200,04EH
	DB	200,04EH
	DB	ENDTRK
;
IBUFF:	DS	80
;
BUFFER:	DB	0

	END	START
