;FORMAT1/ASM - Format Program
	TITLE	<FORMAT - LS-DOS 6.3>
	SUBTTL	'<Format Execution Code>'
;
PASSWORD	EQU	42E0H
RLS	EQU	63H
LF	EQU	10
CR	EQU	13
CRT3	EQU	3C00H
CRT4	EQU	0F800H
;
*GET	SVCMAC:3		;SVC Macro equivalents
*GET	COPYCOM:3		;Copyright message
*LIST	ON
;
	ORG	2600H
;
	IF	@MOD4
BOOTST$	DB	9DH		;Boot step rate offset
	ENDIF
	IF	@MOD2
BOOTST$	DB	03H
	ENDIF
;
GOFMT	BIT	4,(IY+4)	;Jump if alien controller
	JP	NZ,HRDRV
FMTTBL	LD	DE,0		;P/u table pointer
	LD	A,(DE)		;P/u # of sectors to fmt
	INC	DE		;Adj for zero offset
	LD	(SECTRK),A
	LD	B,A
	BIT	5,(IY+4)	;Need twice as many
	JR	Z,$+3		;  if 2-sided drive
	RLCA
	LD	(SECCYL),A
SYSPRM	LD	HL,0		;P/u system info parm
	LD	A,H		;Don't format if system
	OR	L		;  info only is req
	JP	NZ,MOVFREE
	LD	A,(DE)		;P/u track skew
	INC	DE
	LD	(TRKSKEW+1),A
	LD	(SECSKEW+1),DE	;Format sector skew
;
;	Index past sector info
;
	INC	A		;Add DE -> begin of sec #
	ADD	A,B		;B -> # of sectors/side
	ADD	A,E		; A+1 -> a code byte
	LD	E,A
	ADC	A,D
	SUB	E
	LD	D,A
	LD	HL,FORMAT	;Buffer for format data
	LD	BC,HITBUF	;Tempy ptrs to trk,sect info
;
;	Create the formatting data without trk,sect info
;
FMTDAT	LD	A,(DE)		;P/u table format byte
	INC	DE		;Bump table ptr
	CP	0F1H		;Start of cylinder?
	JR	Z,CODF1
	CP	0F2H		;Start of track trailer?
	JR	Z,CODF2
	CP	0F3H		;Start of track ID info?
	JR	Z,CODF3
	CP	0F4H		;End of table parms?
	JR	Z,CODF4
	CP	0F5H		;Start of data?
	PUSH	BC
	JR	NZ,CODE1	;Go if not
;
;	Write 2 byte data pattern to format buffer
;
	LD	A,(DE)		;P/u length to write
	INC	DE		;Bump to 1st data byte
	LD	B,A		;Xfer length to B
	LD	A,(DE)		;P/u a data byte
	INC	DE		;Bump again for 2nd byte
	LD	C,A		;Xfer 1st byte
	LD	A,(DE)		;P/u 2nd byte
CODF5	LD	(HL),C		;Stuff into buf
	INC	HL
	LD	(HL),A
	INC	HL
	DJNZ	CODF5		;Loop til xfered
	JR	CODRET
;
;	Xfer bytes to the format buffer area
;	A => count to move
;	DE=> data byte to duplicate
;
CODE1	LD	B,A		;Count to B
	LD	A,(DE)		;P/u data byte to move
CODE1A	LD	(HL),A		;Fill buf with byte
	INC	HL
	DJNZ	CODE1A		;Loop til done
CODRET	POP	BC
	INC	DE		;Bump table ptr
	JR	FMTDAT		;Back for more
;
;	Save the current table posn and the number of
;	sectors per cylinder on the stack.
;
CODF1	LD	A,(SECTRK)	;P/u # of sectors/side
CODF1A	PUSH	DE		;Save table pointer
	PUSH	AF		;Save value
	JR	FMTDAT
;
;	Done with a sector. Are there more on this cyl?
;
CODF2	POP	AF		;Count down the # of
	DEC	A		;  sectors to format
	JR	Z,CODF2A	;Go if last one done
	POP	DE		;Recover table ptr
	JR	CODF1A		;Loop for more
;
CODF2A	POP	AF		;Clean the stack
	JR	FMTDAT		;  and finish off the cyl
;
;	Build a table of the location in the format buffer of
;	the track and sector ID bytes, to be filled in during
;	the actual formatting.
;
CODF3	LD	A,L		;Stuff pointer to where
	LD	(BC),A		;  track & sector info
	INC	BC		;  is to be placed
	LD	A,H
	LD	(BC),A
	INC	BC
	JR	FMTDAT
;
;	Finished building format cyl info. Terminate the ID table
;	with an extra 256 bytes in case of overrun.
;
CODF4	LD	(VERSKEW+1),DE	;Table posn of verify order
	XOR	A		;Stuff two X'00's to
	LD	(BC),A		;  indicate the end
	INC	BC		;  of the ID posn table
	LD	(BC),A
	LD	B,0		;Stuff 256 FF's into the
	LD	A,0FFH		;  format buffer
	LD	(HL),A
	INC	HL
	DJNZ	$-2
;
;	Begin the formatting
;
	@@DSPLY	FMTCYL$		;"formatting clinder...
BGNFMT	LD	A,(IY+5)	;P/u cylinder position
	CALL	CVDEC		;Cvrt to decimal
	CALL	DSPCYL
SECSKEW	LD	BC,0		;Begin of sector table
BFMT1	LD	HL,HITBUF	;P/u ptr to ID posn table
;
BFMT2
	@@CKBRKC		;Check for break
	JP	NZ,BREAK	;Go if so
;
	LD	E,(HL)		;P/u positions having
	INC	HL		;  sector & cylinder
	LD	D,(HL)		;  info to be stuffed
	INC	HL		;  into format data
	LD	A,D		;Finished?
	OR	E
	JR	Z,BFMT4
	LD	A,(IY+5)	;P/u cylinder # & stuff
	LD	(DE),A		;  into format data
	INC	DE
	LD	A,(IY+3)	;Stuff the side-select
	AND	10H		;  bit
	RRCA
	RRCA
	RRCA
	RRCA
	LD	(DE),A		;  into the format data
	INC	DE
	LD	A,(BC)		;P/u the sector number
	OR	A
	JP	P,BFMT3		;Go if a good number
	ADD	A,C		;  else off the end,
	LD	C,A		;  calculate the beginning
	JR	C,BFMT3		;  of the sector table
	DEC	B
BFMT3	LD	A,(BC)		;P/u the next sector #
	LD	(DE),A		;  and stuff in format data
	INC	DE
	INC	BC
	JR	BFMT2		;Loop until cylinder done
;
BFMT4	LD	(SECSKEW+1),BC	;Save end of sector table
	LD	D,(IY+5)	;P/u current cylinder
	LD	HL,FORMAT	;Pt to format data
	CALL	SELECT		;Drive select
	JP	NZ,IOERR	;Go on error
	CALL	WRCYL		;Cylinder write
	JP	NZ,IOERR
	BIT	5,(IY+4)	;Double sided?
	JR	Z,BFMT5
	BIT	4,(IY+3)	;Flip bit for 2nd side
	JR	NZ,BFMT5	;  if not already on it,
	SET	4,(IY+3)	;  else go to next
	INC	BC		;Bump to start side 2
	JR	BFMT1		;  at different sector #
BFMT5	RES	4,(IY+3)	;Turn off side 2
TRKSKEW	LD	A,0		;P/u the track skew byte
	ADD	A,C		;Repoint to beginning
	LD	C,A		;  of sector table
	ADC	A,B		;Skew start of next track
	SUB	C
	LD	B,A
	LD	(SECSKEW+1),BC
	LD	A,(IY+5)	;Finished?
	CP	(IY+6)
	JR	Z,BGNVER	;Begin verify if so
	LD	BC,1000/15	;Approx 1 ms pause
	@@PAUSE			;  before STEPIN
	CALL	STEPIN		;Step in
	JP	NZ,IOERR	;Go on error
	LD	BC,BGNFMT	;Place RET addr on stack
CKWAIT	CALL	RSELCT		;Wait for idle FDC
	JP	NZ,IOERR	;Go on error
	PUSH	BC		;Save RET addr
;
;	WAIT parameter for time delay after STEPIN
;
WAITPRM	LD	BC,3000/15	;Approx 3 ms delay
	LD	A,B		;  after STEPIN
	OR	C
	RET	Z		;Do next track if no wait
	@@PAUSE			;  else wait for count
	RET
;
;	Begin the verification process
;
BGNVER	LD	C,CR		;Posn to next dsply line
	@@DSP
	CALL	RESTOR		;Restore to cyl 0
	JR	NZ,BVER9	;Go on error
	@@DSPLY	VERCYL$		;"verifying cylinder...
	LD	D,0		;Init track count
BVER1
	@@CKBRKC		;Check for break
	JP	NZ,BREAK	; and abort if so
;
	LD	L,D		;Pt to GAT byte for this
	LD	H,GATBUF<-8	;  track & bypass verify
	LD	A,(HL)		;  if track not formatted
	INC	A
	JR	Z,BVER8
;
	LD	A,D
	CALL	CVDEC		;Convert cyl # to ASCII
	PUSH	DE
	CALL	DSPCYL		;Display the current cyl
	POP	DE
	XOR	A		;Initialize starting sector
	LD	(BVER5+1),A
	LD	(BVER4+1),A
VERSKEW	LD	BC,0		;P/u start of sector tbl
BVER3	LD	A,(BC)		;P/u sector #
BVER4	ADD	A,0		;Add in a side's sectors
	LD	E,A		;  if on side 2
	CALL	VERSEC		;Sector verify
	JR	NZ,BVER9	;Go on error
	INC	BC		;Bump sector table ptr
BVER5	LD	A,0		;P/u sector #
	INC	A		;Bump it up
	LD	(BVER5+1),A	;  and save new #
	LD	E,A		;Xfer to sector register
	LD	A,(SECCYL)	;Is this = a cyl?
	CP	E
	JR	Z,BVER8		;Go if cyl done
	LD	A,(SECTRK)	;Is this a track's worth?
	CP	E
	JR	NZ,BVER3	;Loop if not
	LD	(BVER4+1),A	;Update the add for side2
	INC	BC
	JR	VERSKEW
;
;	Readjust for end of cylinder
;
BVER8	LD	A,D		;P/u current cyl position
	INC	D		;Bump to next cyl
	CP	(IY+6)		;Cp to highest # cyl
	LD	BC,BVER1	;Go if more to verify
	JR	NZ,CKWAIT	;  after checking WAIT
;
;	Shift the FREE table to LOCKOUT table
;
MOVFREE	LD	HL,GATBUF	;Ptr to allocation info
	LD	DE,GATBUF+60H	;Lockout table
	LD	B,0
	LD	C,(IY+6)	;P/u hi cyl
	INC	C		;Offset from 0
	LDIR			;Shift info to the lockout tbl
	LD	C,CR		;Print a newline
	@@DSP
	JR	CALCDIR		;Go finish DIR init
;
;	Got verify error
;
BVER9	CP	5		;Data rec not found?
	JR	Z,BVER10
	CP	4		;Parity error?
	JP	NZ,IOERR	;Quit on any other
BVER10	PUSH	DE
	@@DSPLY	STAR$		;Show the * lockout
	POP	DE
	LD	L,D		;Pt to this cyl
	LD	H,GATBUF<-8	;  in the GAT
	LD	(HL),0FFH	;Lockout this cylinder
	JR	BVER8		;Continue verifying
;
;	Hard drive format - most work done by controller
;
HRDRV	LD	HL,LASTMSG	;Give one last chance to
	BIT	3,(IY+3)	;  abort before wiping
	JR	Z,AFLOP		;  disk unless floppy
	CALL	GET3		;Is hard, get response
	LD	A,(HL)		;P/u 1st char of resp
	CP	'Y'		;Must be yes to continue
	JP	NZ,FMTABT
AFLOP	LD	A,(SYSPRM+1)	;Bypass the formatting
	OR	A		;  if system info only
	JR	NZ,HRDRV1
	@@DSPLY	FMTG$		;"formatting - be patient
	CALL	FMTHD		;Format hard drive
	JP	NZ,IOERR
HRDRV1	LD	A,(IY+7)	;# of sectors/gran
	LD	D,A		;-> reg E
	AND	1FH
	LD	E,A
	INC	E		;Bump for 0 offset
	XOR	D
	RLCA			;Get # of heads
	RLCA			;Into reg D
	RLCA
	INC	A		;Adjust for zero offset
	LD	C,A
	@@MUL8			;Multiply E x C
	BIT	5,(IY+4)	;2-sided?
	JR	Z,$+3
	ADD	A,A		;Twice the number
	LD	(SECCYL),A
	BIT	3,(IY+3)	;Floppy?
	JR	Z,MOVFREE	;Form lock table instead
;
;	Routine to calculate the directory cylinder
;
CALCDIR	CALL	RESTOR		;Step in
	JP	NZ,IOERR	;Go on error
	LD	H,GATBUF<-8
	LD	L,(IY+6)	;P/u highest # cylinder
DIRPARM	LD	BC,0000		;P/U 'DIR=' parm
	LD	A,C		;Check if entered
	OR	B
	JR	Z,NODIR		;Calc one if not entered
	CP	L		;Entered so check if
	JR	NC,NODIR	;  within cylinders
	LD	L,A		;Is ok, use it
	JR	DIRSET
NODIR	INC	L		;Adj for zero offset
	SRL	L		;Divide by 2 to find
DIRSET	LD	C,0		;  disk midpoint
;
;	Perform expanding binary search to find
;	A cylinder available for the directory
;
CALC1	LD	A,(HL)		;Is this cylinder
	INC	A		;Available or locked out?
	JR	NZ,GENSYS	;Bypass if available
	INC	C		;Bump C
	LD	A,C
	RRCA			;Test if odd or even
	LD	A,L		;Get current test pos
	JR	NC,CALC2	;Jump if C was even
	ADD	A,C		;Add to previous pos
	LD	L,A
	CP	(IY+6)		;Go over the top?
	JR	NZ,CALC1	;Loop if not
	JR	CALC3		;Else abort
CALC2	SUB	C		;Try a lower cylinder #
	LD	L,A
	JR	NZ,CALC1	;At cylinder 0?
CALC3	LD	HL,NOCYL$	;"no dir space avail...
	JP	FMTABT
;
;	Generate the system initialization
;
GENSYS	LD	(IY+9),L	;Stuff the dir cyl
	LD	A,L
	CALL	CVDEC		;Cvrt reg A to 2 dec digs
	LD	(DIRASC$),BC	;Stuff into the message
	@@DSPLY	DIRCYL$		;"dir will be placed...
	@@DSPLY	IPLSYS$		;"initializing...
	LD	HL,GATBUF
	LD	A,(HL)		;P/u GAT byte for 1st
	OR	1		;  cylinder & show 1st
	LD	(HL),A		;  gran in use for BOOTs
	LD	A,(IY+9)	;Dir cyl # into DIR/SYS
	LD	(DIRDIR+16H),A
	LD	L,A		;Show entire directory
	LD	(HL),0FFH	;  cylinder used
;
;	Update BOOT for DIR & step rate
;
	LD	A,(IY+9)	;Dir cyl into BOOT
	LD	(BOOT+2),A
	LD	A,(BOOTST$)	;P/u offset
	LD	L,A
	LD	H,BOOT<-8
	LD	A,(STEPDFT)	;P/u boot step rate
	IF	@MOD2
	OR	80H		;Create single byte opcod
	ENDIF
	LD	(HL),A		;  & set into BOOT
	LD	DE,0		;Init for cyl 0, sect 0
	CALL	VERSEC		;Test if formatted
	LD	HL,NOTFMT$	;"Can't, not formatted
	JP	NZ,EXTERR	;Error if not
	LD	HL,BOOT		;Pt to Data disk BOOT
	CALL	WRSEC		;  & write it
	CALL	Z,WRDIR1	;Verify after write
	JP	NZ,IOERR	;  & display '.'
	LD	DE,1		;Pt to cyl 0, sector 1
	LD	HL,BOOT		;Pt to the sector 1 boot
	CALL	WRSEC		;Write 0/1
	CALL	Z,WRDIR+3	;Verify after write
	JP	NZ,IOERR
;
;	Complete GAT construction
;
	LD	A,(IY+6)	;P/u highest # cylinder
	SUB	22H		;  & adj offset from 34
	LD	(GATBUF+0CCH),A	;Stuff GAT cyl excess
	LD	A,(IY+4)	;P/u # of sides
	AND	80H+20H
	LD	B,A		;Save tempy in B
	LD	A,(IY+3)	;P/u density
	AND	40H		;Mask it,
	OR	B		;  merge in sides
	LD	B,A		;  and save it
	LD	A,(IY+8)	;P/u # of grans/cyl
	RLCA
	RLCA			;  to bits 0-2
	RLCA
	AND	7		;Mask it
	LD	(CYLGRN+1),A
	OR	B		;Merge the two
	OR	88H		;Data disk, new date style
	LD	(GATBUF+0CDH),A	;Stuff into GAT
;
	LD	DE,GATBUF+255-10	;6.2 Media Data Block
	LD	HL,LSIID	;Point to header
	LD	BC,04		;Set length &
	LDIR			;  move it
	PUSH	IY		;Get DCT address
	POP	HL		;  into HL
	INC	HL		;Bypass the driver vector
	INC	HL
	INC	HL
	LD	C,7		;Bytes to move
	LDIR
	JR	WRGAT1		;Skip around string
LSIID	DB	03,'LSI'
;
;	Write copy of GAT into 0/3
;
WRGAT1
	LD	HL,GATBUF	;Pt to GAT buffer
	LD	D,0		;Write it out to
	LD	E,3		;Cyl 0, sector 3
	CALL	WRSEC		;Write 0/3
	CALL	Z,WRDIR1	;Verify after write
	JP	NZ,IOERR	;Quit on error
;
;	Write the system information sector
;
	LD	HL,HITBUF	;Zero out buffer
GSYS1	LD	(HL),0
	INC	L
	JR	NZ,GSYS1
	LD	HL,HITBUF	;Set first byte to OSVER
	LD	(HL),RLS	;  for release number
	LD	L,20H		;Point hl to AUTO buffer
	LD	(HL),0DH	;Put in terminator
	LD	DE,2		;Pt to cyl 0, sector 2
	LD	L,D		;Hl now points to HITBUF
	CALL	WRSEC		;Write 0/2
	CALL	Z,WRDIR1	;Verify after write
	JP	NZ,IOERR	;Quit on error
	LD	L,20H		;Zero this out for use
	LD	(HL),0		;  when writing HIT
;
;	Write out the directory GAT
;
	LD	HL,GATBUF	;Pt to GAT sector buffer
	LD	D,(IY+9)	;P/u the dir cyl
	LD	E,L		;Denote sector 0
	CALL	WRDIR		;Write the GAT
	JP	NZ,IOERR
;
;	Construct the HIT
;
	LD	HL,HITBUF	;Point to the HIT buffer
	LD	(HL),0A2H	;Stuff BOOT/SYS hash code
	INC	HL
	LD	(HL),0C4H	;Stuff DIR/SYS hash code
	DEC	HL
	LD	D,(IY+9)	;P/u dir cyl #
	LD	E,1		;Pt to sector 1
	CALL	WRDIR		;Write the HIT
	JP	NZ,IOERR
	LD	DE,HITBUF	;Establish buffer for
	LD	HL,BOOTDIR	;  dir records
	LD	BC,32		;Move BOOT/SYS dir record
	LDIR			;  into 1st slot
	LD	D,(IY+9)	;P/u dir cyl
	LD	E,2		;This will be sector 2
	LD	HL,HITBUF	;Pt to buffer start
	CALL	WRDIR		;Write the sector
	JP	NZ,IOERR
	LD	A,(SECCYL)	;P/u # of records
	LD	(DIRDIR+14H),A	;  & stuff into DIR/SYS
	OR	A		;Are recs=256?
	JR	NZ,CYLGRN	;Go if not
	INC	A
	LD	(DIRDIR+15H),A	;  else stuff msb of ERN
CYLGRN	LD	A,0		;P/u # grans/cyl
	BIT	5,(IY+4)	;Test 2-sided
	JR	Z,$+4
	ADD	A,A		;Double count on 2-sided
	INC	A		;Plus 1 for 0 offset adj
	LD	(DIRDIR+17H),A	;Stuf in DIR/SYS
	LD	A,(IY+9)	;P/u the dir cyl # &
	LD	(DIRDIR+16H),A	;  stuff into the DIR rec
	LD	HL,DIRDIR	;Pt to start of DIR data
	LD	DE,HITBUF	;Pt to start of dir buf
	LD	BC,32		;Move DIR/SYS into buf
	LDIR
	LD	D,(IY+9)	;P/u dir cyl #
	LD	E,3		;Write as sector 3
	LD	HL,HITBUF	;Pt to start of buffer
	CALL	WRDIR		;Write the sector
	JR	NZ,IOERR
	LD	HL,HITBUF	;Zero the 1st 32 bytes
	LD	B,32		;  of the buffer to clear
GSYS2	LD	(HL),0		;Where we stuffed the
	INC	HL		;  BOOT & DIR dir records
	DJNZ	GSYS2
	LD	D,(IY+9)	;P/u dir cyl #
	LD	E,4		;Cont writing at sect 4
GSYS3	LD	HL,HITBUF	;Pt to start of buffer
	CALL	WRDIR		;Write the sector
	JR	NZ,IOERR
;
;	Write the remaining directory
;
	INC	E		;Bump the sector pointer
	LD	A,(SECCYL)	;P/u highest # sector
	CP	E		;Are we finished yet?
	JR	NZ,GSYS3	;Loop if not
	CALL	EXIT2		;Get system disk
	@@DSPLY	FMTCAO$		;"formatting complete...
	JR	EXIT
;
;	Exit procedures
;
IOERR	PUSH	AF		;Save errcod
	CALL	EXIT2		;Interrupts on if needed
	POP	AF		;Rcvr errcod
	CP	63		;Extended errror?
	JR	Z,EXTERR	;Go if so
	LD	L,A		;Error code to HL
	LD	H,0
	OR	0C0H		;Mask to ABORT with brief
	LD	C,A		;Error code to C
	@@ERROR			;  for error display
	JR	ERREXIT
;
BREAK	EQU	$
FMTABT	LD	HL,FMTABT$	;"Command aborted
EXTERR	@@LOGOT			;Some error to abort job
	CALL	EXIT2		;Get system disk
	LD	HL,-1		;Set abort code
ERREXIT	LD	(RETCOD),HL
EXIT	LD	HL,0		;Init to no error
RETCOD	EQU	$-2
	PUSH	HL
	PUSH	IY		;Transfer the saved
	POP	DE		;  system DCT back
	LD	HL,SYSDCT	;  into the system
	LD	BC,10		;  DCT slot
	LDIR
	CALL	RESTOR		;Match DCT and drive
	POP	HL
SPSAV	LD	SP,$-$		;P/u the stack pointer
	@@CKBRKC		;Clear break bit
	RET			;  & exit to caller
;
EXIT2	LD	A,(FMTDRV+1)	;P/u drive # just fmtd
	INC	A		;If drive never entered,
	RET	Z		;  just return
	DEC	A		;If 0, we need a system
	JR	NZ,EXIT4
	LD	HL,PMTSYS$	;"load system disk...
	@@DSPLY
EXIT3	@@KEY			;Request a key
	CP	CR		;Must be <ENTER>
	JR	NZ,EXIT3
EXIT4	JR	RESTOR		;Restore disk to cyl 0
;
;	Disk I/O requests
;
DRVNOP	PUSH	BC
	XOR	A
	JR	FMTDRV
SELECT	PUSH	BC
	LD	A,1
	JR	FMTDRV
RESTOR	PUSH	BC
	LD	A,4
	JR	FMTDRV
STEPIN	PUSH	BC
	LD	A,5
	JR	FMTDRV
RSELCT	PUSH	BC
	LD	A,7
	JR	FMTDRV
WRCYL	PUSH	BC
	LD	A,15
	JR	FMTDRV
FMTHD	PUSH	BC
	LD	A,12
	JR	FMTDRV
WRSEC	PUSH	BC
	LD	A,13
	JR	FMTDRV
WRSYS	PUSH	BC
	LD	A,14
	JR	FMTDRV
RDSEC	PUSH	BC
	LD	A,9
	JR	FMTDRV
VERSEC	PUSH	BC
	LD	A,10
FMTDRV	LD	C,-1		;P/u drive #
	ADD	A,40		;Adjust SVC #
	RST	40
	POP	BC
	RET
;
;	Perform a verification to ensure system sector
;
VERSYS	CALL	VERSEC		;Sector verify
	JR	Z,VERS1		;Bypass if not system
	SUB	6		;Test read system retcod
	RET	Z		;Go if that's what it was
	ADD	A,6		;Restore orig retcod
	RET
VERS1	OR	1		;S/b system, found data
	LD	A,0
	RET
;
WRDIR	CALL	WRSYS		;Write the DIR sector
WRDIR1	CALL	NZ,VERSYS	;Verify after write
	RET	NZ
	PUSH	DE
	LD	C,'.'		;Display a period
	@@DSP			;  for every sector written
	POP	DE
	RET
;
;	Routine to convert reg A to 2 decimal digits
;
CVDEC	LD	C,30H		;Init msd to 0
CVD1	SUB	10		;Sub 10 until underflow
	JR	C,CVD2
	INC	C		;Inc the count
	JR	CVD1
CVD2	ADD	A,3AH		;Add back 10 + '0'
	LD	B,A		;Lsd to B
	RET
;
;	Routines to convert input strings to UC
;	HL => Prompt string
;
GET3	@@DSPLY			;Display the prompt
	LD	BC,3<8		;Init 3 keys max
	JR	$+5
GET8	LD	BC,8<8		;8-chars max
	LD	HL,HITBUF	;Buffer area
GET8A	@@KEYIN			;Enter them
	JP	C,FMTABT	;Quit on Break
	LD	A,B		;Get length of response
	OR	A
	RET	Z		;Back if Enter only
;
;	Routine to convert n-character string to UC
;
	PUSH	AF		;Save the registers
	PUSH	BC
	PUSH	HL
GETUC	LD	A,(HL)		;P/u a char
	CP	'a'		;Skip if below 'a'
	JR	C,GETUC1
	CP	'z'+1		;  or above 'z'
	JR	NC,GETUC1
	RES	5,(HL)		;  else convert to UC
GETUC1	INC	HL		;Bump the buffer ptr
	DJNZ	GETUC		;Loop thru all chars
	POP	HL
	POP	BC
	POP	AF
	RET
;
;	Routine to display the cylinder number
;
DSPCYL	PUSH	BC		;Save ASCII cylinder #
	LD	C,8		;Back up twice &
	@@DSP			;  output new position
	LD	C,8
	@@DSP
	POP	BC		;Recover cyl #
	@@DSP			;Send MSD
	LD	C,B
	@@DSP			;Send LSD
	RET
;
;	Formatting data and tables
;
BOOTDIR	DB	5EH,0,0,0,0,'BOOT    SYS',0F6H,37H
	DB	0,0,5,0,0,0,0FFH,0FFH,-1,-1,-1,-1,-1,-1
DIRDIR	DB	5DH,0,0,0,0,'DIR     SYS',0F6H,37H
	DB	96H,42H,10,0,11H,1,0FFH,0FFH,0,0,0,0,0,0
SYSDCT	DS	10
STEPDFT	DB	0		;Boot step rate default
SECCYL	DS	1		;# of sectors per cyl
SECTRK	DS	1		;# of sectors per trk
;
;	Single density 5" format table
;
S5TBL	DB	10,7
	DB	0,5,1,6,2,7,3,8,4,9
	DB	-10,-10,-10,-10,-10,-10,-10,-10,14,0FFH
	DB	0F1H,6,0,1,0FEH
	DB	0F3H,3,0,1,1,1,0F7H,1,0FFH,11,0FFH
	DB	6,0,1,0FBH,0,0E5H,1,0F7H,1,0FFH,13,0FFH
	DB	0F2H,47H,0FFH,0F4H
	DB	0,1,2,3,4,5,6,7,8,9
;
;	Double density 5" format table
;
D5TBL	DB	18,10
	DB	0,9,1,10,2,11,3,12,4
	DB	13,5,14,6,15,7,16,8,17
	DC	11,-18
	DB	32,4EH
	DB	0F1H,12,0,3,0F5H,1,0FEH
	DB	0F3H,3,0,1,1,1,0F7H,22,4EH,12,0,3,0F5H
	DB	1,0FBH,0F5H,128,6DH,0B6H
	DB	1,0F7H,1,4EH,23,04EH
	DB	0F2H,182,4EH,0F4H
	DB	0,1,2,3,4,5,6,7,8,9
	DB	10,11,12,13,14,15,16,17
;
;	Single density 8" format table
;
S8TBL	DB	16,2
	DB	10,5,0,11,6,1,12,7,2,13,8,3,14,9,4,15
	DB	-16,-16,-16,28H,0FFH
	DB	0F1H,6,0,1,0FEH
	DB	0F3H,3,0,1,1,1,0F7H,11,0FFH,6,0,1,0FBH
	DB	0,0E5H,1,0F7H,1,0FFH,20,0FFH
	DB	0F2H,208,0FFH,0F4H
	DB	10,0,6,12,2,8,14,4,5,11,1,7,13,3,9,15
;
;	Double density 8" format table
;
D8TBL	DB	30,12
	DB	0,10,20,1,11,21,2,12,22,3,13,23,4,14,24
	DB	5,15,25,6,16,26,7,17,27,8,18,28,9,19,29
	DC	13,-30
	DB	20,4EH
	DB	0F1H,0CH,0,3,0F5H,1,0FEH
	DB	0F3H,3,0,1,1,1,0F7H,22,4EH,12,0,3,0F5H
	DB	1,0FBH,0F5H,128,6DH,0B6H
	DB	1,0F7H,1,0FFH,17,4EH
	DB	0F2H,0,4EH,61,4EH,0F4H
	DB	0,20,11,2,22,13,4,24,15,6,26,17,8,28,19
	DB	10,1,21,12,3,23,14,5,25,16,7,27,18,9,29
;
FMTCYL$	DB	29,'Formatting cylinder   ',3
VERCYL$	DB	29,'Verifying  cylinder   ',3
STAR$	DB	'*   ',3
FMTG$	DB	'Formatting...',CR
NOCYL$	DB	'No cylinders available for directory',CR
DIRCYL$	DB	'Directory will be placed on cylinder '
DIRASC$	DB	'00',CR
IPLSYS$	DB	LF,'Initializing DIRECTORY information: ',3
PMTSYS$	DB	LF,'Load SYSTEM diskette  <ENTER>',CR
FMTCAO$	DB	LF,LF,'Formatting complete',CR
FMTABT$	DB	LF,'Command aborted',CR
NOTFMT$	DB	LF,'Can''t, Diskette not formatted',CR
;
;	Patch area
;
	ORG	$<-8+1<+8
GATBUF	DS	203		;GAT sector buffer
	DB	RLS,0,0,0,0	;Ver, cyl exc, type, pswd
	DB	'        MM/DD/YY'
	DC	32,0
BOOT	EQU	$
CORE$	DEFL	$
	ORG	4300H		;Execute at ROM BOOT
	LORG	CORE$		;  but load here
	NOP
	CP	0		;P/u the DIR track
;
	IF	@MOD2
	DB	83H
	ENDIF
	IF	@MOD4
	DI
	ENDIF
	DC	12,0
	LD	DE,80*11+CRT4+29	;Mod 4 video locn
	LD	HL,DATADSK$	;Xfer error to vidmem
	LD	BC,STRLEN
	LDIR
	LD	DE,64*8+CRT3+21	;Mod 3 video locn
	LD	HL,DATADSK$	;Xfer error to vidmem
	LD	BC,STRLEN
	LDIR
STOP	JP	STOP
DATADSK$	DB	'Cannot boot, DATA DISK!'
STRLEN	EQU	$-DATADSK$
	DC	-$&0FFH,0
SAFESP	EQU	$
	ORG	CORE$+256
	LORG	CORE$+256
HITBUF	DS	256
;
	SUBTTL	'<Format Init Code>'
	PAGE	OFF
*GET	FORMAT2:3
;
	END	FORMAT
