	TITLE	FORMAT UTILITY
	LIST	NOCOND
;*************************************************************
;
;   JADE DOUBLE D DISK FORMAT PROGRAM
;
;*************************************************************
;
;   Format is a system utility which provides a means to 
; write a single or double density format on any of drives A 
; through D. 
;
;*************************************************************
;
;	REVISION STATUS:
;
; 1.0 -	8 FEB 81   GRH
;	RELEASE
;
; 1.1 -	25 MAR 83   GRH
;	Removed system track xfer. Superceeded by the new SYSGEN utility.
;	Cleaned up for ASMB.
;	Removed format system tracks only option. Never worked!
;	Added capability to double the directory size for disks with many
;	 small programs (such as libraries).
;
; 1.2 -	31 AUG 83   GRH
;	Added 256 byte (IBM system 34 compatibility) sector formatting.
;	Added sector read verification after format.
;
; 1.3 -	09 JUN 84   GRH
;	Removed format vector from BIOS to this program.
;
VERSN	EQU	'13'	;CHANGE HERE FOR SIGN-ON CHANGE
;
;*************************************************************
FALSE	EQU	0
TRUE	EQU	NOT FALSE
LSTINC	EQU	FALSE
;
;	*INCLUDE JDDCONT.DEF
;	*INCLUDE JDDLOC.DEF
;
	IF	NOT LSTINC
	LIST	OFF
	ENDIF
*INCLUDE	JDDCONT.DEF
*INCLUDE	JDDLOC.DEF
	LIST	ON
	SUBTTL	DECLARATIONS

;
;   DRIVER MODULE DEFINITIONS
;
CTRLC:	EQU	3		;REQUEST REBOOT CPM
LF:	EQU	0AH		;LINE FEED
CR:	EQU	0DH		;CARRIAGE RETURN
BS	EQU	08H		;BACKSPACE

REBOOT:	EQU	0		;REBOOT ADDR
TPA:	EQU	100H		;TRANSIENT PROGRAM AREA

DRV1	EQU	'C'		;1ST CP/M DRIVE TO FORMAT
DRVN	EQU	'D'		;LAST CP/M DRIVE TO FORMAT
NDRVS	EQU	DRVN + 1 - DRV1	;MAX NUMBER OF DRIVES
TRK0:	EQU	0		;TRACK 0
TRK1:	EQU	1		;TRACK 1
TRK2:	EQU	2		;TRACK 2
TRK76:	EQU	76		;TRACK 76
SECSZ:	EQU	128		;128 BYTES PER SECTOR
IDSEC:	EQU	1		;ID SECTOR #


;
;   INJECTION MODULE DEFINITIONS
;
ZEROS:	EQU	00000000B	;ALL ZEROS BYTE
ONES:	EQU	11111111B	;ALL ONES BYTE
FMTSZ	EQU	256		;FORMAT INJECTION MODULE LENGTH


;
;   BDOS CALL VECTORS
;
WBOOT	EQU	0000H		;SYSTEM WARM BOOT
BDOS:	EQU	0005H		;SYSTEM CALL ADDR


;
;   BIOS VECTOR DEFINITIONS
;
SLDSKV:	EQU	8		;SELECT DISK OFFSET
SETRKV:	EQU	9		;SET TRACK OFFSET
SETSECV:EQU	10		;SET SECTOR OFFSET
SETMAV:	EQU	11		;SET ADDRESS OFFSET
RDSECV:	EQU	12		;READ SECTOR OFFSET
WRSECV:	EQU	13		;WRITE SECTOR OFFSET

LOGVC:	EQU	1		;DRV SEL DON'T LOGON

	SUBTTL	MACROS
;;
;;	GENERATE THE TRANSLATE TABLE
;;
GXLATE	MACRO	#SECTORS, #SKEW
	LIST	NOGEN
NXTSEC	DL	1			;;START WITH SECTOR 1
LOWEST	DL	1

	REPT	#SECTORS		;;ONCE FOR EACH SECTOR
	LIST	GEN
	DB	NXTSEC
	LIST	NOGEN
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

	ENDM

	SUBTTL	MAIN PROGRAM
	ORG	TPA
;
;   PROGRAM ENTRY POINT
;
	JP	INIT		;INITIALIZE

$MEMRY	DW	CODEND		;PTR TO 1ST AVAILABLE BYTE OF MEMORY

;
;	DRIVE LIMITS, USER CHANGABLE
;
DRVLO	DB	DRV1 - 'A'	;1ST DRIVE
DRVHI	DB	DRVN - 'A' + 1	;LAST DRIVE + 1

;
;	COPYRIGHT NOTICE
;
SIGNON:	DB	'Floppy disk format Utility   Ver '
	DB	HIGH VERSN,'.',LOW VERSN,CR,LF
	DB	'Copyright (c) 1983   GRH Enterprises'
	DB	'$'


;
;	MAIN PROGRAM CONTINUES
;
INIT:	LD	SP,(BDOS + 1)
	DEC	SP
	DEC	SP

	LD	DE,SIGNON	;OUTPUT MESSAGE
	CALL	MSGOT

FUNBG:	LD	DE,MSGFL	;OUTPUT FUNCTION LIST
	CALL	MSGOT

	CALL	CNSIN		;GET CONSOLE CHAR
	CP	'1'		;IF 1 THEN FORMAT DDEN
	JR	Z,FUN1

	CP	'2'		;ELSE IF 2 THEN     FORMAT SDEN
	JP	Z,FUN2

	CP	'3'		;ELSE IF 3 THEN FORMAT IBM 3740
	JP	Z,FUN3

	CP	'4'		;ELSE IF 4 THEN FORMAT 256 BYTE SECTORS
	JP	Z,FUN4

	LD	DE,MSGSE	;ELSE OUTPUT ERROR MSG
	LD	(LTRSE),A	;STORE BAD SYMBOL

	CALL	MSGOT
	JR	FUNBG		;REPEAT


;----------------------------------------------------------
;
;   FUNCTION 1 - DOUBLE DENSITY FORMAT
;	TRK 0= SINGLE DENSITY
;	TRK 1..76= DOUBLE DENSITY 128 BYTE SECTORS
;
;----------------------------------------------------------
FUN1:
	LD	IX,IDSDD	;SET DEFAULT DIRECTORY SIZE
	LD	A,(IX+DDFLG)	;SET FLAGS
	LD	(FFLAG),A

	LD	HL,DDSDIR
	CALL	SELDR		;SELECT DRIVE
	JR	C,FUNBG		;ERR- RESELECT

	LD	A,TRK0		;SET TRACK #
	LD	(TRKNO),A
	CALL	FMTSD		;FORMAT TRACK SDENS

	CALL	NC,WRTID	;WHILE WE'RE HERE, WRITE ID SECTOR
	JR	C,FUN1		;ERR

	CALL	TRKDONE		;OUTPUT '*'

	LD	A,TRK1		;SET NEXT TRACK #
	LD	(TRKNO),A

REPT1:	CALL	FMTDD		;FORMAT TRACK IN DDENS
	JR	C,FUN1		;ERR

	CALL	TRKDONE

	LD	A,(TRKNO)	;IF LAST TRACK THEN DONE
	CP	TRK76
	JR	Z,DOCHK1

	INC	A		;ELSE DO NEXT TRACK
	LD	(TRKNO),A
	JR	REPT1

DOCHK1:	CALL	CHECK		;CHECK FOR READ ERRORS
	JP	FUN1		;READY FOR ANOTHER DISK


;--------------------------------------------------
;
;   FUNCTION 2 - FORMAT IN JADE SINGLE DENSITY
;	TRK 0= SINGLE DENSITY
;	TRK 1= DOUBLE DENSITY
;	TRK 2..76= SINGLE DENSITY
;
;--------------------------------------------------
FUN2:
	LD	IX,IDSSD	;SELECT DRIVE
	LD	A,(IX+DDFLG)
	LD	(FFLAG),A

	LD	HL,SDSDIR
	CALL	SELDR
	JP	C,FUNBG		;ERR

	LD	A,TRK0		;SET UP FOR TRACK 0
	LD	(TRKNO),A
	CALL	FMTSD		;FORMAT IN SDENS

	CALL	NC,WRTID	;WHILE WE'RE HERE, WRITE ID SECTOR
	JR	C,FUN2		;ERR

	CALL	TRKDONE

	LD	A,TRK1		;SET UP FOR TRACK 1
	LD	(TRKNO),A
	CALL	FMTDD		;FORMAT IN DDENS
	JR	C,FUN2		;ERR

	CALL	TRKDONE
	LD	A,TRK2		;SET UP FOR TRACK 2
	LD	(TRKNO),A
REPT2:	CALL	FMTSD		;FORMAT TRACK IN SDENS
	JR	C,FUN2		;ERR

	CALL	TRKDONE
	LD	A,(TRKNO)
	CP	TRK76
	JR	Z,DOCHK2

	INC	A		;ELSE DO NEXT TRACK
	LD	(TRKNO),A
	JR	REPT2

DOCHK2:	CALL	CHECK		;CHECK FOR READ ERRORS
	JR	FUN2		;READY FOR ANOTHER DISK


;--------------------------------------
;
;   FUNCTION 3 - FORMAT IBM 3740
;	TRK 0..76= SINGLE DENSITY
;
;--------------------------------------
FUN3:	LD	A,0		;SET 3740 FLAGS
	LD	(FFLAG),A

	CALL	SELDR		;SELECT DRIVE
	JP	C,FUNBG		;ERR

	LD	A,TRK0		;SET UP FOR TRACK 0
	LD	(TRKNO),A

REPT3:	CALL	FMTSD		;FORMAT IN SDEN
	JR	C,FUN3		;ERR

	CALL	TRKDONE		;OUTPUT '*'

	LD	A,(TRKNO)	;IF TRACK 76 THEN DONE
	CP	TRK76
	JR	Z,FUN3CK

	INC	A		;ELSE DO NEXT TRACK
	LD	(TRKNO),A
	JR	REPT3

FUN3CK:	CALL	CHECK		;READ EACH SECTOR
	JR	FUN3


;----------------------------------------------------------
;
;   FUNCTION 4 - DOUBLE DENSITY FORMAT
;	TRK 0= SINGLE DENSITY
;	TRK 1..76= DOUBLE DENSITY 256 BYTE SECTORS
;
;----------------------------------------------------------
FUN4:	LD	IX,IDSDD2
	LD	A,(IX+DDFLG)	;SET FORMAT FLAGS
	LD	(FFLAG),A

	LD	HL,DDSDIR
	CALL	SELDR
	JP	C,FUNBG		;ERR- RESELECT

	LD	A,TRK0		;SET TRACK #
	LD	(TRKNO),A
	CALL	FMTSD		;FORMAT TRACK SDENS

	CALL	NC,WRTID	;WHILE WE'RE HERE, WRITE ID SECTOR
	JR	C,FUN4		;ERR

	CALL	TRKDONE		;OUTPUT '*'
	LD	A,TRK1		;SET NEXT TRACK #
	LD	(TRKNO),A

REPT4:	CALL	FMTDD2		;FORMAT TRACK IN DDENS
	JR	C,FUN4		;ERR

	CALL	TRKDONE
	LD	A,(TRKNO)	;IF LAST TRACK THEN DONE
	CP	TRK76
	JR	Z,DOCHK4

	INC	A		;ELSE DO NEXT TRACK
	LD	(TRKNO),A
	JR	REPT4


DOCHK4:	CALL	CHECK		;CHECK FOR READ ERRORS
	JR	FUN4		;READY FOR ANOTHER DISK


	SUBTTL	SUBROUTINES
;****************************************************
;
;   MESSAGE OUTPUT SUBR
;	ENTRY-	DE= PTR TO '$' TERMINATED TEXT
;	EXIT -	?
;
;****************************************************
MSGOT:
	LD	C,9		;PRINT STRING FUNCTION
	JP	BDOS


;***********************************
;
;   CONSOLE INPUT SUBR
;	EXIT -	A= CHAR AND 7FH
;
;***********************************
CNSIN:	LD	C,1		;CONSOLE READ FUNCTION #
	CALL	BDOS

	AND	7FH
	CP	CTRLC		;IF CTRL-C THEN REBOOT
	JP	Z,REBOOT

	CP	'a'		;IF LOWER CASE THEN CONVERT TO UPPER CASE
	RET	C
	CP	'z' + 1
	RET	NC
	AND	5FH
	RET


;*******************************
;
;	OUTPUT '*' SUBR
;
;*******************************
TRKDONE:
	LD	E,'*'


;*******************************
;
;	CONSOLE OUTPUT SUBR
;	ENTRY-	E= CHAR
;
;*******************************
CNSOT:	LD	C,2		;CONSOLE OUTPUT FUNCTION #
	JP	BDOS


;***********************************************
;
;   WRITE ID SECTOR
;	ENTRY-	IX= PTR TO ID SECTOR IMAGE
;	EXIT -	CF= ERROR
;
;***********************************************
WRTID:	PUSH	IX		;HL -> BC
	POP	BC

	CALL	SETDMA		;SET XFER ADDR

	LD	C,TRK0		;SET TRACK 0
	CALL	SETTRK

	LD	C,IDSEC		;SET ID SECTOR
	CALL	SETSEC

	CALL	WRSECT		;WRITE ID SECTOR
	OR	A		;IF NO ERRORS THEN RETURN
	RET	Z

	LD	DE,MSGNC	;ELSE OUTPUT ERROR & RETURN
	CALL	MSGOT
	SCF
	RET


;****************************************
;
;   FORMAT SINGLE DENSITY TRACK SUBR
;	EXIT -	CF: ERROR
;
;****************************************
FMTSD:	LD	HL,FT3740	;SET INJECTION ADDR
	JR	STDMA


;****************************************
;
;   FORMAT DOUBLE DENSITY TRACK SUBR
;	EXIT -	CF: ERROR
;
;****************************************
FMTDD:	LD	HL,FTJ48D	;SET INJECTION ADDR
	JR	STDMA

;****************************************
;
;   FORMAT 256 BYTE DOUBLE DENSITY TRACK
;
;****************************************
FMTDD2:	LD	HL,FTJ26D	;USE 256 BYTE INJECTION MODULE

STDMA:	LD	(BTDMA),HL	;SET PTR TO INJECTION MODULE

	LD	A,(TRKNO)	;SET TRACK # SO BIOS IN SYNC WITH FORMAT
	LD	C,A
	CALL	SETTRK

	CALL	FMTTRK		;FORMAT TRACK
	OR	A		;IF NO ERR THEN RETURN
	RET	Z

	LD	DE,MSGNC	;ELSE OUTPUT ERROR MSG
	CALL	MSGOT
	SCF			;RETURN ERROR FLAG
	RET


;************************************************
;
;   SELECT DRIVE SUBR
;	ENTRY-	HL= DEFAULT DIR VALUES PTR
;		IX= DPB PTR
;	EXIT -	CF= ERROR
;
;************************************************
SELDR:
	LD	A,(FFLAG)	;IF FORMAT FLAG NOT 0 THEN
	OR	A
	JR	Z,REPTD

	LD	A,(HL)		;SET DPB TO DEFAULTS
	LD	(IX+AL0),A
	INC	HL
	LD	A,(HL)
	LD	(IX+DRM),A
	INC	HL
	LD	A,(HL)
	LD	(IX+CKS),A

REPTD:	LD	DE,MSGFD	;PRINT MESSAGE
	CALL	MSGOT
	CALL	CNSIN		;GET DRIVE INPUT
	CP	CR		;IF RETURN THEN EXIT
	JR	Z,EXITD

	LD	(DRLTR),A	;ELSE SAVE DRIVE LETTER & TEST FOR LEGAL
	LD	(LTRSE),A
	SUB	'A'

	LD	HL,DRVLO
	CP	(HL)
	JR	C,ILLG

	LD	HL,DRVHI
	CP	(HL)
	JR	C,NMBRD		;IF LEGAL THEN CONTINUE

ILLG:	LD	DE,MSGSE	;PRINT SELECT ERROR MESSAGE
	CALL	MSGOT
	JR	REPTD

EXITD:	SCF			;SET FLAG TO CALLING RTN
	RET
;
;	DRIVE SELECTED
;
NMBRD:	LD	C,A		;SELECT DRIVE
	LD	HL,DRVLO	;BIAS IT DOWN
	SUB	(HL)
	LD	(BTDRV),A
	LD	E,LOGVC		;LOG ON VECTOR = NO LOG
	CALL	BSELDK

	LD	A,L		;IF SELECT ERROR THEN NO DRIVE
	OR	H
	JR	NZ,LOGOK

	LD	DE,NODRVM
	CALL	MSGOT
	SCF
	RET

LOGOK:	LD	DE,MSGXX	;PRINT TYPE CR WHEN READY MSG
	CALL	MSGOT
	CALL	CNSIN		;IF NOT CR THEN REPEAT
	CP	CR
	JR	NZ,REPTD

;	NOW ASK FOR DOUBLE DIRECTORY SIZE

	LD	A,(FFLAG)	;IF SINGLE DENSITY 3740 THEN NO DPB
	OR	A
	JR	Z,IDOK

	LD	DE,DIRQM
	CALL	MSGOT
	CALL	CNSIN
	CP	'Y'		;IF YES THEN CHANGE
	JR	NZ,IDOK

	SCF			;DOUBLE DIRECTORY SPACE
	RL	(IX+DRM)
	SLA	(IX+CKS)	;DOUBLE CHECKSUMS

	LD	A,(IX+AL0)	;SET UP TO DOUBLE ALLOCATION SIZE

ADDBLK:	SLA	A
	JR	NC,IDOK

	SRA	(IX+AL0)	;ADD ANOTHER BLOCK
	JR	ADDBLK	

IDOK:	LD	DE,FMTHDR	;OUTPUT HEADER OF TRACKS
	CALL	MSGOT

	AND	A		;ELSE CLEAR ERR FLAG & RETURN
	RET


;***************************************************************************
;
;	CHECK FUNCTION CHECKS ALL TRACKS BY READING BACKWARD FROM 76
;
;***************************************************************************
CHECK:

	LD	A,(DRLTR)	;DO LOG-ON SO CONTROLLER INFORMED
	SUB	'A'
	LD	C,A
	LD	E,LOGVC
	CALL	BSELDK

	LD	BC,SECBUF	;USE DUMMY SECTOR BUFFER
	CALL	SETDMA

	LD	A,76		;START WITH LAST TRACK
	LD	(TRKNO),A

;
;	ALL SET TO DO TRACK
;
VLP:
	LD	C,A		;SEEK TRACK
	CALL	SETTRK

	XOR	A		;ASSUME NO ERRORS
	LD	(RDERR),A

	LD	E,BS		;START AT LAST '*'
	CALL	CNSOT

	LD	E,'V'		;OUTPUT VERIFY PROMPT
	CALL	COUT

	LD	A,-1		;ASSUME TRANSLATE
	LD	(TXFLG),A

	LD	A,(FFLAG)	;COMPUTE NUMBER OF SECTORS IN TRACK
	OR	A		;IF SINGLE DENSITY THEN DO 26 SECTORS
	JR	Z,DO26

	LD	A,(TRKNO)	;ELSE IF FLAG BIT == 0 THEN DO 26 SECTORS
	CP	1
	JR	Z,VTRK1
	JR	C,VTRK0

	BIT	2,(IX+DDFLG)
	JR	Z,DO26

DOSECTS:
	XOR	A		;NO XLATE
	LD	(TXFLG),A
	LD	A,(IX+SPT)	;USE DPB SECTORS
	JR	SETNSEC

VTRK1:	BIT	1,(IX+DDFLG)
	JR	Z,DO26
	JR	DOSECTS

VTRK0:	BIT	0,(IX+DDFLG)
	JR	NZ,DOSECTS

DO26:	LD	A,26
SETNSEC:
	INC	A		;OFFSET FOR TEST
	LD	(NSECTS),A

	LD	A,1		;START WITH 1ST SECTOR

;
;	ALL SET TO DO SECTOR
;
RDLP:	LD	(SECTOR),A	;SAVE CURRENT SECTOR

	LD	HL,NSECTS
	CP	(HL)
	JR	Z,TDONE

	LD	C,A
	CALL	SECTRN
	CALL	SETSEC
	CALL	RDSEC
	OR	A
	JR	Z,VRDCNT

	LD	(RDERR),A

VRDCNT:	LD	A,(SECTOR)
	INC	A
	JP	RDLP

;
;	TRACK IS DONE, CHECK IF ANY ERRORS
;
TDONE:	LD	A,(RDERR)
	OR	A
	JR	NZ,VERR

	LD	E,'-'
	JR	OUTV

VERR:	LD	E,'?'		;OUTPUT '?'
OUTV:	CALL	COUT

	LD	A,(TRKNO)	;NEXT TRACK
	DEC	A
	LD	(TRKNO),A

	RET	M		;IF TRACK < 0 THEN DONE
	JP	VLP


;**************************************
;
;	SECTOR TRANSLATION SUBR
;	ENTRY-	C= SECTOR
;	EXIT -	C= SECTOR
;
;**************************************
SECTRN:	LD	A,(TXFLG)	;IF NOT SINGLE DENSITY THEN RETURN
	OR	A
	RET	Z

	LD	B,0
	DEC	C
	LD	HL,TRNTBL
	ADD	HL,BC
	LD	C,(HL)
	RET


;**********************************************************
;
;	CHAR OUT WITH CURSOR AT SAME POSITION SUBR
;	ENTRY-	E= CHAR TO OUTPUT
;
;**********************************************************
COUT:	CALL	CNSOT
	LD	E,BS
	JP	CNSOT


;*******************************
;
;	SET TRACK FUNCTION
;	ENTRY-	BC= TRACK #
;
;*******************************
SETTRK:	LD	A,SETRKV

BIOS:	PUSH	DE		;SAVE POSSIBLE LOGON VECTOR
	LD	HL,(WBOOT +1)	;GET BIOS PTR
	LD	E,A		;ADD IN OFFSET
	LD	D,0
	ADD	HL,DE
	ADD	HL,DE
	ADD	HL,DE
	POP	DE
	JP	(HL)		;EXECUTE

;********************************
;
;	SET SECTOR FUNCTION
;	ENTRY-	BC= SECTOR #
;
;********************************
SETSEC:	LD	A,SETSECV
	JP	BIOS

;**********************************
;
;	SET DMA FUNCTION
;	ENTRY-	BC= MEMORY ADDR
;
;**********************************
SETDMA:	LD	A,SETMAV
	JP	BIOS

;**********************************
;
;	WRITE SECTOR FUNCTION
;
;**********************************
WRSECT:	LD	A,WRSECV
	JP	BIOS

;**********************************
;
;	READ SECTOR FUNCTION
;
;**********************************
RDSEC:	LD	A,RDSECV
	JP	BIOS


;**********************************
;
;	FORMAT TRACK FUNCTION
;
;**********************************
FMTTRK:	
	LD	A,DDMRQ		;SWITCH DD INTO SYSTEM
	OUT	(DDPORT),A

	LD	A,DDMB1		;SELECT BANK 1
	OUT	(DDPORT),A

	LD	BC,FMTSZ	;MOVE FORMAT CODE INTO FDC
	LD	HL,(DADDR)
	LD	DE,DDFBF
	ADD	HL,DE
	EX	DE,HL
	LD	HL,(BTDMA)
	LDIR

	LD	A,DDMRQ		;SELECT BANK 0
	OUT	(DDPORT),A

	LD	BC,7		;MOVE COMMAND BLOCK INTO FDC
	LD	DE,DDCMD
	LD	HL,(DADDR)
	ADD	HL,DE
	EX	DE,HL
	LD	HL,BTCMD
	LDIR

	LD	A,DDEXC		;EXECUTE COMMAND BLOCK
	OUT	(DDPORT),A

	EX	DE,HL		;SET UP TO MOVE DOWN STATUS BYTES
	LD	BC,5
DSKWT:	IN	A,(DDPORT)	;WAIT UNTIL DONE
	AND	DDSHLT
	JR	NZ,DSKWT

	LD	A,DDMRQ		;SWITCH DD INTO SYSTEM
	OUT	(DDPORT),A
	LDIR			;FETCH STATUS BYTES
	LD	A,DDOUT		;REMOVE FDC FROM MEMORY MAP
	OUT	(DDPORT),A

	LD	A,(BTSTS)	;RETURN STATUS
	OR	A
	RET


;*********************************************
;
;	SELECT DISK THROUGH BIOS FUNCTION
;	ENTRY-	E= DISK #
;
;*********************************************
BSELDK:	LD	A,SLDSKV	;SELECT DISK FUNCTION #
	JP	BIOS


	SUBTTL	CONSTANT DECLARATIONS
;--------------------------------------
;
;	DEFAULT DIRECTORY SIZE VALUES
;
;--------------------------------------
DDSDIR:	DB	80H,63,16	;DOUBLE DENSITY
SDSDIR:	DB	0C0H,63,16	;SINGLE DENSITY


;------------------------------------------------
;
;	SINGLE DENSITY TRANSLATION TABLE
;
;------------------------------------------------
TRNTBL:
	GXLATE	26,6

;*******************************************
;
;   JADE SINGLE DENSITY IDENTITY SECTOR
; TRACK 0= SD, 26 128 BYTE SECTORS
; TRACK 1= DD, 48 128 BYTE SECTORS EACH
; TRACK 2..76= SD
;
;*******************************************
IDSSD:	DB	'Jade DD Single density format '	;CONFIRMATION TEXT
;
;	DISK PARAMETER BLOCK IMAGE, TO BE TRANSFERRED TO BIOS AT LOGON TIME
;
	REPT	IDSSD + 20H -$		;POSITION DPB IN SECTOR
	LIST	OFF
	DB	0E5H		;FILL WITH E5
	LIST	ON
	ENDM

SPT	EQU	$ - IDSSD
	DW	26		;SECTORS PER TRACK
	DB	3		;BLOCK SHIFT FACTOR
	DB	7		;BLOCK MASK
	DB	0		;NULL MASK
	DW	242		;DISK SIZE -1
DRM	EQU	$ - IDSSD	;OFFSET TO DRM BYTE
	DW	63		;DIRECTORY MAXIMUM
AL0	EQU	$ - IDSSD	;OFFSET TO DIRECTORY ALLOCATION BYTE
	DB	11000000B	;ALLOC 0
	DB	0		;ALLOC 1
CKS	EQU	$ - IDSSD	;OFFSET TO CHECKSUMS BYTE
	DW	16		;CHECK SIZE
	DW	2		;TRACK OFFSET
;
;	DISK CONTROLLER MODULE DISK PARAMETERS TO BE TRANSFERRED TO DCM AT
;  LOGON TIME
;
	REPT	IDSSD + 30H -$	;LOCATE DCM BLK
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM

	DB	6		;SECTOR STAGGER (TRNS)

DDFLG	EQU	$ - IDSSD
	DB	00000010B	;DISKETTE FLAGS

	REPT	IDSSD+SECSZ-$	;FILL OUT SECTOR
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM


;*********************************************
;
;   JADE DOUBLE DENSITY IDENTITY SECTOR
;   TRACK 0= SD, 26 128 BYTE SECTORS
;   TRACKS 1..76= DD, 48 128 BYTE SECTORS EACH
;
;*********************************************
IDSDD:	DB	'Jade DD Double density format '	;CONFIRMATION TEXT

	REPT	IDSDD + 20H -$
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM

	DW	48		;SECTORS PER TRK
	DB	4		;BLOCK SHIFT FACTOR
	DB	00001111B	;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

	REPT	IDSDD + 30H -$	;LOCATE DCM BLOCK
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM

	DB	6		;SECTOR STAGGER (TRNS)
	DB	00000110B	;DISKETTE FLAGS
;
	REPT	IDSDD + SECSZ -$	;EXTEND TO FULL SECTOR
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM


;*********************************************
;
;   JADE DOUBLE DENSITY IDENTITY SECTOR
; TRACK 0= SD, 26 128 BYTE SECTORS
; TRACK 1..76= DD, 26 256 BYTE SECTORS EACH
;
;*********************************************
IDSDD2:	DB	'Jade DD Double density format '	;CONFIRMATION TEXT

	REPT	IDSDD2 + 20H -$
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM
;
;	IN THIS CASE, CP/M IS FOOLED BY THE DEBLOCKING INTO THINKING
; THERE ARE 52 128 BYTE SECTORS PER TRACK
;
	DW	52		;SECTORS PER TRK
	DB	4		;BLOCK SHIFT FACTOR
	DB	00001111B	;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

	REPT	IDSDD2 + 30H -$	;LOCATE DCM BLOCK
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM

	DB	6		;SECTOR STAGGER (TRNS)
	DB	01000110B	;T0= SD, T1..76= 256 BYTE DD
;
	REPT	IDSDD2 + SECSZ -$	;EXTEND TO FULL SECTOR
	LIST	OFF
	DB	0E5H
	LIST	ON
	ENDM


;******************
;
;   MESSAGES
;
;******************

MSGFL:	DB	CR,LF,LF,'******  Functions List  ******'
	DB	CR,LF,'1. Jade 128 Byte Sector Double Density -n 8"'
	DB	CR,LF,'2. Jade Single Density 8"'
	DB	CR,LF,'3. Standard 3740 8"'
	DB	CR,LF,'4. Jade 256 Byte Sector Double Density 8"'
	DB	CR,LF,'USE CTRL-C TO RE-BOOT.'
	DB	CR,LF,LF,'Enter function number: $'

MSGSE:	DB	CR,LF,LF
LTRSE:	DB	'  Is not a valid selection.$'
MSGFD:	DB	CR,LF,LF,'Write format on drive (CR to reselect): $'
MSGNC:	DB	CR,LF,LF,'Transfer incomplete$'
MSGXX:	DB	CR,LF,LF,'TYPE CR WHEN DRIVE '
DRLTR:	DB	'  IS READY. $'
NODRVM:	DB	CR,LF,'BIOS Select Error!$'
DIRQM:	DB	CR,LF,'Double Directory Size? (Y/N) - $'
FMTHDR	DB	CR,LF,'0---------1---------2---------3---------4---------5'
	DB	'---------6---------7------',CR,LF,'$'

	SUBTTL	INJECTION MODULES
;*************************************************
;
;   SINGLE DENSITY FORMATTER INJECTION MODULE
;	THIS CODE IS INTENDED TO EXECUTE WITHIN THE
;  DOUBLE D MEMORY BANK 1. ALL ABSOLUTE MEMORY REFERENCES MUST BE OFFSET.
;  THE OFFSET IS CALCULATED BY:
;	ADDR = SYMBOL - START_OF_MODULE + DD_MODULE_LOCATION
;
;*************************************************

FT3740:	EQU	$
SDOFF:	EQU	$ - FMTBG	;DETERMINE ADDR OF OFFSET
	DB	'FORMAT!S'	;CONFIRMATION TEXT
;
;	START OF CODE, SHOULD BE FMTBG + 8
;
	LD	HL,SS3740 - SDOFF
	LD	E,26		;SET # SECTORS

BG3740:	LD	B,40		;# BYTES

SRPT1:	IN	A,XPDSH		;WAIT FOR DATA REQ
	LD	A,ONES
	XOR	C
	OUT	WDDTA,A		;WRITE DATA
	DJNZ	SRPT1

	LD	B,6		;WRITE 6 0s
SRPT2:	IN	A,XPDSH
	LD	A,ZEROS
	XOR	C
	OUT	WDDTA,A
	DJNZ	SRPT2

	IN	A,XPDSH		;WRITE INDEX MARK
	LD	A,0FCH
	XOR	C
	OUT	WDDTA,A

	LD	B,26		;WRITE 26 ONES BYTES
SRPT3:	IN	A,XPDSH
	LD	A,ONES
	XOR	C
	OUT	WDDTA,A
	DJNZ	SRPT3

RP3740:	LD	B,6		;WRITE 6 ZEROS BYTES
SRPT4:	IN	A,XPDSH
	LD	A,ZEROS
	XOR	C
	OUT	WDDTA,A
	DJNZ	SRPT4

	IN	A,XPDSH		;WRITE ID MARK
	LD	A,0FEH
	XOR	C
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE TRACK #
	IN	A,WDTRK
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE SIDE #
	LD	A,0
	XOR	C
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE SECTOR #
	LD	A,(HL)
	XOR	C
	OUT	WDDTA,A

	INC	HL
	IN	A,XPDSH		;WRITE SECTOR SIZE
	LD	A,0		;(128)
	XOR	C
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE CRC
	LD	A,0F7H
	XOR	C
	OUT	WDDTA,A

	LD	B,11		;WRITE 11 ONES
SRPT5:	IN	A,XPDSH
	LD	A,ONES
	XOR	C
	OUT	WDDTA,A
	DJNZ	SRPT5

	LD	B,6		;WRITE 6 ZEROS BYTES
SRPT6:	IN	A,XPDSH
	LD	A,ZEROS
	XOR	C
	OUT	WDDTA,A
	DJNZ	SRPT6

	IN	A,XPDSH		;WRITE DATA MARK
	LD	A,0FBH
	XOR	C
	OUT	WDDTA,A

	LD	B,SECSZ		;WRITE SECTOR WITH E5 BYTES
SRPT7:	IN	A,XPDSH
	LD	A,0E5H
	XOR	C
	OUT	WDDTA,A
	DJNZ	SRPT7

	IN	A,XPDSH		;WRITE CRC
	LD	A,0F7H
	XOR	C
	OUT	WDDTA,A

	LD	B,27		;WRITE 27 ONES BYTES
SRPT8:	IN	A,XPDSH
	LD	A,ONES
	XOR	C
	OUT	WDDTA,A
	DJNZ	SRPT8

	DEC	E		;# SECTORS -1
	JP	NZ,RP3740 - SDOFF	;IF ANY LEFT THEN REPEAT

	LD	HL,0		;COUNT = 0
SRPT9:	IN	A,XPDSH
	LD	A,ONES		;WRITE ONES UNTIL INTERRUPT
	XOR	C
	OUT	WDDTA,A
	INC	HL		;RETURN ONES COUNT
	JP	SRPT9 - SDOFF

;
;	SECTOR TRANSLATION TABLE, NONE FOR SINGLE DENSITY
;
SS3740:	GXLATE	26, 1


;***********************************************
;
;   DOUBLE D DOUBLE DENSITY INJECTION MODULE
;
;***********************************************

FTJ48D:	EQU	$
DDOFF:	EQU	$ - FMTBG	;DETERMINE ADDR OFFSET
	DB	'FORMAT!D'	;CONFIRMATION TEXT
;
;	EXECUTION START POINT
;
	LD	HL,SSJ48D - DDOFF	;SET PTR TO SECTOR TRANSLATION TABLE

	LD	E,48		;SECTOR COUNT

BGJ48D:	LD	B,80		;WRITE PREAMBLE - 80 4E BYTES
DRPT1:	IN	A,XPDSH
	LD	A,4EH
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT1

	LD	B,12		;WRITE 12 ZERO BYTES
DRPT10:	IN	A,XPDSH
	XOR	A,A
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT10

	LD	B,3		;WRITE GAP C2 - 3 F6 BYTES
DRPT11:	IN	A,XPDSH
	LD	A,0F6H
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT11

	IN	A,XPDSH		;WRITE INDEX MARK
	LD	A,0FCH
	XOR	C
	OUT	WDDTA,A

	LD	B,32		;WRITE GAP 1 - 32 4E BYTES
DRPT12:	IN	A,XPDSH
	LD	A,4EH
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT12

RPJ48D:	LD	B,8		;WRITE END OF GAP 3 - 8 ZERO BYTES
DRPT2:	IN	A,XPDSH
	XOR	A,A
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT2

	LD	B,3		;WRITE GAP A1 - 3 F5 BYTES
DRPT3:	IN	A,XPDSH
	LD	A,0F5H
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT3

	IN	A,XPDSH		;WRITE ID MARK
	LD	A,0FEH
	XOR	C
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE TRACK #
	IN	A,WDTRK
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE SIDE #
	XOR	A,A
	XOR	C
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE SECTOR #
	LD	A,(HL)
	XOR	C
	OUT	WDDTA,A
	INC	HL

	IN	A,XPDSH		;WRITE SECTOR SIZE
	LD	A,0		;128=0
	XOR	C
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE CRC WORD
	LD	A,0F7H
	XOR	C
	OUT	WDDTA,A

	LD	B,22		;WRITE GAP 2 - 22 4E BYTES
DRPT4:	IN	A,XPDSH
	LD	A,4EH
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT4

	LD	B,8		;WRITE 8 ZERO BYTES
DRPT5:	IN	A,XPDSH
	XOR	A,A
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT5

	LD	B,3		;WRITE GAP A1 - 3 F5 BYTES
DRPT6:	IN	A,XPDSH
	LD	A,0F5H
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT6

	IN	A,XPDSH		;WRITE DATA MARK
	LD	A,0FBH
	XOR	C
	OUT	WDDTA,A

	LD	B,SECSZ		;WRITE SECTOR DATA WITH E5 BYTES
DRPT7:	IN	A,XPDSH
	LD	A,0E5H
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT7

	IN	A,XPDSH		;WRITE CRC
	LD	A,0F7H
	XOR	C
	OUT	WDDTA,A

	LD	B,24		;WRITE GAP 3 - 24 4E BYTES
DRPT8:	IN	A,XPDSH
	LD	A,4EH
	XOR	C
	OUT	WDDTA,A
	DJNZ	DRPT8

	DEC	E		;IF SECTORS LEFT THEN REPEAT
	JP	NZ,RPJ48D - DDOFF

	LD	L,E
	LD	H,L
DRPT9:	IN	A,XPDSH
	LD	A,4EH		;WRITE GAP 4 - 4EH BYTES UNTIL INTERRUPT
	XOR	C
	OUT	WDDTA,A
	INC	HL		;COUNT NUMBER OF GAP 4 BYTES
	JR	DRPT9
;
;	DOUBLE DENSITY SKEW TABLE, SKEW 8 SEEMS OPTIMUM
;
SSJ48D:	GXLATE	48, 8


;***********************************************
;
;   DOUBLE D DOUBLE DENSITY INJECTION MODULE
; 256 BYTE SECTORS
;
;***********************************************

FTJ26D:	EQU	$
DD26OFF: EQU	$ - FMTBG	;DETERMINE ADDR OFFSET
	DB	'FORMAT!D'	;CONFIRMATION TEXT
;
;	EXECUTION START POINT
;
	LD	HL,SSJ26D - DD26OFF	;SET PTR TO SECTOR TRANSLATION TABLE

	LD	E,26		;SECTOR COUNT

BGJ26D:	LD	B,80		;WRITE PREAMBLE - 80 4E BYTES
DD261:
	IN	A,XPDSH
	LD	A,4EH
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD261

	LD	B,12		;WRITE 12 ZERO BYTES
DD2610:	IN	A,XPDSH
	XOR	A,A
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD2610

	LD	B,3		;WRITE GAP C2 - 3 F6 BYTES
DD2611:	IN	A,XPDSH
	LD	A,0F6H
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD2611

	IN	A,XPDSH		;WRITE INDEX MARK
	LD	A,0FCH
	XOR	C
	OUT	WDDTA,A

	LD	B,50		;WRITE GAP 1 - 50 4E BYTES
DD2612:	IN	A,XPDSH
	LD	A,4EH
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD2612

RPJ26D:	LD	B,12		;WRITE END OF GAP 3 - 12 ZERO BYTES
DD262:	IN	A,XPDSH
	XOR	A,A
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD262

	LD	B,3		;WRITE GAP A1 - 3 F5 BYTES
DD263:	IN	A,XPDSH
	LD	A,0F5H
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD263

	IN	A,XPDSH		;WRITE ID MARK
	LD	A,0FEH
	XOR	C
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE TRACK #
	IN	A,WDTRK
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE SIDE #
	XOR	A,A
	XOR	C
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE SECTOR #
	LD	A,(HL)
	XOR	C
	OUT	WDDTA,A
	INC	HL

	IN	A,XPDSH		;WRITE SECTOR SIZE
	LD	A,1		;1= 256
	XOR	C
	OUT	WDDTA,A

	IN	A,XPDSH		;WRITE CRC WORD
	LD	A,0F7H
	XOR	C
	OUT	WDDTA,A

	LD	B,22		;WRITE GAP 2 - 22 4E BYTES
DD264:	IN	A,XPDSH
	LD	A,4EH
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD264

	LD	B,12		;WRITE 12 ZERO BYTES
DD265:	IN	A,XPDSH
	XOR	A,A
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD265

	LD	B,3		;WRITE GAP A1 - 3 F5 BYTES
DD266:	IN	A,XPDSH
	LD	A,0F5H
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD266

	IN	A,XPDSH		;WRITE DATA MARK
	LD	A,0FBH
	XOR	C
	OUT	WDDTA,A

	LD	B,0		;WRITE SECTOR DATA - 256 E5 BYTES
DD267:	IN	A,XPDSH
	LD	A,0E5H
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD267

	IN	A,XPDSH		;WRITE CRC
	LD	A,0F7H
	XOR	C
	OUT	WDDTA,A

	LD	B,54		;WRITE GAP 3 - 54 4E BYTES
DD268:	IN	A,XPDSH
	LD	A,4EH
	XOR	C
	OUT	WDDTA,A
	DJNZ	DD268

	DEC	E		;IF SECTORS LEFT THEN REPEAT
	JP	NZ,RPJ26D - DD26OFF

	LD	L,E
	LD	H,L
DD269:	IN	A,XPDSH
	LD	A,4EH		;WRITE GAP 4 - 4EH BYTES UNTIL INTERRUPT
	XOR	C
	OUT	WDDTA,A
	INC	HL		;COUNT NUMBER OF GAP 4 BYTES
	JR	DD269
;
;	DOUBLE DENSITY SKEW TABLE, SKEW 9 SEEMS OPTIMUM
;
SSJ26D:	GXLATE	26, 9

	SUBTTL	VARIABLE DECLARATIONS
;
;	FDC COMMAND BLOCK
;
BTCMD	DB	DDFMT		;FORMAT COMMAND
BTDRV	DS	1		;DRIVE #
TRKNO:	DS	1		;TRACK NUMBER HOLD
FFLAG:	DS	1		;FORMAT FLAG (DCM)
	DW	0		;SPARES
	DB	0		;MODE CONTROLS
BTSTS	DS	1		;STATUS BYTE
	DS	4		;LOAD WORDS

BTDMA	DS	2		;ADDRESS OF INJECTION MODULE

NSECTS	DS	1		;NUMBER OF SECTORS IN TRACK
TXFLG	DS	1		;TRANSLATE SECTOR BOOLEAN FLAG
RDERR	DS	1		;READ ERROR BOOLEAN FLAG
SECTOR	DS	1		;CURRENT SECTOR

SECBUF	DS	256		;SECTOR BUFFER

CODEND	EQU	$
	END
