	TITLE	8" FLOPPY DISK FORMAT UTILITY FOR JADE DD CONTROLLER
	LIST	NOCOND
;***************************************************************************
;
;   JADE DOUBLE D DISK FORMAT PROGRAM
;
;***************************************************************************
;
;   FORMATn is a system utility which provides a means to write a single or
; double density format on any of the drives accessed by the DD controller. 
;
;***************************************************************************
;
;  KNOWN BUGS:
;
;  *	LEAVES LOGON DISABLED ON FDC.
;
;	REVISION STATUS:
;
; X.1 - 30 DEC 86   GRH
;	Fix bug causing display of side 1 sector number > 32768.
;	Remove sector skew for double density in order to get failure data.
;
; X.2 - 31 DEC 86   GRH
;	Reinstall double density skew factor.
;	Add precomp thresholds to ID sector data & add logon to track 0
;	 format after writing ID sector
;
; 1.0 -	8 FEB 81   GRH
;	RELEASE
;
; 2.00	5 AUG 88   GRH
;	Change Format command philosophy to table-driven. Change FORMAT8 to
;	 comply with new DCM8.
;	Correct bug in DSDD48 which defined disk as 896k when it was only
;	 894k.
;	Change ID sector to reflect new format.
;	Implement BIOS call for IOPB execution.
;
; 2.01	6-9-90   GRH
;	Fix bug in main loop which caused drive logon to remain disabled
;	 when returned to BIOS.
;
VERSN	EQU	'01'	;CHANGE HERE FOR SIGN-ON CHANGE
;
;***************************************************************************

	SUBTTL	DECLARATIONS
;===========================================================================
;
;	ASSEMBLY CONTROL
;
;===========================================================================
FALSE	EQU	0
TRUE	EQU	NOT FALSE
;
DIAG	EQU	TRUE
;
MINVERS	EQU	301		;MINIMUM BIOS VERSION FOR COMPATABILITY
;
DSIZE	EQU	8


;===========================================================================
;
;*INCLUDE DISKS.DEF
;*INCLUDE COMIOPB.DEF
;
;===========================================================================
	LIST	OFF
*INCLUDE DISKS.DEF
*INCLUDE COMIOPB.DEF
	LIST	ON


;===========================================================================
;
;   CONSTANTS
;
;===========================================================================
CTRLC:	EQU	3		;REQUEST REBOOT CPM
LF:	EQU	0AH		;LINE FEED
CR:	EQU	0DH		;CARRIAGE RETURN
BS	EQU	08H		;BACKSPACE
;
NDRVS	EQU	4		;MAX NUMBER OF DRIVES
SECSZ:	EQU	128		;128 BYTES PER SECTOR


;===========================================================================
;
;	LOCATIONS
;
;===========================================================================
REBOOT:	EQU	0		;REBOOT ADDR
BIOS	EQU	28H		;BIOS FUNCTION RESTART VECTOR
TPA:	EQU	100H		;TRANSIENT PROGRAM AREA


;===========================================================================
;
;   BDOS CALL VECTORS
;
;===========================================================================
WBOOT	EQU	0000H		;SYSTEM WARM BOOT
BDOS:	EQU	0005H		;SYSTEM CALL ADDR


;===========================================================================
;
;   BIOS CALL DATA
;
;===========================================================================
RETVERS	EQU	0	;RETURN BIOS VERSION # IN HL
XIOPBC	EQU	2	;EXECUTE IOPB IN DE FUNCTION


	SUBTTL	MACROS
;;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
;;
;;	GENERATE THE TRANSLATE TABLE
;;
;;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
GXLATE	MACRO	#SECTORS, #SKEW
	LIST	OFF
NXTSEC	DL	1			;;START WITH SECTOR 1
LOWEST	DL	1
;;
	REPT	#SECTORS		;;ONCE FOR EACH SECTOR
	LIST	ON
	DB	NXTSEC
	LIST	OFF
NXTSEC	DL	NXTSEC + #SKEW		;;ADD IN SKEW FACTOR
;;
	IF	NXTSEC > #SECTORS	;;CHECK FOR OVERFLOW
NXTSEC	DL	NXTSEC - #SECTORS
;;
	IF	NXTSEC <= LOWEST	;;CHECK FOR REPEAT
NXTSEC	DL	LOWEST + 1
LOWEST	DL	NXTSEC
	ENDIF
	ENDIF
;;
	ENDM
	LIST	ON
	ENDM


	SUBTTL	MAIN PROGRAM
	ORG	TPA
;---------------------------------------------------------------------------
;
;   PROGRAM ENTRY POINT
;
;---------------------------------------------------------------------------
	JP	INIT		;INITIALIZE


;###########################################################################
;
;	COPYRIGHT NOTICE
;
;###########################################################################
SIGNON:	DB	'Jade Double D 8" disk format Utility   Ver 2.'
	DB	HIGH VERSN,LOW VERSN,CR,LF
	DB	'Copyright (c) 1983,1986,1987,1988   GRH Enterprises'
	DB	'$'


;---------------------------------------------------------------------------
;
;	MAIN PROGRAM CONTINUES
;
;---------------------------------------------------------------------------
INIT:
;
;   SET UP LOCAL STACK
;
	LD	SP,(BDOS + 1)	
	DEC	SP
	DEC	SP
;
;   OUTPUT SIGNON MESSAGE
;
	LD	DE,SIGNON	;OUTPUT MESSAGE
	CALL	MSGOT
;
;   IF BIOS CALL VECTOR NOT IN MONITOR THEN IMPLEMENTED
;
	LD	A,(BIOS + 2)
	CP	A,0F8H
	JR	C,BIOSVOK
;
;   ELSE BIOS FUNCTION CALL NOT IMPLEMENTED, ABORT
;
BIOSERR:
	LD	DE,BIOSM
	CALL	MSGOT
	JP	0
;
;
;   BIOS VECTOR OK, IS VERSION OK
;
BIOSVOK:
	LD	C,RETVERS
	RST	BIOS
;
	LD	DE,MINVERS	;MUST BE >= THIS 
	OR	A,A
	SBC	HL,DE
;
	JR	C,BIOSERR
;
;
;   OUTPUT MENU
;
FUNBG:	LD	DE,MSGFL	;OUTPUT FUNCTION LIST
	CALL	MSGOT
;
;   GET FUNCTION SELECTION FROM USER
;
	CALL	CNSIN		;GET CONSOLE CHAR
	LD	(LTRSE),A	;SAVE CHAR FOR ERROR MESSAGE
;
;   CHECK FOR RANGE
;
	SUB	A,'0'
	CP	A,NFUNCS
	JR	C,FUNOK
;
;   UNKNOWN FUNCTION, ERROR
;
FUNERR:	LD	DE,MSGSE	;ELSE OUTPUT ERROR MSG
	CALL	MSGOT
;
;   IF USER WANTS TO CONTINUE THEN REPEAT
;
	CALL	CNSIN
	CP	A,'Y'
	JR	NZ,FUNBG		;REPEAT
;
;   ELSE RETURN TO CP/M
;
	JP	0
;
;
;   FUNCTION RANGE OK, COMPUTE EXECUTION ADDRESS
;
FUNOK:
	LD	HL,FUNTBL
	LD	E,A
	LD	D,0
	ADD	HL,DE
	ADD	HL,DE
	LD	E,(HL)
	INC	HL
	LD	D,(HL)
	LD	HL,FUNRET	;SET UP RETURN ADDRESS
	PUSH	HL
	EX	DE,HL
	JP	(HL)		;EXECUTE COMMAND
;
;
;   FUNCTIONS RETURN HERE, RE-ENABLE LOGON CAPABILITY FOR THIS DRIVE
;
FUNRET: LD	IX,IOPB		;USE COMMON IOPB
;
	LD	(IX + PB_CMDO),PB_STDKC
;
	LD	HL,SECBUF	;USE SECTOR BUFFER TO RETURN PARAMETERS
	LD	(IOPB + PB_DMAO),HL
;
	LD	(IX + PB_FLGO),3	;RETURN DATA AND ENABLE LOGON
	CALL	EXIOPBX
;
;   NEXT OPTION
;
	JP	FUNBG
;
;
;   NO SUPPORTED FUNCTION STUB
;
NOFUN:	POP	HL		;RESTORE STACK
	JR	FUNERR		;TELL ERROR


;############################################################################
;
;   FUNCTION ADDRESS TABLE
;
;############################################################################
;
FUNTBL:	DW	FUN0		;SINGLE SIDED SINGLE DENSITY IBM 3740	(241K)
	DW	FUN1		;SINGLE SIDED SINGLE DENSITY 26SPT JADE	(241K)
	DW	FUN2		;SINGLE SIDED DOUBLE DENSITY 48SPT JADE	(440K)
	DW	FUN3		;DOUBLE SIDED SINGLE DENSITY 26SPT	(480K)
	DW	FUN4		;DOUBLE SIDED DOUBLE DENSITY 48SPT JADE	(880K)
	DW	NOFUN
	DW	NOFUN
	DW	NOFUN
	DW	NOFUN
	DW	CUSTOM
NFUNCS	EQU	($ - FUNTBL) / 2


	SUBTTL	FORMAT FUNCTIONS
;---------------------------------------------------------------------------
;
;   SELECT PARAMETERS
;
;---------------------------------------------------------------------------
;
;
;   FUNCTION 0: IBM 3740, SINGLE SIDED, SINGLE DENSITY, 26 SPT
;
FUN0:	LD	HL,SSSD40ID	;IBM 3740 SSSD 26SPT
	JR	DO48
;
;   FUNCTION 1: JADE SINGLE SIDED, SINGLE DENSITY, 26SPT
;
FUN1:	LD	HL,SSSDID
	JR	DO48
;
;
;   FUNCTION 2: JADE SINGLE SIDED, DOUBLE DENSITY, 48 SPT
;
FUN2:	LD	HL,SSDD48ID	;JADE FORMAT SSDD 48SPT 
	JR	DO48
;
;
;   FUNCTION 3: DOUBLE SIDED, SINGLE DENSITY, 26 SPT
;
FUN3:	LD	HL,DSSDID	;JADE DSSD 26SPT
	JR	DO48
;
;
;   FUNCTION 4: JADE DOUBLE SIDED, DOUBLE DENSITY, 48 SPT
;
FUN4:	LD	HL,DSDD48ID	;JADE FORMAT DSDD 48SPT
;
;   COMMON CODE
;
DO48:
;
;   OVERLAY DPB DATA
;
	LD	DE,IDSIMG + ID_SPTO
	LD	BC,ID_DPBSZ
	LDIR
;
;   OVERLAY DISK FORMAT DATA
;
	LD	DE,IDSIMG + ID_FLGO
	LD	BC,ID_FSIZE
	LDIR
;
;   FALL INTO FORMAT DISK
;


;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	FORMAT DISK FUNCTION
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
FMTDSK:
;
;   SELECT DRIVE
;
	CALL	SELDR		;SELECT DRIVE
	RET	C		;ERR- RESELECT
;
;   SET UP IOPB FOR 1ST TRACK
;
	LD	A,0		;SET TRACK #
	LD	(IOPB + PB_TRKO),A
;
;   MAIN LOOP
;
FMTDSKLP:
;
;   SIDE 0
;
	LD	HL,1
	LD	(IOPB + PB_SECO),HL
;
;   FORMAT TRACK
;
	CALL	FMTTRK
	RET	NZ		;IF ERROR THEN RETURN
;
;   IF NOT ON TRACK 0, NO DESCRIPTOR SECTOR WRITE
;
	LD	A,(IOPB + PB_TRKO)
	OR	A,A
	JP	NZ,FMTDSK1
;
;   ELSE IF NOT 3740 THEN WRITE DESCRIPTOR SECTOR
;
	LD	A,(IDSIMG + ID_DTYPE)
	OR	A,A		;3740 == 0
	JR	NZ,FMTWID
;
FMTDSK1:
;
;   DO SECOND SIDE IF NEEDED
;
	LD	A,(IDSIMG + ID_HEADS)
	CP	A,1
	JR	Z,NO2ND
;
	LD	A,(IOPB + PB_TRKO)	;FETCH TRACK SECTOR COUNT
	CALL	GETSPT
;
	INC	A			;ONE PAST LAST SECTOR ON SIDE 0
	LD	(IOPB + PB_SECO),A
;
	CALL	FMTTRK
	RET	NZ
;
NO2ND:
;
;   NEXT TRACK
;
	LD	A,(IOPB + PB_TRKO)
	INC	A
	LD	(IOPB + PB_TRKO),A
;
;   IF NOT PAST LAST CYLINDER THEN REPEAT
;
	LD	HL,IDSIMG + ID_CYLS
	CP	A,(HL)
	JR	C,FMTDSKLP
;
;   FORMAT DONE, GO TEST FOR READ ERRORS
;
	CALL	CHECK		;CHECK FOR READ ERRORS
	JP	FMTDSK		;READY FOR ANOTHER DISK
;
;
;   WRITE ID SECTOR
;
FMTWID:	
	CALL	WRTID		;WHILE WE'RE HERE, WRITE ID SECTOR
	RET	NZ		;ERR
	JP	FMTDSK1


;---------------------------------------------------------------------------
;
;	CUSTOM FORMATTER
;
;---------------------------------------------------------------------------
CUSTOM:
	RET

	SUBTTL	PROCEDURES & FUNCTIONS
;***************************************************************************
;
;	MESSAGE OUTPUT PROCEDURE
;	ENTRY-	DE= PTR TO '$' TERMINATED TEXT
;	EXIT -	?
;
;***************************************************************************
PUTS:
MSGOT:
	LD	C,9		;PRINT STRING FUNCTION
	JP	BDOS


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	CONSOLE INPUT FUNCTION
;	EXIT -	A= CHAR AND 7FH
;		BC, DE, HL= ?
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CNSIN:
;
;   GET CHARACTER
;
	LD	C,1		;CONSOLE READ FUNCTION #
	CALL	BDOS
;
;   MASK BIT 7
;
	AND	A,7FH
;
;   CONVERT LOWER CASE TO UPPER CASE
;
	CP	A,'a'
	RET	C
	CP	A,'z' + 1
	RET	NC
	AND	A,5FH
	RET


;***************************************************************************
;
;	CONSOLE OUTPUT PROCEDURE
;	ENTRY-	E= CHAR
;
;***************************************************************************
CNSOT:	LD	C,2		;CONSOLE OUTPUT FUNCTION #
	JP	BDOS


;***************************************************************************
;
;	PUT DECIMAL PROCEDURE
;	ENTRY-	HL= VALUE TO OUTPUT
;	EXIT -	HL, DE, BC, A= ?
;
;***************************************************************************
PUTD:
;
;   PUT DATA IN PROPER REGISTERS
;
	EX	DE,HL
;
;   INIT DIGITS TO 0
;
	LD	HL,UNIT
	LD	B,5
SET0:	LD	(HL),0
	INC	HL
	DJNZ	SET0
;
;   PROCESS TENTHOUSANDS DIGIT
;
	DEC	HL
	LD	BC,-10000
	CALL	DECDIG
;
;   PROCESS THOUSANDS DIGIT
;
	LD	BC,-1000
	CALL	DECDIG
;
;   PROCESS HUNDREDS DIGIT
;
	LD	BC,-100
	CALL	DECDIG
;
;   PROCESS TENS DIGIT
;
	LD	BC,-10
	CALL	DECDIG
;
;   REMAINDER IS UNITS DIGIT
;
	LD	(HL),E
;
;   OUTPUT DIGITS WITH LEADING SPACES
;
	LD	HL,TTHOU	;SET PTR
	LD	BC,500H		;5 DIGITS, NOCONVERT 0 TO SPACE = FALSE
;
NXTDEC:	LD	A,(HL)		;FETCH DIGIT
	DEC	HL		;NEXT DIGIT
	ADD	A,'0'		;CONVERT TO ASCII
	CP	A,'0'		;IF NOT 0 THEN NOCONVERT TO SPACE = TRUE
	JR	NZ,FIRST
;
	INC	C		;ELSE IF FLAG != 0 THEN DIGIT OCCURRED
	DEC	C
	JR	NZ,OUTNUM
;
	LD	A,B		;AT LEAST ONE 0
	DEC	A
	LD	A,'0'
	JR	Z,OUTNUM
;
	LD	A,' '		;PAD WITH LEADING BLANKS UNTIL DIGIT
	JR	OUTNUM
;
;   NON-0 DIGIT OCCURRED, FLAG = TRUE
;
FIRST:	INC	C
;
;   OUTPUT DIGIT
;
OUTNUM:	PUSH	HL
	PUSH	BC
	PUSH	AF
	LD	E,A
	LD	C,2
	CALL	BDOS
	POP	AF
	POP	BC
	POP	HL
	DJNZ	NXTDEC
;
;   DONE ALL 5 DIGITS
;
	RET


;***************************************************************************
;
;	OUTPUT CRLF PROCEDURE
;	EXIT -	HL, DE, BC, AF= ?
;
;***************************************************************************
CRLF:	LD	DE,CRLFM
	JP	PUTS


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	CREATE DECIMAL DIGIT FUNCTION
;	ENTRY-	HL= PTR TO PLACE TO STORE DIGIT
;		DE= VALUE TO CONVERT
;		BC= DIVISOR FOR DIGIT
;	EXIT -	HL= PTR TO NEXT DIGIT
;		DE= REMAINDER
;		BC= -BC
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DECDIG:	PUSH	HL
	EX	DE,HL
	ADD	HL,BC
	JR	NC,ADDIT
;
	EX	DE,HL
	POP	HL
	INC	(HL)
	JR	DECDIG
;
;
ADDIT:	LD	A,C
	CPL
	LD	E,A
	LD	A,B
	CPL
	LD	D,A
	INC	DE
	ADD	HL,DE
	EX	DE,HL
	POP	HL
	DEC	HL
	RET

UNIT:	DS	4
TTHOU:	DS	1


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	WRITE ID SECTOR FUNCTION
;	EXIT -	AF= /0: ERROR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
WRTID:
;
;   SET UP IOPBs
;
	LD	A,(IOPB + PB_DRVO)
	LD	(WIDIOPB + PB_DRVO),A
;
	LD	HL,IDSIMG
	LD	(WIDIOPB + PB_DMAO),HL
;
	LD	HL,ID_SECT	;SET ID SECTOR
	LD	(WIDIOPB + PB_SECO),HL
;
;   EXECUTE THE IOPB
;
	LD	IX,WIDIOPB	;PASS PTR TO IOPB
	CALL	EXIOPBX
	RET	Z
;
;   ERROR ENCOUNTERED, TELL IT
;
	LD	DE,MSGNC	;ELSE OUTPUT ERROR & RETURN
	CALL	MSGOT
	XOR	A,A
	DEC	A
	RET


;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	FORMAT TRACK FUNCTION
;	EXIT -	AF= /0: ERROR
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
FMTTRK:
;
;   SELECT DISK FORMAT TABLE BASED ON SECTOR SIZE & TRACK DENSITY FLAGS
;
	LD	A,(IOPB + PB_TRKO)	;FETCH SECTOR SIZE
	CALL	GETSSZ
;
	AND	A,3			;MOULO 4
	ADD	A,A			;X2
	LD	L,A			;SAVE
;
	LD	A,(IOPB + PB_TRKO)	;SELECT CORRECT DENSITY FLAG
	CP	A,1
	LD	A,(IDSIMG + ID_FLGO)	;PREFETCH DENSITY FLAGS
	JR	Z,FMT1
;
	JP	NC,FMTDT

	ADD	A,A		;SHIFT PROPER DENSITY BIT INTO BIT 3
;
FMT1:	ADD	A,A
;
FMTDT:	ADD	A,A
;
;   IF DOUBLE DENSITY THEN ADD 4
;
	AND	A,8
	OR	A,L		;ADD IN SECTOR SIZE OFFSET
;
	LD	HL,TBLPTRS	;FETCH DATA PTR FROM TABLE
	ADD	A,L
	LD	L,A
	LD	A,0
	ADC	A,H
	LD	H,A
	LD	A,(HL)
	INC	HL
	LD	H,(HL)
	LD	L,A
;
;   GOT FORMAT TABLE, SET XFER PTR TO IT
;
	LD	(IOPB + PB_DMAO),HL
;
;   CALCULATE CHECKSUM
;
	LD	B,127		;SAVE LAST BYTE FOR -CHECKSUM
	XOR	A,A		;CHECKSUM = 0
;
FMTCKS:	ADD	A,(HL)		;ADD TO BYTE
	INC	HL		;POINT TO NEXT BYTE
	DJNZ	FMTCKS		;IF --COUNT != 0 THEN REPEAT
;
;   STORE -CHECKSUM IN LAST BYTE
;
	NEG
	LD	(HL),A
;
;   FORMAT THE TRACK
;
	LD	DE,FMTGM	;OUTPUT FORMATTING MESSAGE
	CALL	MSGOT
;
	LD	HL,(IOPB + PB_TRKO)
	CALL	PUTD
;
	LD	DE,ENDEQM
	CALL	MSGOT
;
	LD	IX,IOPB
	LD	(IX + PB_CMDO),PB_FRMTC		;INSURE IS FORMAT COMMAND
	CALL	EXIOPBX		;FORMAT TRACK
;
;   TELL LAST PADDING
;
	PUSH	AF
	LD	HL,(IOPB + PB_ST2O)
	CALL	PUTD
;
	POP	AF
	RET	Z		;IF NO ERROR THEN RETURN
;
;   ERROR- TELL SO
;
	LD	DE,MSGNC	;ELSE OUTPUT ERROR MSG
	CP	A,PB_SEEK	;IF SEEK ERROR THEN DIFFERENT MESSAGE
	JR	NZ,FTE1
;
	LD	DE,SKERM
;
FTE1:	CALL	MSGOT
	XOR	A,A		;RETURN ERROR FLAG
	DEC	A
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	SELECT DRIVE FUNCTION
;	EXIT -	CF= ERROR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SELDR:
;
;   OUTPUT PROMPT
;
	LD	DE,MSGFD
	CALL	MSGOT
;
;   GET RESPONSE
;
	CALL	CNSIN
;
;   IF RETURN THEN EXIT
;
	CP	A,CR		;IF RETURN THEN EXIT
	SCF
	RET	Z
;
;   SAVE DRIVE LETTER IN MESSAGES
;
	LD	(DRLTR),A	;ELSE SAVE DRIVE LETTER & TEST FOR LEGAL
	LD	(LTRSE),A
;
;   TEST FOR LEGAL DRIVE {0..3}
;
	SUB	A,'0'
	CP	A,4
	JR	C,NMBRD		;IF LEGAL THEN CONTINUE
;
;   ILLEGAL DRIVE, REPEAT
;
	LD	DE,MSGSE	;PRINT SELECT ERROR MESSAGE
	CALL	MSGOT
	JR	SELDR
;
;
;	DRIVE SELECTED
;
NMBRD:
	LD	(IOPB + PB_DRVO),A
	LD	(WIDIOPB + PB_DRVO),A
	LD	(RDIOPB + PB_DRVO),A
;
;   PAUSE FOR READY
;
	LD	DE,MSGXX	;PRINT TYPE CR WHEN READY MSG
	CALL	MSGOT
	CALL	CNSIN		;IF NOT CR THEN REPEAT
	CP	A,CR
	JR	NZ,SELDR
;
;   TELL CONTROLLER WHAT TYPE DISK WE'RE DOING
;
	LD	IX,IOPB
	LD	(IX + PB_CMDO),PB_STDKC	;SET DISK PARAMETERS CMD
;
	LD	HL,IDSIMG + ID_FLGO	;SAME AS ID SECTOR DATA
	LD	(IOPB + PB_DMAO),HL
;
	LD	(IX + PB_FLGO),0	;SET PARAMS & DISABLE LOGON
;
	JP	EXIOPBX


;***************************************************************************
;
;   CHECK FUNCTION CHECKS ALL TRACKS BY READING BACKWARD FROM LAST TRACK
;
;***************************************************************************
CHECK:
;
;   SET UP
;
	LD	HL,(IOPB + PB_TRKO)	;START WITH LAST TRACK FORMATTED
	DEC	HL
	LD	(RDIOPB + PB_TRKO),HL
;
	LD	IX,RDIOPB
;
;   NEW LINE
;
	CALL	CRLF
;
;   ALL SET TO DO TRACK, SET TRACK SIZE
;
RDTRKL:
	LD	HL,SSXLATE	;ASSUME SINGLE SIDED
	LD	(XLATPTR),HL
;
	LD	A,(RDIOPB + PB_TRKO)	;FETCH SECTORS PER TRACK
	CALL	GETSPT
	LD	L,A
;
	LD	A,(IDSIMG + ID_HEADS)	;IF DOUBLE SIDED THEN SECTORS *= 2
	CP	A,1
	LD	A,L		;RESTORE SECTORS
	JR	Z,SETNSEC
;
;   DOUBLE SIDED, DOUBLE SECTORS & XLATION TABLE
;
	ADD	A,A
;
	LD	HL,DSXLATE
	LD	(XLATPTR),HL
;
SETNSEC:
	INC	A		;OFFSET FOR TEST
	LD	(NSECTS),A
;
;   START WITH 1ST SECTOR
;
	LD	A,1		;START WITH 1ST SECTOR
;
;   READ LOOP
;
RDLP:
;
;   CHECK FOR SECTOR TRANSLATION
;
	LD	(CURSEC),A		;SAVE THE CURRENT SECTOR
;
	LD	A,(IDSIMG + ID_FLGO)	;FETCH FLAGS
	LD	L,A
	LD	A,(RDIOPB + PB_TRKO)	;FETCH TRACK
	CP	A,1			;IF TRACK 0 THEN TEST BIT 0
	JR	C,RDTST
	JR	Z,RDTST1		;IF TRACK 1 THEN TEST BIT 1
;
	SRL	L			;ELSE TEST BIT 2
;
RDTST1:	SRL	L
;
RDTST:	BIT	0,L			;IF DOUBLE DENSITY THEN NO XLATE
	LD	A,(CURSEC)
	JR	NZ,RDSOK
;
;   IF NOT 128 BYTE SECTORS THEN NO XLATE
;
	LD	L,A		;SAVE SECTOR
	LD	A,(RDIOPB + PB_TRKO)
	CALL	GETSSZ
	OR	A,A
	LD	A,L		;RESTORE SECTOR
	JP	NZ,RDSOK
;
;   ELSE XLATE SECTOR
;
	LD	HL,(XLATPTR)		;POINT TO TABLE
	DEC	A			;{1..N} -> {0..N-1}
	ADD	A,L			;CALCULATE OFFSET TO SECTOR
	LD	L,A
	LD	A,0
	ADC	A,H
	LD	H,A
	LD	A,(HL)			;FETCH TRANSLATED SECTOR
;
;   SET SECTOR
;
RDSOK:	LD	(RDIOPB + PB_SECO),A	;SAVE CURRENT SECTOR
;
;   CHECK CONSOLE FOR ABORT
;
	LD	C,11		;GET CONSOLE STATUS
	CALL	BDOS
;
	OR	A,A
	JP	Z,NOABRT
;
	LD	C,1		;FLUSH CONSOLE CHAR BEFORE ABORT
	CALL	BDOS
;
	LD	DE,ABRTDM	;OUTPUT ABORTED MESSAGE
	JP	MSGOT
;
;
NOABRT:
;
;   IF LAST SECTOR OF TRACK THEN DONE
;
	LD	HL,NSECTS
	LD	A,(CURSEC)
	CP	A,(HL)
	JR	NC,TDONE
;
;   OUTPUT TESTING TRACK MESSAGE
;
	LD	DE,TSTGM
	CALL	MSGOT
;
	LD	HL,(RDIOPB + PB_TRKO)
	CALL	PUTD
;
;   OUTPUT SIDE NO.
;
	LD	DE,SIDEM
	CALL	MSGOT
;
	LD	A,(RDIOPB + PB_TRKO)
	CALL	GETSPT
	PUSH	AF			;SAVE SPT FOR LATER
;
	LD	HL,RDIOPB + PB_SECO
	CP	A,(HL)			;CF= SIDE 1, NC= SIDE 0
	PUSH	AF			;SAVE SIDE FLAG (CF)
;
	LD	L,0
	RL	L
	LD	H,0
	CALL	PUTD
;
;   OUTPUT SECTOR
;
	LD	DE,SECM
	CALL	MSGOT
;
	POP	AF		;SIDE FLAG (CF)
	POP	HL		;H: SPT
	LD	A,(RDIOPB + PB_SECO)	;IF SIDE == 0 THEN SECTOR OK
	LD	L,A
	JP	NC,RDSOK2
;
	SUB	A,H		;ELSE SECTOR -= SPT
	LD	L,A
;
RDSOK2:	LD	H,0
	CALL	PUTD
;
;   EXECUTE THE READ
;
	LD	IX,RDIOPB
	CALL	EXIOPBX
;
	LD	DE,ERM			;IF READ ERROR THEN OUTPUT ERROR
	CALL	NZ,MSGOT	
;
;   NEXT SECTOR & REPEAT
;
	LD	A,(CURSEC)
	INC	A
	JP	RDLP
;
;
;   TRACK IS DONE, NEXT TRACK
;
TDONE:	LD	A,(RDIOPB + PB_TRKO)
	DEC	A
	LD	(RDIOPB + PB_TRKO),A
;
;   IF NEXT TRACK < 0 THEN RETURN
;
	JP	P,RDTRKL
;
	LD	DE,OKM
	JP	MSGOT


;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	EXECUTE IOPB FUNCTION
;	ENTRY-	IX= IOPB PTR
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;   THIS ENTRY SETS XFER COUNT TO 128
;
EXIOPBX:
	LD	(IX + PB_BCNTO),128
	LD	(IX + PB_BCNTO + 1),0
;
;   FALL INTO EXECUTE IOPB FUNCTION
;
;   THIS ENTRY ASSUMES IOPB ALL SET UP
;
EXECIOPB:
	PUSH	IX
;
	LD	C,2		;EXECUTE IOPB COMMAND
	RST	BIOS
;
;   TEST FOR ERROR
;
	POP	IX
	LD	A,(IX + PB_STATO)
	OR	A,A
   IF	DIAG = TRUE
;
;   RETURN IF OK
;
	RET	Z
;
;   OUTPUT ERROR DATA
;
	PUSH	AF
	LD	L,A
	LD	H,0
	PUSH	IX
	PUSH	HL
	LD	DE,IOPBERM
	CALL	MSGOT
;
	POP	HL
	CALL	PUTD
;
	POP	IX
	PUSH	IX
	LD	L,(IX + PB_ST1O)
	LD	H,0
	CALL	PUTD
	POP	IX
	POP	AF
;
   ENDIF
	RET


;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	RETURN TRACK PHYSICAL SECTORS PER TRACK FUNCTION
;	ENTRY-	A= TRACK {0,1,..N-1}
;	EXIT -	A= PHYSICAL SECTORS PER TRACK {1,2,..255}
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
GETSPT:
;
;   TO IMPROVE SPEED DEFAULT TO DATA TRACKS
;
	PUSH	HL
	LD	HL,IDSIMG + ID_SPTDO
;
;   COMMON GET DATA CODE
;
GETIDD:	CP	A,1		;TEST TRACK NO.
;
;   IF TRACK == 1 THEN SET PTR TO TRK 1 DATA
;
	JR	Z,GFT1
;
;   ELSE TO IMPROVE SPEED, DEFAULT TO DATA TRACKS
;
	JP	NC,RETIT
;
;   ELSE SET PTR TO TRK 0
;
	DEC	HL
	DEC	HL
;
GFT1:	DEC	HL
	DEC	HL
;
RETIT:	LD	A,(HL)
	POP	HL
	RET


;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	RETURN DISK FORMAT PHYSICAL SECTOR SIZE INDEX FUNCTION
;	ENTRY-	A= TRACK {0,1,..N-1}
;	EXIT -	A= SECTOR SIZE INDEX {0:128, 1:256, 2:512, 3:1024}
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
GETSSZ:	PUSH	HL
	LD	HL,IDSIMG + ID_SSZDO
	JP	GETIDD


	SUBTTL	INITIALIZED DATA
;############################################################################
;
;	SINGLE DENSITY TRANSLATION TABLE
;
;############################################################################
;
;   SINGLE SIDED
;
SSXLATE:
   IF DSIZE = 8
	GXLATE	26,6
   ENDIF

;
;   DOUBLE SIDED
;
DSXLATE:
   IF DSIZE = 8
	GXLATE	52,6
   ENDIF

	SUBTTL	DISK DESCRIPTOR SECTOR DATA
;###########################################################################
;
;	SINGLE DENSITY DESCRIPTOR SECTOR (128 BYTES)
; TRACK 0..77= SD, (SDSPTC) 128 BYTE SECTORS
;
;###########################################################################
IDSIMG:
;
;   RESERVE FIRST 16 BYTES FOR BOOT, IF NEEDED
;
	REPT	16
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM
;
;   DISK DESCRIPTOR SECTOR KEY
;
	DB	'Disk Descriptor2'
;
;	DISK PARAMETER BLOCK IMAGE, TO BE TRANSFERRED TO BIOS AT LOGON TIME
;
	DW	26		;SECTORS PER TRACK
	DB	3		;BLOCK SHIFT FACTOR
	DB	7		;BLOCK MASK
	DB	0		;NULL MASK
	DW	242		;DISK SIZE -1
	DW	63		;DIRECTORY MAXIMUM
	DB	11000000B	;ALLOC 0
	DB	0		;ALLOC 1
	DW	16		;CHECK SIZE
	DW	2		;TRACK OFFSET
	DB	0		;PHYSICAL RECORD SHIFT FACTOR
	DB	0		;PHYSICAL RECORD MASK
;
;   PAD TO FORMAT DATA WITH E5H
;
	REPT	IDSIMG + 40H - $
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM
;
;   DISKETTE FORMAT DATA
;
	DB	00000000B	;DISKETTE FLAGS
;
	REPT	3
	DB	26,0	;;SECTORS PER TRACK,
;;			  BYTES PER SECTOR {0:128, 1:256, 2:512, 3:1024}
	ENDM
;
;   ADDITIONAL DISK PHYSICAL FORMAT INFO
;
	DB	0	;;DISK TYPE
	DW	77	;;NUMBER OF CYLINDERS
	DB	1	;;NUMBER OF HEADS
	DW	0	;;REDUCED WRITE CURRENT CYL
	DB	26	;;MEDIUM PRECOMP START CYL
	DB	52	;;HIGH PRECOMP START CYL
	DB	0	;;ECC BURST LENGTH
	DB	0	;;CONTROL

;   FILL REMAINING SECTOR DATA WITH E5H
;
	REPT	IDSIMG + 128 - $	;FILL OUT SECTOR
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM


;###########################################################################
;
;	DISK DESCRIPTOR SECTOR OVERLAYS
;
;###########################################################################
   IF	DSIZE = 8
;
;	SINGLE SIDED, SINGLE DENSITY, IBM 3740
;
SSSD40ID:
SSSDID:
	DW	26		;SECTORS PER TRACK
	DB	3		;BLOCK SHIFT FACTOR
	DB	7		;BLOCK MASK
	DB	0		;NULL MASK
	DW	242		;DISK SIZE -1
	DW	63		;DIRECTORY MAXIMUM
	DB	11000000B	;ALLOC 0
	DB	0		;ALLOC 1
	DW	16		;CHECK SIZE
	DW	2		;TRACK OFFSET
	DB	0		;PHYSICAL RECORD SHIFT FACTOR
	DB	0		;PHYSICAL RECORD MASK
;
;   DISKETTE PHYSICAL FORMAT DATA
;
	DB	00000000B	;DISKETTE FLAGS
;
	REPT	3
	DB	26,0	;;SECTORS PER TRACK,
;;			  BYTES PER SECTOR {0:128, 1:256, 2:512, 3:1024}
	ENDM
;
;   ADDITIONAL DISK PHYSICAL FORMAT INFO
;
	DB	0	;;DISK TYPE
	DW	77	;;NUMBER OF CYLINDERS
	DB	1	;;NUMBER OF HEADS
	DW	0	;;REDUCED WRITE CURRENT CYL
	DB	26	;;MEDIUM PRECOMP START CYL
	DB	52	;;HIGH PRECOMP START CYL
	DB	0	;;ECC BURST LENGTH
	DB	0	;;CONTROL

;----------------------------------------------------------------------------
;
;	DOUBLE SIDED SINGLE DENSITY, 128 BYTE SECTORS
;
DSSDID:
	DW	52		;SECTORS PER TRACK
	DB	4		;BLOCK SHIFT FACTOR
	DB	0FH		;BLOCK MASK
	DB	1		;NULL MASK
	DW	242		;DISK SIZE -1
	DW	63		;DIRECTORY MAXIMUM
	DB	10000000B	;ALLOC 0
	DB	0		;ALLOC 1
	DW	16		;CHECK SIZE
	DW	2		;TRACK OFFSET
	DB	0		;PHYSICAL RECORD SHIFT FACTOR
	DB	0		;PHYSICAL RECORD MASK
;
;   DISKETTE PHYSICAL FORMAT DATA
;
	DB	00001000B	;DISKETTE FLAGS
;
	REPT	3
	DB	26,0	;;SECTORS PER TRACK, BYTES PER SECTOR
	ENDM
;
;   ADDITIONAL DISK PHYSICAL FORMAT INFO
;
	DB	3	;;DISK TYPE
	DW	77	;;NUMBER OF CYLINDERS
	DB	2	;;NUMBER OF HEADS
	DW	0	;;REDUCED WRITE CURRENT CYL
	DB	26	;;MEDIUM PRECOMP START CYL
	DB	52	;;HIGH PRECOMP START CYL
	DB	0	;;ECC BURST LENGTH
	DB	0	;;CONTROL


;----------------------------------------------------------------------------
;
;	SINGLE SIDED DOUBLE DENSITY, 128 BYTE SECTORS
;
SSDD48ID:
	DW	48		;SECTORS PER TRACK
	DB	4		;BLOCK SHIFT FACTOR
	DB	0FH		;BLOCK MASK
	DB	1		;NULL MASK
	DW	224		;DISK SIZE -1
	DW	63		;DIRECTORY MAXIMUM
	DB	10000000B	;ALLOC 0
	DB	0		;ALLOC 1
	DW	16		;CHECK SIZE
	DW	2		;TRACK OFFSET
	DB	0		;PHYSICAL RECORD SHIFT FACTOR
	DB	0		;PHYSICAL RECORD MASK
;
;   DISKETTE PHYSICAL FORMAT DATA
;
	DB	00000110B	;DISKETTE FLAGS
;
	DB	26,0	;;SECTORS PER TRACK, BYTES PER SECTOR
	DB	48,0
	DB	48,0
;
;   ADDITIONAL DISK PHYSICAL FORMAT INFO
;
	DB	2	;;DISK TYPE
	DW	77	;;NUMBER OF CYLINDERS
	DB	1	;;NUMBER OF HEADS
	DW	0	;;REDUCED WRITE CURRENT CYL
	DB	26	;;MEDIUM PRECOMP START CYL
	DB	52	;;HIGH PRECOMP START CYL
	DB	0	;;ECC BURST LENGTH
	DB	0	;;CONTROL


;----------------------------------------------------------------------------
;
;	DOUBLE SIDED DOUBLE DENSITY, 128 BYTE SECTORS
;
DSDD48ID:
	DW	96		;SECTORS PER TRACK
	DB	4		;BLOCK SHIFT FACTOR
	DB	0FH		;BLOCK MASK
	DB	0		;NULL MASK
	DW	448		;DISK SIZE -1
	DW	127		;DIRECTORY MAXIMUM
	DB	11000000B	;ALLOC 0
	DB	0		;ALLOC 1
	DW	16		;CHECK SIZE
	DW	2		;TRACK OFFSET
	DB	0		;PHYSICAL RECORD SHIFT FACTOR
	DB	0		;PHYSICAL RECORD MASK
;
;   DISKETTE PHYSICAL FORMAT DATA
;
	DB	00001110B	;DISKETTE FLAGS
;
	DB	26,0	;;SECTORS PER TRACK, BYTES PER SECTOR
	DB	48,0
	DB	48,0
;
;   ADDITIONAL DISK PHYSICAL FORMAT INFO
;
	DB	4	;;DISK TYPE
	DW	77	;;NUMBER OF CYLINDERS
	DB	2	;;NUMBER OF HEADS
	DW	0	;;REDUCED WRITE CURRENT CYL
	DB	26	;;MEDIUM PRECOMP START CYL
	DB	52	;;HIGH PRECOMP START CYL
	DB	0	;;ECC BURST LENGTH
	DB	0	;;CONTROL
   ENDIF


;###########################################################################
;
;				MESSAGES
;
;###########################################################################
MSGFL:	DB	CR,LF,LF,'******  Functions List  ******'
	DB	CR,LF,'0. Single sided, single density, IBM 3740 (249k)'
	DB	CR,LF,'1. Single sided, single density, 26 SPT   (249K)'
	DB	LF
	DB	CR,LF,'2. Single sided, double density, 48 SPT   (460k)'
	DB	CR,LF,'3. Double sided, single density, 52 SPT   (499k)'
	DB	CR,LF,'4. Double sided, double density, 96 SPT   (921k)'
;	DB	CR,LF,LF,'9. Custom configuration'
	DB	CR,LF,LF,'Any Other to Stop.'
	DB	CR,LF,LF,'Enter function number: $'

MSGSE:	DB	CR,LF,LF
LTRSE:	DB	'  Is not a valid selection. Stop (Y/N) - $'
MSGFD:	DB	CR,LF,LF,'Write format on controller drive ',7BH,'0..3',7DH
	DB	' (CR to reselect): $'
MSGNC:	DB	CR,LF,LF,'Execution Error!$'
SKERM:	DB	CR,LF,'Seek Error. Is Drive Double Sided?$'
MSGXX:	DB	CR,LF,LF,'Type CR when drive '
DRLTR:	DB	'  is ready. $'
FMTGM	DB	CR,'Formatting track $'
ENDEQM	DB	'  End = $'
TSTGM	DB	CR,'Testing track $'
SIDEM	DB	'  Side $'
SECM	DB	'  Sector $'
CRLFM	DB	CR,LF,'$'
OKM	DB	'  Ok',CR,LF,'$'
ERM	DB	'  Error!',CR,LF,'$'
ABRTDM	DB	'  ** ABORTED **',CR,LF,'$'
   IF	DIAG
IOPBERM	DB	CR,LF,'IOPB error = (status   fdc status) $'
   ENDIF
BIOSM	DB	CR,LF,'BIOS Not Compatable - Aborting...$'


	SUBTTL	DISK FORMAT LIST TABLES
;############################################################################
;
;	FORMAT LIST TABLE TABLE
;
;############################################################################
TBLPTRS:
	DW	TLSD128		;SINGLE DENSITY 128 BYTE SECTORS
	DW	TLSD256
	DW	TLSD512
	DW	TLSD102		;1024 BYTE SECTORS
;
	DW	TLDD128		;DOUBLE DENSITY 128 BYTE SECTORS
	DW	TLDD256
	DW	TLDD512
	DW	TLDD102


   IF	DSIZE = 8
;############################################################################
;
;	SINGLE DENSITY FORMAT TABLE
;	THIS TABLE WILL COMPILE CODE WITHIN THE JADE FLOPPY CONTROLLER, WHICH
; WILL PERFORM THE ACTUAL FORMAT FUNCTION
;
;############################################################################
TLSD128:
	DB	26	;SPT
;
	DB	40,0FFH	;GAP 4A
	DB	6,0	;SYNC
	DB	1,0FCH	;INDEX MARK
	DB	26,0FFH	;GAP 1
	DB	0
;
	DB	6,0	;SYNC
	DB	1,0FEH	;ID MARK
	DB	0
;
	DB	1,0	;SECTOR SIZE INDEX (0= 128 BYTES)
	DB	1,0F7H	;HEADER CRC
	DB	11,0FFH	;GAP 2
	DB	6,0	;SYNC
	DB	1,0FBH	;DATA ID MARK
	DB	128,0E5H	;DATA
	DB	1,0F7H		;DATA CRC
	DB	27,0FFH		;GAP 3
	DB	0
;
	DB	0FFH		;GAP 4B DATA
;
;   SECTOR SKEW TABLE
;
	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
;
   IF	$ >= (TLSD128 + 128)
;
;   USER WARNING MESSAGE
;
	CONMSG	****  WARNING! SD128 TABLE EXCEEDS 128 BYTES!! ****
   ELSE
	REPT	(TLSD128 + 128) - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
   ENDIF


;############################################################################
;
;	SINGLE DENSITY 256 BYTE FORMAT TABLE
;
;############################################################################
TLSD256:
	DB	15	;SPT
;
	DB	40,0FFH	;GAP 4A
	DB	6,0	;SYNC
	DB	1,0FCH	;INDEX MARK
	DB	26,0FFH	;GAP 1
	DB	0
;
	DB	6,0	;SYNC
	DB	1,0FEH	;ID MARK
	DB	0
;
	DB	1,1	;SECTOR SIZE INDEX (1= 256 BYTES)
	DB	1,0F7H	;HEADER CRC
	DB	11,0FFH	;GAP 2
	DB	6,0	;SYNC
	DB	1,0FBH	;DATA ID MARK
	DB	128,0E5H	;DATA
	DB	128,0E5H
	DB	1,0F7H		;DATA CRC
	DB	42,0FFH		;GAP 3
	DB	0
;
	DB	0FFH		;GAP 4B DATA
;
	GXLATE	15,3
;
   IF	$ >= (TLSD256 + 128)
;
;   USER WARNING MESSAGE
;
	CONMSG	****  WARNING! SD256 TABLE EXCEEDS 128 BYTES!! ****
   ELSE
	REPT	(TLSD256 + 128) - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
   ENDIF


;############################################################################
;
;	SINGLE DENSITY 512 BYTE FORMAT TABLE
;
;############################################################################
TLSD512:
	DB	8 	;SPT
;
	DB	40,0FFH	;GAP 4A
	DB	6,0	;SYNC
	DB	1,0FCH	;INDEX MARK
	DB	26,0FFH	;GAP 1
	DB	0
;
	DB	6,0	;SYNC
	DB	1,0FEH	;ID MARK
	DB	0
;
	DB	1,2	;SECTOR SIZE INDEX (2= 512 BYTES)
	DB	1,0F7H	;HEADER CRC
	DB	11,0FFH	;GAP 2
	DB	6,0	;SYNC
	DB	1,0FBH	;DATA ID MARK
	DB	255,0E5H	;DATA
	DB	255,0E5H
	DB	2,0E5H
	DB	1,0F7H		;DATA CRC
	DB	58,0FFH		;GAP 3
	DB	0
;
	DB	0FFH		;GAP 4B DATA
;
	GXLATE	8,3
;
   IF	$ >= (TLSD512 + 128)
;
;   USER WARNING MESSAGE
;
	CONMSG	****  WARNING! SD512 TABLE EXCEEDS 128 BYTES!! ****
   ELSE
	REPT	(TLSD512 + 128) - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
   ENDIF


;############################################################################
;
;	SINGLE DENSITY 1024 BYTE FORMAT TABLE
;
;############################################################################
TLSD102:
	DB	4 	;SPT
;
	DB	40,0FFH	;GAP 4A
	DB	6,0	;SYNC
	DB	1,0FCH	;INDEX MARK
	DB	26,0FFH	;GAP 1
	DB	0
;
	DB	6,0	;SYNC
	DB	1,0FEH	;ID MARK
	DB	0
;
	DB	1,3	;SECTOR SIZE INDEX (3= 1024 BYTES)
	DB	1,0F7H	;HEADER CRC
	DB	11,0FFH	;GAP 2
	DB	6,0	;SYNC
	DB	1,0FBH	;DATA ID MARK
	DB	255,0E5H	;DATA
	DB	255,0E5H
	DB	255,0E5H
	DB	255,0E5H
	DB	4,0E5H
	DB	1,0F7H		;DATA CRC
	DB	138,0FFH	;GAP 3
	DB	0
;
	DB	0FFH		;GAP 4B DATA
;
	GXLATE	4,2
;
   IF	$ >= (TLSD102 + 128)
;
;   USER WARNING MESSAGE
;
	CONMSG	****  WARNING! SD102 TABLE EXCEEDS 128 BYTES!! ****
   ELSE
	REPT	(TLSD102 + 128) - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
   ENDIF


	FORM
;###########################################################################
;
;   DOUBLE DENSITY 128 TABLE
;
;###########################################################################
TLDD128:
	DB	48		;SPT
;
	DB	80,4EH		;GAP 4A
	DB	12,0		;SYNC
	DB	3,0F6H
	DB	1,0FCH		;INDEX MARK
	DB	32,4EH		;GAP 1
	DB	0
;
	DB	8,0		;GAP 3
	DB	3,0F5H		;GAP A1
	DB	1,0FEH		;ID MARK
	DB	0
;
	DB	1,0		;SECTOR SIZE INDEX (0= 128 BYTES)
	DB	1,0F7H		;HEADER CRC
	DB	22,4EH		;GAP 2
	DB	8,0		;SYNC
	DB	3,0F5H		;GAP A1
	DB	1,0FBH		;DATA MARK
	DB	128,0E5H	;DATA
	DB	1,0F7H		;DATA CRC
	DB	24,4EH		;GAP 3
	DB	0
;
	DB	4EH		;GAP 4 DATA
;
;   DOUBLE DENSITY SKEW TABLE, SKEW 8 SEEMS OPTIMUM
;
	GXLATE	48, 6

   IF	$ >= (TLDD128 + 128)
;
;   USER WARNING MESSAGE
;
	CONMSG	****  WARNING! DD TABLE EXCEEDS 128 BYTES!! ****
   ELSE
	REPT	(TLDD128 + 128) - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
   ENDIF

	FORM
;###########################################################################
;
;   IBM SERIES 34 DOUBLE DENSITY TABLE (256 BYTE SECTORS)
;
;###########################################################################
TLDD256:
	DB	26		;SPT
;
	DB	80,4EH		;GAP 4A
	DB	12,0		;SYNC
	DB	3,0F6H
	DB	1,0FCH		;INDEX MARK
	DB	50,4EH		;GAP 1
	DB	0
;
	DB	12,0		;GAP 3
	DB	3,0F5H		;GAP A1
	DB	1,0FEH		;ID MARK
	DB	0
;
	DB	1,1		;SECTOR SIZE INDEX (1= 256 BYTES)
	DB	1,0F7H		;HEADER CRC
	DB	22,4EH		;GAP 2
	DB	12,0		;SYNC
	DB	3,0F5H		;GAP A1
	DB	1,0FBH		;DATA MARK
	DB	255,0E5H	;DATA
	DB	1,0E5H		;DATA OVERFLOW
	DB	1,0F7H		;DATA CRC
	DB	54,4EH		;GAP 3
	DB	0
;
	DB	4EH		;GAP 4 DATA
;
;   DOUBLE DENSITY SKEW TABLE, SKEW 8 SEEMS OPTIMUM
;
	GXLATE	26, 6

   IF	$ >= (TLDD256 + 128)
;
;   USER WARNING MESSAGE
;
	CONMSG	****  WARNING! DD TABLE EXCEEDS 128 BYTES!! ****
   ELSE
	REPT	(TLDD256 + 128) - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
   ENDIF


;###########################################################################
;
;   IBM SERIES 34 DOUBLE DENSITY TABLE (512 BYTE SECTORS)
;
;###########################################################################
TLDD512:
	DB	15		;SPT
;
	DB	80,4EH		;GAP 4A
	DB	12,0		;SYNC
	DB	3,0F6H
	DB	1,0FCH		;INDEX MARK
	DB	50,4EH		;GAP 1
	DB	0
;
	DB	12,0		;GAP 3
	DB	3,0F5H		;GAP A1
	DB	1,0FEH		;ID MARK
	DB	0
;
	DB	1,2		;SECTOR SIZE INDEX (2= 512 BYTES)
	DB	1,0F7H		;HEADER CRC
	DB	22,4EH		;GAP 2
	DB	12,0		;SYNC
	DB	3,0F5H		;GAP A1
	DB	1,0FBH		;DATA MARK
	DB	255,0E5H	;DATA
	DB	255,0E5H
	DB	2,0E5H
	DB	1,0E5H		;DATA OVERFLOW
	DB	1,0F7H		;DATA CRC
	DB	84,4EH		;GAP 3
	DB	0
;
	DB	4EH		;GAP 4 DATA
;
;   DOUBLE DENSITY SKEW TABLE, SKEW 8 SEEMS OPTIMUM
;
	GXLATE	15, 3

   IF	$ >= (TLDD512 + 128)
;
;   USER WARNING MESSAGE
;
	CONMSG	****  WARNING! DD512 TABLE EXCEEDS 128 BYTES!! ****
   ELSE
	REPT	(TLDD512 + 128) - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
   ENDIF


;###########################################################################
;
;   IBM SERIES 34 DOUBLE DENSITY TABLE (1024 BYTE SECTORS)
;
;###########################################################################
TLDD102:
	DB	8 		;SPT
;
	DB	80,4EH		;GAP 4A
	DB	12,0		;SYNC
	DB	3,0F6H
	DB	1,0FCH		;INDEX MARK
	DB	50,4EH		;GAP 1
	DB	0
;
	DB	12,0		;GAP 3
	DB	3,0F5H		;GAP A1
	DB	1,0FEH		;ID MARK
	DB	0
;
	DB	1,3		;SECTOR SIZE INDEX (3= 1024 BYTES)
	DB	1,0F7H		;HEADER CRC
	DB	22,4EH		;GAP 2
	DB	12,0		;SYNC
	DB	3,0F5H		;GAP A1
	DB	1,0FBH		;DATA MARK
	DB	255,0E5H	;DATA
	DB	255,0E5H
	DB	255,0E5H
	DB	255,0E5H
	DB	4,0E5H
	DB	1,0E5H		;DATA OVERFLOW
	DB	1,0F7H		;DATA CRC
	DB	116,4EH		;GAP 3
	DB	0
;
	DB	4EH		;GAP 4 DATA
;
;   DOUBLE DENSITY SKEW TABLE, SKEW 8 SEEMS OPTIMUM
;
	GXLATE	8, 2

   IF	$ >= (TLDD102 + 128)
;
;   USER WARNING MESSAGE
;
	CONMSG	****  WARNING! DD102 TABLE EXCEEDS 128 BYTES!! ****
   ELSE
	REPT	(TLDD102 + 128) - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
   ENDIF
   ENDIF


;############################################################################
;
;			IOPBS
;
;############################################################################
;
;   FORMAT TRACK IOPB
;
IOPB:	DB	PB_FRMTC	;FORMAT TRACK
	DB	0		;DRIVE
	DW	0		;TRACK
	DW	1		;SECTOR
	DB	0		;FLAG
	DW	SECBUF		;DMA
	DB	0
	DW	128		;COUNT
	DW	0,0		;STATUS

;
;   WRITE ID SECTOR IOPB
;
WIDIOPB:
	DB	PB_WRITC	;WRITE SECTOR
	DB	0		;DRIVE
	DW	0		;TRACK
	DW	ID_SECT		;SECTOR
	DB	0		;FLAG
	DW	IDSIMG		;DMA
	DB	0
	DW	128		;COUNT
	DW	0,0		;STATUS

;
;   READ SECTOR IOPB
;
RDIOPB:	DB	PB_READC	;READ SECTOR
	DB	0		;DRIVE
	DW	0		;TRACK
	DW	1		;SECTOR
	DB	0		;FLAG
	DW	SECBUF		;DMA
	DB	0
	DW	128		;COUNT
	DW	0,0		;STATUS



	SUBTTL	VARIABLE DECLARATIONS
;############################################################################
;
;		UNINITIALIZED DATA
;
;############################################################################
NSECTS	DS	1		;NUMBER OF SECTORS IN TRACK
CURSEC	DS	1		;CURRENT SECTOR
DTYPE	DS	1		;DISK TYPE
XLATPTR	DS	2		;XLATION TABLE PTR

;
;   READ SECTOR BUFFER
;
SECBUF	DS	1024		;SECTOR BUFFER

	END
