FORMAT

.Page
;++
;			Format
;
;--
; REGISTERS
;  IN
;	All =	Any value
;  OUT
;	All =	Destroyed
;
; CALLS
;	ClrBuf	Clears 524 byte buffer and other variables
;	SelSide	Selects side
;	Recall	Recalibrates disk to optical index sensor
;	WriTrk	Write no. of sectors in TempSec
;	VerTrk	Verifies no. of sectors in TempSec
;	SeekAlt	Seeks the teack in IIob+Track and sets speed
;	WrSynTrk	Writes bitslip FF's and A9's then sector 0
;	WArd16	Write sector x, both header and data fields
;	RdAdr	Reads sector header
;	Read16	Reads data fields
;	VfyCksum	Verifies checksum that was read
;	PreNib	Prenibblizes certain bytes for timing purposes
;
;++
.Page
Format	.Equ *				; Format entry point
FormTrk	.Equ *
	Jsr	ClrBuf			; Clear the buffer to be written
	Lda	#7
	Sta	FmtGap
	Jsr	RecalMtr			; Turn on motor & start from a known point (Track 0 )
	Bcs	FormRts			; Abort upon error from Recal

FormTop	Jsr	SeekAlt			; Go to othe track in IIob+Track & set speed
	Ldy	CurClass
	Lda	SecPrtTrk,y		; Fetch number of sectors in current track
	Sta	TempSec			; Save it for WriTrk

	Jsr	WriTrk			; Write a track full of sectors

	Lda	IIob+Command		; If a format track
	Cmp	#FrmTrk			; Then we're done-exit the routine
	Beq	VT00			; Command = FormatTrack (5)

	Lda	Iob+NoSides		; 1 = single side, 2 = double side
	Cmp	#2
	Bne	$39			; if <> 2 then go to incr to next track
	Lda	#20
	Sta	IIob+Side
	Jsr	WriTrk			; Now write second side
	Lda	#00
	Sta	IIob+Side			; Restore to side 0

$39	Inc	IIob+Track
	Lda	IIob+Track
	Cmp	#MaxTrack+1
	Bcc	FormTop			; Until we run out of tracks
	Dec	IIob+Track
	Bne	VT00			; Skip tunring the motor on

Verify	.Equ *				; Verify entry point
	Lda	#MaxTrack
	Sta	IIob+Track		; From inside of disk to outer edge
VerTrk	.Equ *
	Jsr	RecalMtr			; Turn on motor & start from a know point ( track 0 )
	Bcs	FormRts			; Abort upon error from Recal

VT00	.Equ *
	Jsr	SeekAlt			; Go to track in IIob+Track & set speed
	Ldy	CurClass
	Lda	SecPrTrk,y		; Fetch the number of sectors in current track
	Sta	TempSec			; Save it for WriTrk routine

	Jsr	VerTrk
	Bcs	FormErr			; Error, exit from routine

	Lda	IIob+Command		; If a verify track
	Cmp	#FrmtTrk			; Then we're done-exit the routine
	Bcs	$41			; Command = FormatTrack (5) or VerifyTrack (6)

	Lda	Iob+NoSides		; 1 = Single side, 2 = double side
	Cmp	#2
	Bne	$39
	Lda	#20
	Sta	IIob+Side
	Jsr	VerTrk			; Now verify side 1, track x
	Bcs	FormErr			; Error, exit from routine
	Lda	#00
	Sta	IIob+Side

$39	Dec	IIob+Track
	Bpl	VT00

$41	Clc
	Rts

FormErr	Lda	IIob+Track		; Current track number
	Sta	Trkjl0dNumb		; Save for host's usage
	Lda	IIob+Side			; Current side
	And	#20			; leave bit 5 -- side bit
	Beq	$17
	Lda	#1
$17	Sta	SideNumb			; Save for host's usage
	Lda	#SErrFrmt			; Format error code
FormRts	Rts

TooSml	.Equ *
	.Byte	0., 5., 10., 15.		; Not used
	.Byte	20., 25., 30., 35.		; 4:7
	.Byte	40., 45., 50., 55.		; 8:11
	.Byte	60., 65., 70., 75.		; 12:15

JustRit	.Equ *
	.Byte	108., 99., 90., 81., 72.	; Sectors in class * 9 bytes per sector

;++
;  WriTrk will physically format a disk in a 2:1 interleave.  It will
; write sector 0, sector x, sector 1, sector y, etc.
;--
WriTrk	.Equ				; Entry for writing a track of 524 byte sectors
	Jsr	SelSide			; Select proper side
	Lda	TempSec			; Total number of sectors on current track
	Sta	TotCnt			; Init total number of sectors on current track
	Lsr	A			; Divide by 2 and put remainder into carry
	Adc	#0			; Round up by adding carry
	Sta	HihCnt			; Init counter for high sector values
	Lda	#00
	Sta	CntPtr			; Init pointer for which count to use
	Sta	LowCnt			; For counting up from Sector 0
	Sta	IIob+Sector		; Start w/ sector 0

	Jsr	WrSynTrk			; Write 20 usec nibbles and A9's before sector 0
	Dec	TotCnt			; Subtract 1 from total sector count
	Inc	LowCnt			; Increment value to next low sector (1)
$23	Ldx	CntPtr			; Pointer to which cnt to use -- low or high
	Beq	$35			; If = 0 then increment to 1
	Ldx	#0FF			; If = 1 then decrement to 0
$35	Inx
	Stx	CntPtr
	Lda	LowCnt,x			; Fetch sector number
	Sta	IIob+Sector
	Inc	LowCnt,x			; Increment to next sector number
	Jsr	WAdr16			; Write address and data fields
	Dec	TotCnt			; Decrement total sector count
	Bne	$23			; When = 0 then all sectors are written

	Lda	#00
	Sta	IIob+Sector
	Jsr	RdAdrTmt			; If =  then less than 256 bytes were counted
	Bne	IncrG1			; >256 bytes so increase inter-sector gap

	Ldy	FmtGap
	Lda	TooSml,y
	Cmp	RangeL
	Bcs	DecrG1			; a > normal cnt with current Gap amount

	Ldy	CurClass
	Adc	JustRit,y
	Cmp	RangeL
	Bcs	WrTkDone			; A > range so all OK

IncrG1	Lda	#14.
	Cmp	FmtGap			; Limit to 14. self-sync groups of five
	Beq	WrTkDone
	Inc	FmtGap			; incr count for next track

WrTkDone	.Equ *
	Rts

DecrG1	.Equ	*
	Lda	#4.
	Cmp	FmtGap
	Beq	WrTkDone			; Minimum gap is 4 counts of 5 20 usec bytes

;++
;
;--
VerTrk	.Equ *
	Jsr	SelSide			; Select proper side
	Lda	#00
	Sta	IIob+Sector
	Sta	ScTrCnt
VfyTrk1	Lda	MaxRetry
	Sta	RetryCnt

VfyTrk2	Jsr	RdAdr			; Read sector address field
	Bcs	VfyErr
	Jsr	Read16			; Read sector data
	Bcs	VfyErr
	Jsr	VfyCksum			; Verify the checksum
	Bcs	VfyErr			; Must Be zero
VfRtry	Inc	IIob+Sector
	Lda	IIob+Sector
	Cmp	TempSec
	Bne	VfyTrk1			; If equal then carry will be set
	Lda	SctrCnt
	Bne	$74
	Clc
$74	Rts

VfyErr	Dec	RetryCnt
	Bne	VfyTrk2
	Ldy	SctrCnt
	Lda	IIob+Sector		; Current Sector Number
	Sta	SctrSav,y			; Save for host usage
	Inc	SctrCnt
	Bne	VfrTry			; Go to next sector and try again

ClrBuf	.Equ *
	Lda	#00			; Clear the total buffer area
	Tay
$05	Sta	Page02,y			; Zero part of the data buffer
	Sta	Page03,y			; Zero the rest of the data buffer
	Iny
	Bne	$05
	Ldy	#Bufr12SZ			; For 12 bytes header buffer
$10	Sta	Bufr12,y
	Dey
	Bpl	$10
	Sta	Cksum1			; Clear the three checksum butes
	Sta	Cksum2
	Sta	Cksum3
	Jmp	PreNib			; Create 5 composite bytes & return to caller