	.TITLE	"FORMAT - JADE DOUBLE D"
	.SBTTL	'TITLE PAGE'
;******************************************************
;						      *
;	PROGRAM ID:	FORMAT                        *
;						      *
;******************************************************
;						      *
;	PRESENTED BY:	JADE COMPUTER PRODUCTS	      *
;			4901 W. ROSECRANS BLVD.	      *
;			HAWTHORNE, CALIFORNIA	      *
;			90250,   U.S.A.		      *
;						      *
;******************************************************
;						      *
;	VERSION:	CP/M 2.2   RELEASE 2A         *
;						      *
;******************************************************
;						      *
;	WRITTEN BY:	STAN KRUMME		      *
;						      *
;******************************************************
; FORMAT  IS A SYSTEM UTILITY  WHICH PROVIDES A MEANS *
; TO WRITE A  SINGLE OR  DOUBLE DENSITY FORMAT ON ANY *
; OF DRIVES  A THROUGH D.  THIS UTILITY ALSO PROVIDES *
; A  COPY-SYSTEM-TRACKS  FEATURE.  THIS  IS  A USEFUL *
; FUNCTION FOR  FORMAT AS THE  SYSTEM  TRACKS  CAN BE *
; WRITTEN WITH THE  OPERATING SYSTEM  WHEN FORMATTED. *
; FORMAT IS 8080/8085/Z80 COMPATABLE.                 *
;******************************************************

;******************************************************
; FORMAT INJECTION MODULES ARE COMMAND COMPATABLE WITH*
; THE FOLLOWING  WESTERN  DIGITAL  CONTROLLER  CHIPS. *
; DOUBLE D  USER SWITCH 0  (U0 OR R0)  MUST BE SET TO *
; INDICATE THE  CONTROLLER CHIP  DATA  BUS  POLARITY. *
;******************************************************
;	CONTROLLER IC    	USER SW0	      *
;	-------------    	--------	      *
;	FD1791-02 (01)    	 CLOSED		      *
;	FD1793-02 (01)    	 OPENED		      *
;	FD1795-02         	 CLOSED		      *
;	FD1797-02         	 OPENED		      *
;******************************************************

;******************************************************
; RELEASE 2A:   SINGLE AND DOUBLE SIDED DRIVES CAN BE *
; FORMATED.  INSPECTION OF TWO SIDED* SIGNAL FROM THE *
; DISK DRIVE DETERMINES NUMBER OF SIDES.  WITH DOUBLE *
; SIDED DISKETTES, BOTH SIDES FORM ONE LOGICAL DISK.  *
; EACH DOUBLE DENSITY TRACK NOW CONTAINS 50 SECTORS.  *
;******************************************************
	.PAGE
	.SBTTL	"PROGRAM EQUATES"
;******************************************************
; DRIVER MODULE DEFINITIONS			      *
;******************************************************

LF	==	00AH		;ASCII LINE FEED.
CR	==	00DH		;CARRAIGE RETURN.
EOM	==	'$'		;STRING TERMINATOR.
TPA	==	0100H		;TRANSIENT PROGRAM.
TRK.0	==	0		;TRACK 0.
TRK.1	==	1		;TRACK 1.
TRK.2	==	2		;TRACK 2.
SEC.SZ	==	128		;128 BYTES PER SECTOR.
ID.SEC	==	1		;ID SECTOR NUMBER.
REBOOT	==	0		;REBOOT ADDRESS.
BS.PTR	==	0001H		;WARM ADDR POINTER.
NO.LOG	==	01H		;REQUEST NO LOG-ON.
FT.ERC	==	11111110B	;FORMAT ERROR MASK.
FT.TSM	==	00000001B	;TWO SIDED MASK.

;******************************************************
; INJECTION MODULE DEFINITIONS			      *
;******************************************************

FMT.EA	==	1700H		;FORMAT EXEC ADDRESS.
WD.TRK	==	005H		;DOUBLE D TRACK PORT.
WD.DTA	==	007H		;DOUBLE D DATA PORT.
XP.DSH	==	80H		;DATA SYNC HOLD PORT.
ZEROS	==	00000000B	;ALL ZERO BYTE.
ONES	==	11111111B	;ALL ONES BYTE.

;******************************************************
; BDOS CALL - VECTOR NUMBERS			      *
;******************************************************

BDOS	==	0005H		;SYSTEM CALL ADDR.
BC.PTX	==	009H		;PRINT STRING CONSOLE.
BC.RCB	==	00AH		;READ CONSOLE BUFFERD.

;******************************************************
; ASSEMBLER DIRECTIVES				      *
;******************************************************

	.I8080
	.PABS
	.PHEX
	.XLINK
	.LOC	TPA

;******************************************************

	.PAGE
	.SBTTL	'PROGRAM START'
;******************************************************
; PROGRAM BEGINS				      *
;******************************************************

BEGIN:	JMP	INIT		;GO TO INITIALIZE.

;******************************************************
; ASCII IDENTIFICATION INSERT			      *
;******************************************************

	.ASCII	'JADE COMPUTER PRODUCTS '
	.ASCII	'DOUBLE D - FORMAT 8" '
	.ASCII	'VERSION 2.2 RELEASE 2A '

;******************************************************
; SET STACK POINTER AND ISSUE LOG-ON		      *
;******************************************************

INIT:	LXI	SP,SP.TOP	;SET STACK POINTER.
	LXI	D,MSG.BG	;LOAD MESSAGE ADDR.
	CALL	MSG.OT		;ISSUE MESSAGE.

;******************************************************
; LOAD BIOS VECTORS JUMP TABLE - WARM THRU FORMAT     *
;******************************************************

	LXI	B,BS.VSZ	;SET BIOS VECTORS SIZE.
	LXI	D,BS.WRM	;SET FORMAT TABLE.
	LHLD	BS.PTR		;WARM VECTOR POINTER.
	CALL	B.MOVE		;BLOCK MOVE VECTORS.

;******************************************************
; SELECT DRIVE TO FORMAT ON			      *
;******************************************************

	LXI	H,MSG.FD	;FORMAT ON DRIVE MSG.
	CALL	SEL.DR		;CALL SELECT DRIVE.
	STA	FD.NBR		;FORMAT DRIVE NMBR.

;******************************************************
	.PAGE
;******************************************************
; DISPLAY FUNCTIONS LIST			      *
;******************************************************

LIST:	LXI	D,MSG.FL	;FUNCTIONS MSG ADDR.
	CALL	MSG.OT		;ISSUE THIS MESSAGE.

;******************************************************
; INQUIRE SELECTION 				      *
;******************************************************

SELECT:	LXI	D,MSG.SF	;SELECT FUNCTION MSG.
	CALL	MSG.OT		;ISSUE THIS MESSAGE.
	CALL	CNS.IN		;GET CONSOLE CHARACTER.
	LDA	RC.NBR		;LOAD BUFFER SIZE.
	CPI	1		;CHECK FOR 1 CHARACTER.
	JNZ	SELECT		;OTHER THAN 1 TOO BAD.

;******************************************************
; SELECT FUNCTION DRIVER			      *
;******************************************************

	LDA	RC.TXT+0	;LOAD CONSOLE CHAR.
	CPI	"1"
	JZ	FUN.1		;FMT DOUBLE DENSITY.
	CPI	"2"
	JZ	FUN.2		;FMT SINGLE DENSITY.
	CPI	"3"
	JZ	FUN.3		;FMT 3740.
	CPI	"4"
	JZ	FUN.4		;READ SYSTEM TRACKS.
	CPI	"5"
	JZ	FUN.5		;WRITE SYSTEM TRACKS.
	CPI	"*"
	JZ	FMT.ST		;FORMAT SYSTEM TRACKS.
	CPI	"'"
	JZ	RST.7		;DDT TRAP.

;******************************************************
; MUST BE A BAD CHOICE				      *
;******************************************************

	LXI	D,MSG.SE	;SELECT ERROR MESSAGE.
	CALL	MSG.OT		;ISSUE MESSAGE.
	JMP	LIST		;DIPLAY LIST AGAIN.

;******************************************************
	.PAGE
	.SBTTL	"FUNCTION CONTROLLERS"
;******************************************************
; FUNCTION 1 - FORMAT IN DOUBLE DENSITY		      *
;******************************************************

FUN.1:	LDA	DD.FLG		;LOAD DDENS FLAGS.
	STA	F.FLAG		;STORE FORMAT FLAGS.
	MVI	A,TRK.0		;TRACK 0.
	STA	TRK.NO		;SET TRACK NUMBER.
	CALL	FMT.SD		;FORMAT TRACK SDENS.
	JNZ	TRK.ER		;JUMP ERROR DETECTED.
	MVI	A,TRK.1		;TRACK 1 VALUE.
	STA	TRK.NO		;SET TRACK NUMBER.
..REPT:	CALL	FMT.DD		;FORMAT TRACK DDENS.
	JNZ	TRK.ER		;JUMP ERROR DETECTED.
	CALL	TRK.NX		;SET FOR NEXT TRACK.
	JZ	..REPT		;FORMAT NEXT TRACK.
..ID:	CALL	WDD.ID		;WRITE DDENS ID SECTOR.
	JMP	SELECT		;SELECT NEW FUNCTION.

;******************************************************
; FUNCTION 3 - FORMAT STANDARD 3740 - SINGLE SIDED    *
;******************************************************

FUN.3:	MVI	A,0		;3740 SDENS FLAGS.
	STA	F.FLAG		;STORE FORMAT FLAGS.
	MVI	A,TRK.0		;TRACK 0.
	STA	TRK.NO		;SET TRACK NUMBER.
..REPT:	CALL	FMT.SD		;FORMAT TRACK SDENS.
	JNZ	TRK.ER		;JUMP ERROR DETECTED.
	CALL	TRK.NX		;SET FOR NEXT TRACK.
	JZ	..REPT		;FORMAT NEXT TRACK.
	JMP	SELECT		;SELECT NEW FUNCTION.

;******************************************************
; FUNCTION 4 - READ SYSTEM TRACKS		      *
;******************************************************

FUN.4:	LXI	H,MSG.RS	;READ DRIVE MSG.
	CALL	SEL.DR		;SELECT READ SYS DRV.
	MVI	A,'R'		;READ TRANSFER CODE.
	STA	TF.DIR		;SET TRANSFER DIRC.
	STA	SYS.RF		;SET SYSTEM READ FLAG.
	CALL	TRNSFR		;READ SYSTEM TRACKS.
	LDA	FD.NBR		;GET FORMAT DRV NMBR.
	MOV	C,A		;PUT INTO C REG.
	MVI	E,NO.LOG	;INSURE NO LOGON.
	CALL	BS.DSK		;BIOS SELECT DISK.
	JMP	SELECT		;RESELECT FUNCTION.

;******************************************************
	.PAGE
;******************************************************
; FUNCTION 2 - FORMAT IN SINGLE DENSITY		      *
;******************************************************

FUN.2:	LDA	SD.FLG		;LOAD SDENS FLAGS.
	STA	F.FLAG		;STORE FORMAT FLAGS.
	MVI	A,TRK.0		;TRACK 0.
	STA	TRK.NO		;SET TRACK NUMBER.
	CALL	FMT.SD		;FORMAT TRACK SDENS.
	JNZ	TRK.ER		;JUMP ERROR DETECTED.
	MVI	A,TRK.1		;TRACK 1
	STA	TRK.NO		;SET TRACK NUMBER.
	CALL	FMT.DD		;FORMAT TRACK DDENS.
	JNZ	TRK.ER		;JUMP ERROR DETECTED.
	MVI	A,TRK.2		;TRACK 2.
	STA	TRK.NO		;SET TRACK NUMBER.
..REPT:	CALL	FMT.SD		;FORMAT TRACK SDENS.
	JNZ	TRK.ER		;JUMP ERROR DETECTED.
	CALL	TRK.NX		;SET FOR NEXT TRACK.
	JZ	..REPT		;FORMAT NEXT TRACK.
..ID:	CALL	WSD.ID		;WRITE SDENS ID SECTOR.
	JMP	SELECT		;SELECT NEW FUNCTION.

;******************************************************
; NON DOCUMENTED FUNCTION - FORMAT JADE SYSTEM TRACKS *
;******************************************************
; USED FOR SPECIAL PURPOSE - NOT NEEDED BY END USER   *
;******************************************************

FMT.ST:	LDA	SD.FLG		;LOAD SDENS FLAGS.
	STA	F.FLAG		;STORE FORMAT FLAGS.
	MVI	A,TRK.0		;TRACK 0.
	STA	TRK.NO		;SET TRACK NUMBER.
	CALL	FMT.SD		;FORMAT TRACK SDENS.
	JNZ	TRK.ER		;JUMP ERROR DETECTED.
	MVI	A,TRK.1		;TRACK 1
	STA	TRK.NO		;SET TRACK NUMBER.
	CALL	FMT.DD		;FORMAT TRACK DDENS.
	JNZ	TRK.ER		;JUMP ERROR DETECTED.
	CALL	WSD.ID		;WRITE SDENS ID SECTOR.
	JMP	SELECT		;SELECT NEW FUNCTION.

;******************************************************
	.PAGE
;******************************************************
; FUNCTION 5 - WRITE SYSTEM TRACKS		      *
;******************************************************

FUN.5:	LDA	SYS.RF		;LOAD SYSTEM READ FLAG.
	CPI	'R'		;TEST IF READ CODE.
	JNZ	..NSYS		;JUMP IF NO SYSTEM.
	MVI	A,'W'		;WRITE TRANSFER CODE.
	STA	TF.DIR		;SET TRANSFER DIRC.
	CALL	TRNSFR		;WRITE SYSTEM TRACKS.
	JMP	SELECT		;WRITE ANOTHER DISK.
..NSYS:	LXI	D,MSG.NR	;NO SYSTEM LOADED MSG.
	CALL	MSG.OT		;ISSUE THIS MESSAGE.
	JMP	SELECT		;SELECT NEW FUNCTION.

;******************************************************
; NEXT TRACK SELECT ROUTINE			      *
;******************************************************

TRK.NX:	LDA	TRK.MX		;LOAD MAX TRACK NMBR.
	MOV	B,A		;SAVE IN REG B.
	LDA	TRK.NO		;GET THIS TRACK NO.
	CMP	B		;CHECK FOR LAST TRACK.
	JZ	..DONE		;JUMP IF LAST TRACK.
	INR	A		;GET NEXT TRACK.
	STA	TRK.NO		;STORE NEXT TRACK.
	XRA	A		;SET ZERO FLAG.
	RET			;RETURN TO CALLER.
..DONE:	MVI	A,ONES		;SET ALL ONES.
	ANA	A		;SET FLAG NOT ZERO.
	RET			;LAST TRACK EXIT.

;******************************************************
; FORMAT TRACK ERROR				      *
;******************************************************

TRK.ER:	LXI	D,MSG.FE	;FORMAT ERROR MSG ADDR.
	CALL	MSG.OT		;DISPLAY MESSAGE.
	JMP	SELECT		;SELECT NEW FUNCTION.

;******************************************************
	.PAGE
	.SBTTL	'CONSOLE AND BIOS COMMUNICATION'
;******************************************************
; MESSAGE DISPLAY ROUTINE			      *
;******************************************************

MSG.OT:	MVI	C,BC.PTX	;PRINT TEXT VECTOR.
	JMP	BDOS		;CONTINUE IN BDOS.

;******************************************************
; CONSOLE INPUT ROUTINE				      *
;******************************************************

CNS.IN:	LXI	D,RC.BUF	;KEYBOARD BUFFER ADDR.
	MVI	C,BC.RCB	;BDOS CONSOLE BUF READ.
	JMP	BDOS		;CONTINUE IN BDOS.

;******************************************************
; BIOS VECTOR DEFINITIONS			      *
;******************************************************

BS.WRM:	JMP	0		;RELOAD CCP/BDOS.
	JMP	0		;GET CONSOLE STATUS.
	JMP	0		;CONSOLE CHAR INPUT.
	JMP	0		;CONSOLE CHAR OUTPUT.
	JMP	0		;PRINTER OUTPUT.
	JMP	0		;PUNCH CHARACTER OUT.
	JMP	0		;READER INPUT.
	JMP	0		;HOME SELECTED DRIVE.
BS.DSK:	JMP	0		;SELECT DISK DRIVE.
BS.TRK:	JMP	0		;SET TRACK NUMBER.
BS.SEC:	JMP	0		;SET SECTOR NUMBER.
BS.DMA:	JMP	0		;SET TRANSFER ADDR.
BS.RDS:	JMP	0		;READ DISK SECTOR.
BS.WRS:	JMP	0		;WRITE DISK SECTOR.
	JMP	0		;LIST DEV STATUS.
	JMP	0		;SECTOR TRANSLATE.
BS.FMT:	JMP	0		;FORMAT DISK TRACK.
BS.VSZ	==	.-BS.WRM	;CALCULATE SIZE.

;******************************************************
; BLOCK MOVE SUBROUTINE				      *
;******************************************************

B.MOVE:	MOV	A,M		;GET BYTE
	INX	H		;INC SOURCE.
	STAX	D		;STORE BYTE.
	INX	D		;INC DESTINATION.
	DCX	B		;ONE LESS TO DO.
	MOV	A,B		;GET B REG.
	ORA	C		;OR IN C REG.
	JNZ	B.MOVE		;REPEAT FOR LENGTH.
	RET			;RETURN CALLER.

;******************************************************
	.PAGE
	.SBTTL	"WRITE DISKETTE IDENTITY"
;******************************************************
; WRITE ID SECTOR				      *
;******************************************************

;*******( SET TRANSFER ADDRESS )***********************

WSD.ID:	LXI	B,IDS.SS	;ID SECTOR ADDRESS.
	LDA	TS.FLG		;GET TWO SIDES FLG.
	ANA	A		;TEST.
	JZ	WRT.ID		;JUMP ONE SIDED.
	LXI	B,IDS.DS	;DOUBLE SIDED.
	JMP	WRT.ID		;JUMP TWO SIDED.
WDD.ID:	LXI	B,IDS.SD	;ID SECTOR ADDRESS.
	LDA	TS.FLG		;GET TWO SIDES FLG.
	ANA	A		;TEST.
	JZ	WRT.ID		;JUMP ONE SIDED.
	LXI	B,IDS.DD	;DOUBLE SIDED.
WRT.ID:	CALL	BS.DMA		;BIOS TRANSFER ADDR.

;*******( SET TRACK AND SECTOR NUMBERS )***************

	MVI	C,TRK.0		;TRACK 0 SET.
	CALL	BS.TRK		;BIOS SET TRACK.
	MVI	C,ID.SEC	;ID SECTOR VALUE.
	CALL	BS.SEC		;BIOS SET SECTOR.
	
;*******( PERFORM WRITE SECTOR )***********************

	CALL	BS.WRS		;BIOS WRITE SECTOR.
	ORA	A		;SET CONDITION CODES.
	RZ			;RETURN USER GOOD.
	LXI	D,MSG.NC	;TRANSFER INCOMPLETE.
	CALL	MSG.OT		;ISSUE MESSAGE.
	MVI	A,ONES		;SET ACUMULATOR.
	ANA	A		;SET FLAGS NOT ZERO.
	RET			;ERROR RETURN.

;******************************************************
	.PAGE
	.SBTTL	"FORMAT TRACK DRIVER LINKAGE"
;******************************************************
; FORMAT TRACK DRIVER				      *
;******************************************************

;*******( DENSITY ENTRIES )****************************

FMT.SD:	LXI	B,FT3740	;LOAD INJECTION ADDR.
	JMP	ST.DMA		;GO SET DMA ADDR.
FMT.DD:	LXI	B,FTJ50D	;LOAD INJECTION ADDR.

;*******( SET INJECTION MODULE ADDRESS )***************

ST.DMA:	CALL	BS.DMA		;SET TRANSFER ADDRESS.

;*******( SET TRACK NUMBER AND DCM FLAGS )*************

	LDA	TRK.NO		;LOAD TRACK NMBR.
	MOV	C,A		;PUT INTO C REGISTER.
	CALL	BS.TRK		;SET TRACK NMBR.

	LDA	F.FLAG		;LOAD DCM FLAG.
	MOV	C,A		;DCM FLAGS.
	CALL	BS.SEC		;SET DCM FLAGS.
	
;*******( PERFORM FORMAT TRACK )***********************

	CALL	BS.FMT		;BIOS WRITE TRACK.
	STA	FT.STS		;FORMAT STATUS.
	ANI	FT.ERC		;TEST FOR ERRORS.
	RNZ			;ERROR EXIT.

;*******( SET CONTROLS FOR SIDE/SIDES )****************

	LDA	FT.STS		;GET STATUS.
	ANI	FT.TSM		;TEST TWO SIDES FLAG.
	STA	TS.FLG		;STORE FLAG.
	JNZ	..TWSD		;TWO SIDES IS A 1.
	MVI	A,77-1		;SINGLE SIDED MAX.
	JMP	..EXIT		;EXIT.
..TWSD:	MVI	A,2*77-1	;DOUBLE SIDED MAX.
..EXIT:	STA	TRK.MX		;SET MAX TRACK.
	XRA	A		;SET ZERO FLAG.
	RET			;RETURN TO CALLER.

;******************************************************
	.PAGE
	.SBTTL	"SYSTEM TRACKS TRANSFER SUBROUTINE"
;******************************************************
; SYSTEM TRACKS TRANSFER FUNCTION - ENTRY POINT	      *
;******************************************************

;*******( TRANSFER INITIALIZE )************************

TRNSFR:	LXI	H,ST.LST	;ADDR OF TRANSFER LIST.
	SHLD	TF.PTR		;SET TRANSFER POINTER.

;*******( SET BIOS TRACK NUMBER )**********************

..REPT:	CALL	..PLST		;POP BYTE FROM LIST.
	CPI	EOL		;TEST FOR END OF LIST.
	RZ			;EXIT TRANSFER.
	CALL	BS.TRK		;BIOS SET TRACK.

;*******( SET BIOS SECTOR NUMBER )*********************

	CALL	..PLST		;POP BYTE FROM LIST.
	CALL	BS.SEC		;BIOS SET SECTOR.

;*******( SET BIOS TRANSFER ADDRESS )******************

	CALL	..PLST		;POP BYTE FROM LIST.
	CALL	..ADDR		;CALCULATE ADDRESS.
	CALL	BS.DMA		;BIOS TRANSFER ADDR.

;*******( SECTOR TRANSFER OPERATION )******************

	LXI	H,..RETN	;LOAD RETURN ADDRESS.
	PUSH	H		;PUSH ONTO STACK.
	LDA	TF.DIR		;LOAD TRNSFR DIRECTION.
	CPI	'W'		;SEE IF WRITE FUNCTION.
	JZ	BS.WRS		;BIOS WRITE SECTOR.
	CPI	'R'		;SEE IF READ FUNCTION.
	JZ	BS.RDS		;BIOS READ SECTOR.
	MVI	A,ONES		;ERROR CODE NOT R/W.
..RETN:	ORA	A		;SET CONDITION CODES.
	JZ	..REPT		;DO SOME MORE.

;*******( ENCOUNTERED DIFFICULTY )*********************

	LXI	D,MSG.NC	;MESSAGE ADDRESS.
	CALL	MSG.OT		;SEND MESSAGE.
	RET			;GO HOME.

;******************************************************
	.PAGE
;******************************************************
; POP LIST SUBROUTINE				      *
;******************************************************

..PLST:	LHLD	TF.PTR		;LOAD LIST POINTER.
	MOV	C,M		;GET ITEM NUMBER.
	INX	H		;INCREMENT POINTER.
	SHLD	TF.PTR		;STORE LIST POINTER.
	MOV	A,C		;MOVE C TO ACUM.
	RET			;RETURN TO CALLER.

;******************************************************
; GET MEMORY ADDRESS SUBROUTINE			      *
;******************************************************

..ADDR:	ANA	A		;CLEAR CARRY BIT.
	RAR			;DIVIDE BY 2.
	MOV	B,A		;HI ORDER TO B REG.
	MVI	A,0		;CLEAR ACUMULATOR.
	RAR			;CARRY BIT TO MSB.
	MOV	C,A		;LO ORDER TO C REG.
	LHLD	TF.INX		;LOAD TRANSFER INDEX.
	DAD	B		;ADD IN OFFSET.
	MOV	B,H		;HALF MOV BC,HL.
	MOV	C,L		;THE OTHER (HA!)
	RET			;RETURN TO CALLLER.

;******************************************************
	.PAGE
	.SBTTL	'SYSTEM TRACKS TRANSFER LIST'
;******************************************************
; THE FOLLOWING  IS A  LIST OF  SYSTEM TRACK  SECTORS *
; USED  BY THE  TRNSFR  SUBROUTINE.   THERE ARE THREE *
; ENTRIES PER SECTOR.   1ST IS TRACK NUMBER.   2ND IS *
; SECTOR NUMBER.   3RD IS MEMORY LOAD OFFSET.         *
;******************************************************
; SECTORS 2 THRU 26 ARE TRANSFERED ON TRACK 0. SECTOR *
; 1 IS NOT TRANSFERED,  THIS IS THE  IDENTITY SECTOR. *
; TRACK 0 SECTOR ARE LOCATED IN SEQUENCIAL ORDER,  SO *
; THIS LIST IS STAGGERED.   SECTORS  1  THRU  48  ARE *
; TRANSFERED ON TRACK 1.			      *
;******************************************************

TK0	==	0		;DEFINE TRACK 0.
TK1	==	1		;DEFINE TRACK 1.
EOL	==	0FFH		;DEFINE END OF LIST.

;******************************************************

ST.LST:	.BYTE	TK0,04,04,TK0,08,08,TK0,12,12,TK0,16,16
	.BYTE	TK0,20,20,TK0,24,24,TK0,02,02,TK0,06,06
	.BYTE	TK0,10,10,TK0,14,14,TK0,18,18,TK0,22,22
	.BYTE	TK0,26,26,TK0,05,05,TK0,09,09,TK0,13,13
	.BYTE	TK0,17,17,TK0,21,21,TK0,25,25,TK0,03,03
	.BYTE	TK0,07,07,TK0,11,11,TK0,15,15,TK0,19,19
	.BYTE	TK0,23,23

	.BYTE	TK1,01,27,TK1,02,28,TK1,03,29,TK1,04,30
	.BYTE	TK1,05,31,TK1,06,32,TK1,07,33,TK1,08,34
	.BYTE	TK1,09,35,TK1,10,36,TK1,11,37,TK1,12,38
	.BYTE	TK1,13,39,TK1,14,40,TK1,15,41,TK1,16,42
	.BYTE	TK1,17,43,TK1,18,44,TK1,19,45,TK1,20,46
	.BYTE	TK1,21,47,TK1,22,48,TK1,23,49,TK1,24,50
	.BYTE	TK1,25,51,TK1,26,52,TK1,27,53,TK1,28,54
	.BYTE	TK1,29,55,TK1,30,56,TK1,31,57,TK1,32,58
	.BYTE	TK1,33,59,TK1,34,60,TK1,35,61,TK1,36,62
	.BYTE	TK1,37,63,TK1,38,64,TK1,39,65,TK1,40,66
	.BYTE	TK1,41,67,TK1,42,68,TK1,43,69,TK1,44,70
	.BYTE	TK1,45,71,TK1,46,72,TK1,47,73,TK1,48,74

	.BYTE	EOL		;END OF LIST.

;******************************************************
	.PAGE
	.SBTTL	"SELECT DRIVE SUBROUTINE"
;******************************************************
; SELECT DRIVE THRU BIOS			      *
;******************************************************

;*******( DISPLAY MESSAGE AND WAIT FOR RESPONSE )******

SEL.DR:	SHLD	MSG.SV		;SAVE MESSAGE ADDRESS.
..REPT:	LHLD	MSG.SV		;LOAD MESSAGE ADDRESS.
	XCHG			;PUT ADDRESS IN DE.
	CALL	MSG.OT		;ISSUE MESSAGE.
	CALL	CNS.IN		;CONSOLE INPUT.
	LDA	RC.NBR		;LOAD NMBR OF CHARS.
	CPI	1		;SEE IF ONE CHARACTER.
	JNZ	..REPT		;IF NOT 1 CHAR TOO BAD.

;*******( SEE IF DRIVE LETTER GOOD )*******************

	LDA	RC.TXT		;LOAD LETTER.
	SUI	'A'		;GET NUMBER.
	JC	..ILLG		;ILLEGAL, REPEAT.
	CPI	04H		;DRIVE A THRU D?
	JC	..NMBR		;GOOD NUMBER.
	SUI	'a'-'A'		;OFFSET LOWER CASE.
	JC	..ILLG		;ILLEGAL, REPEAT.
	CPI	04H		;LOWER a THRU d?
	JC	..NMBR		;LEGAL DRIVE.

;*******( EXIT TO RESELECT FUNCTION )******************

..ILLG:	LXI	D,MSG.SE	;'SELECT ERROR'
	CALL	MSG.OT		;ISSUE MESSAGE.
	JMP	..REPT		;REPEAT SELECTION.

;*******( VALID DRIVE NUMBER )*************************

..NMBR:	STA	SV.NBR		;SAVE DRIVE NUMBER.
	MOV	C,A		;DRIVE NMBR TO C.
	MVI	E,NO.LOG	;LOG ON VECTOR.
	CALL	BS.DSK		;BIOS SELECT DISK.
	MOV	A,H		;CHECK RETURN ADDR.
	ORA	L		;SET FLAGS Z/NZ.
	JZ	..ILLG		;BIOS SAID NOGO IF 0.
	LDA	SV.NBR		;GET NUMBER.
	RET			;RETURN CALLER.

;******************************************************
	.PAGE
	.SBTTL	"SMALL ROUTINES AND DATA AREAS"
;******************************************************
; SOFTWARE TRAPS - DDT EXIT			      *
;******************************************************

RST.7:	RST	7		;EXIT FORMAT.
	JMP	SELECT		;RETURN FOR SELECTION.

;******************************************************
; WORKING VARIABLES				      *
;******************************************************

TF.INX:	.WORD	0F80H	;TRANSFER INDEX.
TF.PTR:	.WORD	0	;LIST ADDRESS POINTER.
TF.DIR:	.BYTE	0	;TRANSFER DIRECTION.
MSG.SV:	.WORD	0	;MESSAGE SAVE ADDRESS.
FT.STS:	.BYTE	0	;FORMAT STATUS SAVE.
TS.FLG:	.BYTE	0	;TWO SIDED DRIVE FLAG.
TRK.NO:	.BYTE	0	;TRACK NUMBER HOLD.
TRK.MX:	.BYTE	0	;LAST TRACK LIMIT.
SEC.NO:	.BYTE	0	;SECTOR NUMBER HOLD.
F.FLAG:	.BYTE	0	;FORMAT FLAG (DCM).
SYS.RF:	.BYTE	0	;SYSTEM TRACK READ FLAG.
SV.NBR:	.BYTE	0	;SEL.DV TEMP STORAGE.
FD.NBR:	.BYTE	0	;FORMAT DRIVE NUMBER.

STACK:	.BLKW	16	;PROGRAM STACK AREA.
SP.TOP	==	.	;TOP OF STACK.

;******************************************************
; CONSOLE INPUT BUFFER AREA			      *
;******************************************************

CB.SIZ	==	20	;CONSOLE BUFFER SIZE SET.

RC.BUF:	.BYTE	CB.SIZ	;DECLARE BUFFER SIZE.
RC.NBR:	.BYTE	0	;INPUT STRING SIZE.
RC.TXT:	.BLKB	CB.SIZ	;RESERVE CONSOLE BUFFER AREA.

;******************************************************
	.PAGE
	.SBTTL	"IDENTITY SECTORS"
;******************************************************
; JADE SINGLE DENSITY - IDENTITY SECTORS	      *
;******************************************************

IDS.SS:	.ASCII	"Jade DD S Sided S Density Format "

	.LOC	IDS.SS+20H	;LOCATE CP/M 2.2 DPB.
	.WORD	26		;SECTORS PER TRACK.
	.BYTE	3		;BLOCK SHIFT FACTOR.
	.BYTE	7		;BLOCK MASK.
	.BYTE	0		;EXM.
	.WORD	26*75/8-1	;DISK SIZE - 1.
	.WORD	63		;DIRECTORY MAXIMUM.
	.BYTE	11000000B	;ALLOC 0.
	.BYTE	0		;ALLOC 1.
	.WORD	16		;CHECK SIZE.
	.WORD	2		;TRACK OFFSET.

	.LOC	IDS.SS+30H	;LOCATE DCM BLOCK.
	.BYTE	0		;NOT USED.
SD.FLG:	.BYTE	00000010B	;DISKETTE FLAGS.

	.LOC	IDS.SS+SEC.SZ	;EXTEND FULL SECTOR.

;******************************************************

IDS.DS:	.ASCII	"Jade DD D Sided S Density Format "

	.LOC	IDS.DS+20H	;LOCATE CP/M 2.2 DPB.
	.WORD	26		;SECTORS PER TRACK.
	.BYTE	4		;BLOCK SHIFT FACTOR.
	.BYTE	15		;BLOCK MASK.
	.BYTE	1		;EXM.
	.WORD	26*152/16-1	;DISK SIZE - 1.
	.WORD	63		;DIRECTORY MAXIMUM.
	.BYTE	10000000B	;ALLOC 0.
	.BYTE	0		;ALLOC 1.
	.WORD	16		;CHECK SIZE.
	.WORD	2		;TRACK OFFSET.

	.LOC	IDS.DS+30H	;LOCATE DCM BLOCK.
	.BYTE	0		;NOT USED.
	.BYTE	00001010B	;DISKETTE FLAGS.

	.LOC	IDS.DS+SEC.SZ	;EXTEND FULL SECTOR.

;******************************************************
	.PAGE
;******************************************************
; JADE DOUBLE DENSITY - IDENTITY SECTORS	      *
;******************************************************

IDS.SD:	.ASCII	"Jade DD S Sided D Density Format "

	.LOC	IDS.SD+20H	;LOCATE CP/M 2.2 DPB.
	.WORD	50		;SECTORS PER TRACK.
	.BYTE	4		;BLOCK SHIFT FACTOR.
	.BYTE	00001111B	;BLOCK MASK.
	.BYTE	1		;EXM.
	.WORD	50*75/16-1	;DISK SIZE - 1.
	.WORD	63		;DIRECTORY MAXIMUM.
	.BYTE	10000000B	;ALLOC 0.
	.BYTE	0		;ALLOC 1.
	.WORD	16		;CHECK SIZE.
	.WORD	2		;TRACK OFFSET.

	.LOC	IDS.SD+30H	;LOCATE DCM BLOCK.
	.BYTE	0		;NOT USED.
DD.FLG:	.BYTE	00000110B	;DISKETTE FLAGS.

	.LOC	IDS.SD+SEC.SZ	;EXTEND TO FULL SIZE

;******************************************************

IDS.DD:	.ASCII	"Jade DD D Sided D Density Format "

	.LOC	IDS.DD+20H	;LOCATE CP/M 2.2 DPB.
	.WORD	50		;SECTORS PER TRACK.
	.BYTE	5		;BLOCK SHIFT FACTOR.
	.BYTE	31		;BLOCK MASK.
	.BYTE	3		;EXM.
	.WORD	50*152/32-1	;DISK SIZE - 1.
	.WORD	127		;DIRECTORY MAXIMUM.
	.BYTE	10000000B	;ALLOC 0.
	.BYTE	0		;ALLOC 1.
	.WORD	32		;CHECK SIZE.
	.WORD	2		;TRACK OFFSET.

	.LOC	IDS.DD+30H	;LOCATE DCM BLOCK.
	.BYTE	0		;NOT USED.
	.BYTE	00001110B	;DISKETTE FLAGS.

	.LOC	IDS.DD+SEC.SZ	;EXTEND TO FULL SIZE

;******************************************************
	.PAGE
	.SBTTL	'TEXT MESSAGES'
;******************************************************
MSG.BG:		;CONSOLE SIGN ON		      *
;******************************************************

 .ASCII [CR][LF]
 .ASCII [CR][LF]'--------------------------------'
 .ASCII [CR][LF]'FORMAT UTILITY 2 - JADE DOUBLE D'
 .ASCII	[CR][LF]'--------------------------------'
 .ASCII [CR][LF][EOM]

;******************************************************
MSG.FD:		;FORMAT ON DRIVE SELECT		      *
;******************************************************

 .ASCII [CR][LF]'Select DRIVE to be FORMATTED: '[EOM]

;******************************************************
MSG.SE:		;SELECTION ERROR		      *
;******************************************************

 .ASCII [CR][LF]'NOT a VALID SELECTION '[EOM]

;******************************************************
MSG.FL:		;DISPLAY FUNCTION SELECTIONS	      *
;******************************************************

 .ASCII [CR][LF][CR][LF]
 .ASCII [CR][LF]'--------------------------------'
 .ASCII	[CR][LF]'      FUNCTIONS LIST            '
 .ASCII [CR][LF]'--------------------------------'
 .ASCII	[CR][LF]
 .ASCII [CR][LF]' 1. FORMAT  Double Density 8" '
 .ASCII [CR][LF]' 2. FORMAT  Single Density 8" '
 .ASCII	[CR][LF]' 3. FORMAT  Standard 3740  8" '
 .ASCII [CR][LF]' 4. READ    System Tracks Image  '
 .ASCII [CR][LF]' 5. WRITE   System Tracks Image  '
 .ASCII	[CR][LF]
 .ASCII [CR][LF]'--------------------------------'
 .ASCII	[CR][LF][EOM]

;******************************************************
MSG.SF:		;SELECT FUNCTION		      *
;******************************************************

 .ASCII [CR][LF]'ENTER Function NUMBER: '[EOM]

;******************************************************
	.PAGE
;******************************************************
MSG.RS:		;READ SYSTEM ON DRIVE		      *
;******************************************************

 .ASCII [CR][LF]
 .ASCII [CR][LF]'READ System from DRIVE: '[EOM]

;******************************************************
MSG.NC:		;TRANSFER INCOMPLETE		      *
;******************************************************

 .ASCII [CR][LF]
 .ASCII [CR][LF]'TRANSFER INCOMPLETE'
 .ASCII	[CR][LF][EOM]

;******************************************************
MSG.FE:		;FORMAT ERROR			      *
;******************************************************

 .ASCII [CR][LF]
 .ASCII [CR][LF]'FORMAT TRACK ERROR'
 .ASCII	[CR][LF][EOM]

;******************************************************
MSG.NR:		;SYSTEM NOT LOADED		      *
;******************************************************

 .ASCII [CR][LF]
 .ASCII [CR][LF]'SYSTEM TRACKS NOT LOADED'
 .ASCII	[CR][LF][EOM]

;******************************************************
	.PAGE
	.SBTTL	"INJECTION MODULE - MACRO DEFINITIONS"
;******************************************************
; FORMAT - TITLE BLOCK AND PAGE ALIGNMENT	      *
;******************************************************

	.DEFINE	FORMAT [NAME] = [
NAME	==	(.!0FFH)+1	;SET NEXT PAGE BOUNDRY.
	.LOC	NAME		;SET LOC TO NEXT PAGE.
OFFSET	=	FMT.EA-NAME	;DETERMINE ADDR OFFSET.
	.Z80			;NOW USE Z8O  CODE.
	.ASCII	'FORMAT!']	;INCLUDE HEADER!

;******************************************************
; DENSITY - DECLARE TYPE			      *
;******************************************************

	.DEFINE	DENSITY	[TYPE] = [
	.IFIDN	[TYPE][SINGLE], [
	.ASCII	'S'
	.EXIT]
	.IFIDN	[TYPE][DOUBLE], [
	.ASCII	'D'
	.EXIT]
	.ERROR	'INVALID DENSITY']

;******************************************************
; SECTORS - SPECIFY SEQUENCE AND NUMBER OF SECTORS    *
;******************************************************

	.DEFINE	SECTORS	[LIST,NMBR] = [
	LXI	H,LIST+OFFSET	;SECTOR SEQUENCE ADDR.
	MVI	E,NMBR]		;NUMBER OF SECTORS.

;******************************************************
; BLOCK - GENERATE A BLOCK OF CONSTANTS		      *
;******************************************************

	.DEFINE	BLOCK [COUNT,BYTE,%REPT] = [
	NMBR = COUNT		;SET EQUAL FOR NOW.
	MVI	B,NMBR		;LOAD NMBR OF BYTES.
%REPT:	IN	XP.DSH		;WAIT FOR DATA REQ.
	MVI	A,BYTE		;LOAD BYTE VALUE.
	XRA	C		;INVERT (1791-01).
	OUT	WD.DTA		;WRITE DATA PORT.
	DJNZ	%REPT]		;REPEAT FOR COUNT.

;******************************************************
	.PAGE
;******************************************************
; REPEAT - REPEAT FORMAT SECTION FOR EACH SECTOR      *
;******************************************************

	.DEFINE	REPEAT [LOCATION] = [
	DCR	E		;DEC NMBR SECTORS LEFT.
	JNZ	LOCATION+OFFSET]

;******************************************************
; ENDING - RECORD NMBR OF TRAILING BYTES WRITTEN      *
;******************************************************

	.DEFINE	ENDING	[BYTE,%REPT] = [
	LXI	H,0		;COUNT OF ZERO.
%REPT:	IN	XP.DSH		;WAIT FOR REQ.
	MVI	A,BYTE		;LOAD CONSTANT.
	XRA	C		;INVERT (1791-01).
	OUT	WD.DTA		;WRITE TO PORT.
	INX	H		;INCREMENT COUNT.
	JMP	%REPT+OFFSET	;CONTINUE.]

;******************************************************
	.PAGE
;******************************************************
; WRITE - WRITE SPECIFIC FORMAT BYTES		      *
;******************************************************

	.DEFINE	WRITE [TYPE,VALU] = [

;*******( ID ADDRESS MARK )****************************

	.IFIDN	[TYPE][ID.MARK],   [
	 IN	XP.DSH		;WAIT FOR DATA REQ.
	 MVI	A,0FEH		;ID ADDR MARK.
	 XRA	C		;INVERT (1791-01).
	 OUT	WD.DTA		;WRITE DATA PORT.
	.EXIT]			;TERMINATE MACRO

;*******( INDEX MARK )*********************************

	.IFIDN	[TYPE][INDEX.MARK], [
	 IN	XP.DSH		;WAIT FOR DATA REQ.
	 MVI	A,0FCH		;INDEX MARK.
	 XRA	C		;INVERT (1791-01).
	 OUT	WD.DTA		;WRITE DATA PORT.
	.EXIT]			;TERMINATE MACRO

;*******( DATA ADDRESS MARK )**************************

	.IFIDN	[TYPE][DATA.MARK], [
	 IN	XP.DSH		;WAIT FOR DATA REQ.
	 MVI	A,0FBH		;DATA ADDR MARK.
	 XRA	C		;INVERT (1791-01).
	 OUT	WD.DTA		;WRITE DATA PORT.
	.EXIT]			;TERMINATE MACRO

;*******( CRC )****************************************

	.IFIDN	[TYPE][CRC], [
	 IN	XP.DSH		;WAIT FOR DATA REQ.
	 MVI	A,0F7H		;GENERATE CRC.
	 XRA	C		;INVERT (1791-01).
	 OUT	WD.DTA		;WRITE DATA PORT.
	.EXIT]			;TERMINATE MACRO

;*******( EXPLICIT BYTE VALUE )************************

	.IFIDN	[TYPE][BYTE], [
	 IN	XP.DSH		;WAIT FOR DATA REQ.
	 MVI	A,VALU 		;EXPLICIT VALUE.
	 XRA	C		;INVERT (1791-01).
	 OUT	WD.DTA		;WRITE DATA PORT.
	.EXIT]

;*******( TRACK NUMBER )*******************************

	.IFIDN	[TYPE][TRACK.NO], [
	 IN	XP.DSH		;WAIT FOR REQUEST.
	 IN	WD.TRK		;GET TRACK NMBR.
	 OUT	WD.DTA		;WRITE DATA PORT.
	.EXIT]

;*******( SECTOR NUMBER )******************************

	.IFIDN	[TYPE][SECTOR.NO], [
	IN	XP.DSH		;WAIT FOR REQUEST.
	MOV	A,M		;SET SECTOR NUMBR.
	XRA	C		;INVERT (1791-01).
	OUT	WD.DTA		;WRITE DATA PORT.
	INX	H		;INC SEC-NMBR PNTR.
	.EXIT			;TERMINATE MACRO]

;*******( SIDE NUMBER )********************************

	.IFIDN	[TYPE][SIDE.NO], [
	IN	XP.DSH		;WAIT FOR REQUEST.
	MVI	A,0		;SET SIDE NUMBER.
	XRA	C		;INVERT (1791-01).
	OUT	WD.DTA		;WRITE DATA PORT.
	.EXIT			;TERMINATE MACRO]

;*******( SECTOR SIZE CODE )***************************

	.IFIDN	[TYPE][SECTOR.SIZE], [
	SEC.CD = 0FFH		;DECLARE BLANK.
	.IFIDN [VALU][128],	[SEC.CD = 000H]
	.IFIDN [VALU][256],	[SEC.CD = 001H]
	.IFIDN [VALU][512],	[SEC.CD = 002H]
	.IFIDN [VALU][1024],	[SEC.CD = 003H]
	.IFE	(SEC.CD-0FFH),	[
	.ERROR	'INVALID SECTOR SIZE']
	 IN	XP.DSH		;WAIT FOR DATA REQ.
	 MVI	A,SEC.CD	;LOAD SIZE CODE.
	 XRA	C		;INVERT (1791-01).
	 OUT	WD.DTA		;WRITE DATA PORT.
	.EXIT			;TERMINATE MACRO]

;*******( ILLEGAL EXPANSION )**************************

	.ERROR	'ILLEGAL EXPANSION']

;******************************************************
	.PAGE
	.SBTTL	'INJECTION MODULE FT3740'
	FORMAT	FT3740
	DENSITY	SINGLE
	SECTORS	SS3740,26

BG3740:	BLOCK	40,ONES
	BLOCK	6,ZEROS
	WRITE	INDEX.MARK
	BLOCK	26,ONES
RP3740:	BLOCK	6,ZEROS
	WRITE	ID.MARK
	WRITE	TRACK.NO
	WRITE	SIDE.NO
	WRITE	SECTOR.NO
	WRITE	SECTOR.SIZE,128
	WRITE	CRC
	BLOCK	11,ONES
	BLOCK	6,ZEROS
	WRITE	DATA.MARK
	BLOCK	128,0E5H
	WRITE	CRC
	BLOCK	27,ONES
	REPEAT	RP3740

	ENDING	ONES

SS3740:	.BYTE	 1, 2, 3, 4, 5, 6, 7, 8, 9,10
	.BYTE	11,12,13,14,15,16,17,18,19,20
	.BYTE	21,22,23,24,25,26

	.PAGE
	.SBTTL	'INJECTION MODULE FTJ50D'
	FORMAT	FTJ50D
	DENSITY	DOUBLE
	SECTORS	SSJ50D,50

BGJ50D:	BLOCK	80,04EH
RPJ50D:	BLOCK	8,ZEROS
	BLOCK	3,0F5H
	WRITE	ID.MARK
	WRITE	TRACK.NO
	WRITE	SIDE.NO
	WRITE	SECTOR.NO
	WRITE	SECTOR.SIZE,128
	WRITE	CRC
	BLOCK	22,04EH
	BLOCK	12,ZEROS
	BLOCK	3,0F5H
	WRITE	DATA.MARK
	BLOCK	128,0E5H
	WRITE	CRC
	BLOCK	17,04EH
	REPEAT	RPJ50D

	ENDING	ONES

SSJ50D:	.BYTE	 1,11,21,31,41
	.BYTE	 2,12,22,32,42
	.BYTE	 3,13,23,33,43
	.BYTE	 4,14,24,34,44
	.BYTE	 5,15,25,35,45
	.BYTE	 6,16,26,36,46
	.BYTE	 7,17,27,37,47
	.BYTE	 8,18,28,38,48
	.BYTE	 9,19,29,39,49
	.BYTE	10,20,30,40,50
	.END
