	
	* * * * * * * * * * * * * * * * * * * * * * * * * * *
	*						    *
	*  						    *
        *      Written for AMPRO by Paul Bartholomew        *
	*  						    *
	*    COPYRIGHT (C) 1985,86 AMPRO COMPUTERS, INC.    *
	*						    *
	* * * * * * * * * * * * * * * * * * * * * * * * * * *



; Assemble with ASM.COM or equivalent. There is no Z80 code.


;REVISION LOG:	
;
;  Vers 1.2   fsw	Corrected BPB's to work with DOS 3.2
;
;  Vers 1.1   rbl	Changed diskette sensing so more reliable
;			with microfloppies.
;			Changed format selection menu text.
;
;		08/08/85 Release version 1.0.
;                          Supports the following formats:
;                             IBM PC-DOS version 1.x SSDD (8 Sector)
;                             IBM PC-DOS version 1.x DSDD (8 Sector)
;                             IBM PC-DOS version 2.x SSDD (9 Sector)
;                             IBM PC-DOS version 2.x DSDD (9 Sector)
;

;PCFMT allows formatting IBM PC-DOS disk formats.  It is based on
;the code developed for AMPRODSK and uses most of the algorithms
;in that program.  The major differences are:
;
;       1. Modified GEN routine to be a CALLable subroutine.
;
;       2. Modified GEN routine to allow writes to SIDE-1.
;
;       3. "TYPE" byte removed, because ALL formats have a
;          write after the FORMAT.  "TYPELETTER" is used to
;          see which write routine is to be used.

;
; wd1770 equates
REST	EQU	0		; slow restore
RDSEC	EQU	88H		; read sector command
WRSEC	EQU	0A8H		; write sector command
WRTRK	EQU	0F8H		; write track command
STEPI	EQU	58H		; step in command
RDID	EQU	0C8H		; read address command
MOT	EQU	80H		; motor on status
WPR	EQU	40H		; write protected status
SPU	EQU	20H		; disk at speed status (type i)
TYP	EQU	20H		; record type status (types ii and iii)
RNF	EQU	10H		; record not found status
CRC	EQU	8		; crc error status
TK0	EQU	4		; track zero status (type i)
LDT	EQU	4		; lost data status (types ii and iii)
IDX	EQU	2		; index status (type i)
DRQ	EQU	2		; data request status (types ii and iii)
BSY	EQU	1		; controller busy status

ERRII	EQU	WPR+RNF+CRC+LDT	; type ii error status mask
ERRIII	EQU	WPR+LDT		; type iii error status mask

CMND	EQU	0C0H		; fdc command register
WTRK	EQU	CMND+1		; write to track register
WSEC	EQU	WTRK+1		; write to sector register
WDAT	EQU	WSEC+1		; write to data register

STAT	EQU	WDAT+1		; fdc status register
RTRK	EQU	STAT+1		; read from track register
RSEC	EQU	RTRK+1		; read from sector register
RDAT	EQU	RSEC+1		; read from data register

CONT	EQU	0		; system control port
ROMOFF	EQU	40H		; turn rom off

SID0	EQU	0EFH		; mask side bit off
SID1	EQU	10H		; side bit in control register
SDEN	EQU	20H		; single density bit in control register
TRY	EQU	3		; tries
TRYHARD	EQU	10		; we try harder

MSEC	EQU	167		; constant for 1 ms delay

CR	EQU	13		; carriage return
LF	EQU	10		; line feed
ESC	EQU	27		; escape key
UPCASE	EQU	5FH		; upper case mask

bdos	equ	5

	ORG	100H

	;embed the copyright notice
	;
START:	JMP	BEGIN		; leave room for copyright
	DB	' DOSFMT Copyright (C) 1985,86 AMPRO Computers, Inc. '
	DB	13,10
	DB	' Written for AMPRO by Paul Bartholomew '
	DB	13,10,26

	;set up the stack and print signon message
	;
BEGIN:	LXI	SP,STACK	; set local stack
	CALL	CLRSC		; clear the screen
	CALL	ILPRT		; print following text
	DB	CR,LF,'   IBM PC-DOS Diskette Format/Verify Utility'
	DB	CR,LF,'  Copyright (c) 1985,86 AMPRO Computers, Inc.'
	DB	CR,LF,'                 Version 1.2$'

	call	get$bios$vers
	mvi	a,16
	jnz	new$sys
	lhld	1
	mvi	L,5ch
	mov	a,m
	jmp	plugem
new$sys:
	push	psw
	mvi	a,0
	lxi	h,jplug1
	mov	m,a
	inx	h
	mov	m,a
	inx	h
	mov	m,a
	pop	psw
plugem:
	adi	'@'
	sta	plug1
	inr	a
	sta	cplug1
	jmp	doit


DISP$FDEV:
;
; [E2.15]
;
;
	lda	lb$vers
	cpi	20
	rm

	LXI	D,D$FDEV$HDR	; Print header
	mvi	c,9
	call	bdos

	mvi	a,0		; starting unit #
D$NEXT$FDEV:
	sta	unit
	call	lb$get$ldte	; Get address of unit id	
	MOV	A,M		; Get unit id
	CPI	01		; Floppy?
	JNZ	D$BUMP$PTR	; No -- go to the next device
	inx	h		; Get drive #
	mov	a,m		; .
	ani	03h		; mask out excess bits
	MOV	l,a		; update floppy device number
	mvi	h,0		; .
	dad	h		; x2
	xchg
	LXI	H,FNAMES	; .
	dad	d		; x2
	dad	d		; x4
	dad	d		; x6
	lxi	d,d$fname	;
	lxi	b,6		; 
	db	0edh,0b0h	; . (LDIR)
	lda	unit		;
	adi	'A'		;
	sta	d$current	;
	LXI	D,D$FDEV$LIN	; and output the line
	mvi	c,9
	call	bdos

D$BUMP$PTR:
	lda	unit
	inr	a		; Bump to next unit
	cpi	16		; Done yet?
	jm	D$NEXT$FDEV	; No -- go do the next one
	RET

unit:	db	0

D$FDEV$HDR:	DB	CR,LF,LF,'- FLOPPY DISK ASSIGNMENTS -',CR,LF
		DB	' CP/M drive   '
		DB	'Floppy disk',CR,LF
		DB	' ------------------------',CR,LF,'$'

D$FDEV$LIN:
		DB	'  '
D$CURRENT:	DB	'x  '
D$EDISK:	DB	'   '
D$EBLANK:	DB	'         '
D$FNAME:	DB	'        '
		DB	CR,LF,'$'
D$FDEV$HLEN	EQU	$-D$FDEV$LIN	; Line length

FNAMES:		DB	'First '
		DB	'Second'
		DB	'Third '
		DB	'Fourth'

; end of DISPLAY$FDEV


GET$BIOS$VERS:
; Get bios version -- Brings the current BIOS jump tables (starting
;     at warm boot) to a local area for ease of utility access.  If
;     this BIOS is version 2.1 or greater, the secondary jump table
;     is brought in as well.
;
; Entry: none
; Exit:  Z  = bios < 2.1 (old bios)
;        NZ = bios 2.1+  (fixed disk bios)
;        All registers are modified
;
	LHLD	1		; Get start of bios jump table
	LXI	D,LB$BIOS$TBL	; Move bios to local storage
	LXI	B,LB$LEN	; .  (length of bios area)
	DB	0edh,0b0h	; .  (move routine)
	MVI	A,0		; Test CP/M version
	CALL	LB$GETNXT	; Get next jump table
	STA	LB$VERS		; Save bios version
	INX	H		; See if HL is 0FFFFh
	MOV	A,H		; .
	ORA	L		; .
	RZ			; If so, then old version
	DCX	H		; Fix HL as it has the table addr
	LXI	D,LB$XTBL	; Move extra table to local storage
	LXI	B,LB$XLEN	; .  (length of extra table)
	db	0edh,0b0h	; .  (move routine)
	MVI	A,0FFH		; Set NZ to indicate bios
	ORA	A		; ... version 2.1+
	RET			; ... and return.

doit:
	; main program begins here
	;
ASK1:	CALL	ILPRT		; print following string
	DB	CR,LF,LF,'FORMAT or VERIFY?  (F or V)'
	DB	CR,LF,'Press <ESC> or <^C> to exit.$'
ASK1A:	CALL	CONIN		; get response
	CPI	ESC
	JZ	EXIT		; exit to operation system
	CPI	3
	JZ	EXIT		; ctl c
	ANI	UPCASE		; force upper case
	CPI	'F'
	JZ	SETF		; if format
	CPI	'V'
	JZ	SETV		; if verify
	JMP	ASK1A		; otherwise, do this again

	; set function code and do it
	;
SETF:	MVI	A,1
	STA	FUNC
	JMP	FORMAT
SETV:	MVI	A,2
	STA	FUNC
	JMP	VERIFY

	;setup the format routine
	;
FORMAT:	CALL	CLRSC
	CALL	ILPRT
	DB	8,32,CR,LF,LF	; overwrite response and make new line
	DB	'FORMAT prepares a fresh diskette for data or '
	DB	'program storage.$'
	CALL	ASK5		; ask destination
	JC	ASK1		; restart if bad selection
	JMP	ASK2
FORM0:	CALL	ASK6		; give warning
	JC	ASK1
	CALL	EXEC		; do it
	JMP	ASK1		; restart at end of format

	;setup the verify routine
	;
VERIFY:	CALL	CLRSC
	CALL	ILPRT
	DB	8,32,CR,LF
	DB	CR,LF,'VERIFY checks the reliability of data on a disk.$'
	CALL	ASK5		; ask for destination disk
	JC	ASK1
	JMP	ASK2
VERF0:	CALL	ASK3		; ask to load disk
	JC	ASK1
	CALL	EXEC		; do it
	JMP	ASK1

	;get selection and update TABLE
	;
ASK2:	CALL	ILPRT		; print following string
	DB	CR,LF,LF
	DB	'Formats Available: (48 tpi Drive Required)'
 	DB	CR,LF,LF
	DB	'    1 - Single-Sided 8 Sector (160K)'
	DB	CR,LF
	DB	'    2 - Double-Sided 8 Sector (320K)'
	DB	CR,LF
	DB	'    3 - Single-Sided 9 Sector (180K)'
	DB	CR,LF
	DB	'    4 - Double-Sided 9 Sector (360K)'
	DB	CR,LF,LF,'Choose one or <ESC> to Restart: $'

ASKAGN:	CALL	CONIN		; get the answer
	CPI	3		; ^c?
	JZ	EXIT		; exit
	CPI	ESC		; esc?
	JZ	ASK1		; return
;	ANI	UPCASE		; mask upper case
	sta	typeletter
	CPI	'1'		; 1?
	JZ	DOS1SS		; DOS ver 1 SSDD
	CPI	'2'		; 2?
	JZ	DOS1DS		; DOS ver 1 DSDD
	CPI	'3'		; 3?
	JZ	DOS2SS		; DOS ver 2 SSDD
	CPI	'4'		; 4?
	JZ	DOS2DS		; DOS ver 2 DSDD
	JMP	ASKAGN		; anything else ask again	

typeletter:
	db	'a'

ASK2E:	STC			; set error flag
	RET

	;update TABLE routines begin here...
	;
DOS1SS:
	MVI	A,2		; 512 bytes/sectors
	STA	SIZE		; store it
	MVI	A,80		; gap3 size
	STA	GAP3		;
	MVI	A,39		; # of tracks
	STA	MAXTRK		;
	XRA	A		; zero out accum
	STA	SBIAS		; no bias
	STA	TPI96		; 0=48tpi, 1=96tpi format
	STA	TWOSID		; single sided format
	LXI	D,SEC512	; point to data
	CALL	MOVDAT		; move to dat0
	LXI	D,S1SKW		; point to skew table
	JMP	MOVSKW		; move it to skew

S1SKW:	DB	1,2,3,4,5,6,7,8,255

DOS1DS:
	MVI	A,2		; 512 bytes/sectors
	STA	SIZE		; store it
	MVI	A,80		; gap3 size
	STA	GAP3		;
	MVI	A,39		; # of tracks
	STA	MAXTRK		;
	XRA	A		; zero out accum
	STA	SBIAS		; no bias
	STA	TPI96		; 0=48tpi, 1=96tpi format
	INR	A
	STA	TWOSID		; double sided format
	LXI	D,SEC512	; point to data
	CALL	MOVDAT		; move to dat0
	LXI	D,D1SKW		; point to skew table
	JMP	MOVSKW		; move it to skew

D1SKW:	DB	1,2,3,4,5,6,7,8,255

DOS2SS:
	MVI	A,2		; 512 bytes/sectors
	STA	SIZE		; store it
	MVI	A,80		; gap3 size
	STA	GAP3		;
	MVI	A,39		; # of tracks
	STA	MAXTRK		;
	XRA	A		; zero out accum
	STA	SBIAS		; no bias
	STA	TPI96		; 0=48tpi, 1=96tpi format
	STA	TWOSID		; single sided format
	LXI	D,SEC512	; point to data
	CALL	MOVDAT		; move to dat0
	LXI	D,S2SKW		; point to skew table
	JMP	MOVSKW		; move it to skew

S2SKW:	DB	1,2,3,4,5,6,7,8,9,255

DOS2DS:
	MVI	A,2		; 512 bytes/sectors
	STA	SIZE		; store it
	MVI	A,80		; gap3 size
	STA	GAP3		;
	MVI	A,39		; # of tracks
	STA	MAXTRK		;
	XRA	A		; zero out accum
	STA	SBIAS		; no bias
	STA	TPI96		; 0=48tpi, 1=96tpi format
	INR	A
	STA	TWOSID		; double sided format
	LXI	D,SEC512	; point to data
	CALL	MOVDAT		; move to dat0
	LXI	D,D2SKW		; point to skew table
	JMP	MOVSKW		; move it to skew

D2SKW:	DB	1,2,3,4,5,6,7,8,9,255

	;move the new data to TABLE
	;
MOVDAT:	MVI	B,8		; # of bytes to move
	LXI	H,DAT0		; point to data location
MOVDT:	LDAX	D		; move byte to accum
	MOV	M,A		; store it
	INX	D		; roll up reg de
	INX	H		; roll up reg hl
	DCR	B		; count down 1
	JNZ	MOVDT		; done?
	RET

MOVSKW:	LXI	H,SKEW		; point to skew
MOVSK:	LDAX	D		; move into accum
	MOV	M,A		; store it
	CPI	0FFH		; done?
	JZ	RETURN		;
	INX	D		; roll up de
	INX	H		; roll up hl
	JMP	MOVSK		; again 
RETURN: LDA	FUNC		; get function #
	CPI	1		; was it a format?
	JZ	FORM0		; 
	JMP	VERF0		; if not format must be verify

SEC512:	DB	128,0E5H,128,0E5H,128,0E5H,128,0E5H

	;tell them to put the disk in
	;
ASK3:	lda	typeletter
	call	conout
	CALL	ILPRT		; print the following string
	DB	CR,LF,LF,'Place disk in Drive '
ASK30s:	db	'a'
	DB	CR,LF,LF,'Press <RETURN> to VERIFY, '
	DB	'<ESC> to quit.  $'
	JMP	ASK6E

ASK5:
	call	disp$fdev
	CALL	ILPRT
	DB	CR,LF,LF,'Destination drive?  (A - '
plug1:	db	'D) $'
ASK5E:	CALL	CONIN		; get the answer
	CPI	ESC
	JZ	EXIT
	CPI	3
	JZ	EXIT
	ANI	UPCASE		; force upper case
	CPI	'A'		; first valid drive
	JC	ASK5E
cplug1:	equ	$+1
	CPI	'E'		; first invalid drive
	JNC	ASK5E
	sta	ask60d
	sta	ask30s
	push	psw
	call	conout
	pop	psw
	sui	'A'
jplug1:	jmp	ask50s
	call	lb$get$ldte
	mov	a,m
	cpi	1
	jnz	ask5
	inx	h
	mov	a,m
	ani	3
ask50s:
	STA	DDRIV
	CALL	SETSEL		; disk select bits
	ORA	A
	RET

ASK6:	lda	typeletter
	call	conout
	CALL	ILPRT		; print the following string
	DB	CR,LF,LF,'Place destination disk on drive '
ask60d	DB	'a'
	DB	CR,LF,LF,'Press <RETURN> to write, '
	DB	'<ESC> to quit.  $'
ASK6E:	CALL	CONIN		; get answer
	CPI	CR
	RZ
	CPI	ESC
	JZ	EXIT
	JMP	ASK6E

	;execute it!
	;
EXEC:	CALL	ILPRT
	DB	CR,LF,LF,'$'
	LDA	FUNC		; function 1=fmt, 2=vfy
	CPI	1
	JZ	FMT
	CPI	2
	JZ	VFY		; 
	RET

	;format routines...
	;
FMT:	LDA	DDRIV
	CALL	SETSEL
	CALL	SETUP
	XRA	A
	STA	TRACK
	STA	HEAD
NEXTRK:	CALL	KEY
	LXI	H,FRMSG
	CALL	PRINT
	CALL	TMRPRT
	CALL	MAKETRK
	MVI	A,TRY
	STA	TRIES
NT3:	CALL	WRITRK
	JZ	NT5
	LXI	H,TRIES
	DCR	M
	JNZ	NT3
	CALL	ILPRT
	DB	CR,'                              '
	DB	CR,LF,'FORMAT failed.',CR,LF,'$'
	CALL	REPORT
	RET

NT5:	LDA	TWOSID
	ORA	A
	LDA	TRACK
	JZ	NT0
	LDA	HEAD
	ORA	A
	LDA	TRACK
	JZ	NT1
NT0:	LXI	H,MAXTRK
	CMP	M
	JNZ	NT1
	CALL	ILPRT
	DB	CR,'                              '
	DB	CR,LF,'FORMAT complete.',CR,LF,LF,'$'

	LDA	TYPELETTER
	CPI	'1'	
	JZ	WRT1S		;8 sector SS DD  
	CPI	'2'	                        
	JZ	WRT1D		;8 sector DS DD  
	CPI	'3'	                        
	JZ	WRT2S		;9 sector SS DD  
	CPI	'4'	                        
	JZ	WRT2D		;9 sector DS DD  
	JMP	VFY		; anything else begin verify


;*****************************************************************************
;
; Write data for IBM PC-DOS version 1.x SSDD
;
;*****************************************************************************
WRT1S:
	MVI	A,1		;We'll be writing 7 sectors
	LXI	H,SKEW1
	MVI	B,7
WRT1SA:
	MOV	M,A
	INX	H
	INR	A
	DCR	B
	JNZ	WRT1SA
	MVI	M,255
;
;Boot record
;
	LXI	D,B1DAT		;Move 512 bytes for boot record
	LXI	H,TKBUF
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
;
;FAT 1
;
	LXI	D,F1SDAT	;Move 3 FAT bytes (FAT 1)
	MVI	B,3
	CALL	MOVDT
	MVI	E,0
	MVI	D,125		;Rest of first 128-bytes of FAT1
	CALL	LOAD

	MVI	C,3		;3 more 128-byte sectors
F1S1:
	PUSH	B
	MVI	E,0
	MVI	D,128
	CALL	LOAD		;128-bytes of FAT1
	POP	B
	DCR	C
	JNZ	F1S1

;
;FAT 2
;
	LXI	D,F1SDAT	;Move 3 FAT bytes (FAT 2)
	MVI	B,3
	CALL	MOVDT
	MVI	E,0
	MVI	D,125		;Rest of first 128-bytes of FAT2
	CALL	LOAD

	MVI	C,3		;3 more 128-byte sectors
F2S1:
	PUSH	B
	MVI	E,0
	MVI	D,128
	CALL	LOAD		;128-bytes of FAT2
	POP	B
	DCR	C
	JNZ	F2S1

;
;Directory
;

	MVI	C,16*4		;16 128-byte sectors
S1DIR:
	PUSH	B
	MVI	E,0E5H		;Use E5 as marker for erased file
	MVI	D,1
	CALL	LOAD
	MVI	E,0F6H
	MVI	D,31
	CALL	LOAD
	POP	B
	DCR	C
	JNZ	S1DIR
	XRA	A
	STA	TRACK
	STA	HEAD
	CALL	GEN		;Write the info out to disk
	JMP	VFY		;Go do verify

;*****************************************************************************
;
; Write data for IBM PC-DOS version 1.x DSDD
;
;*****************************************************************************
WRT1D:
	MVI	A,1		;We'll be writing 8 sectors
	LXI	H,SKEW1
	MVI	B,8
WRT1DA:
	MOV	M,A
	INX	H
	INR	A
	DCR	B
	JNZ	WRT1DA
	MVI	M,255
;
;Boot record
;
	LXI	D,B1DAT		;Move 512 bytes for boot record
	LXI	H,TKBUF
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
;
;FAT 1
;
	LXI	D,F1DDAT	;Move 3 FAT bytes (FAT 1)
	MVI	B,3
	CALL	MOVDT
	MVI	E,0
	MVI	D,125		;Rest of first 128-bytes of FAT1
	CALL	LOAD

	MVI	C,3		;3 more 128-byte sectors
F1D1:
	PUSH	B
	MVI	E,0
	MVI	D,128
	CALL	LOAD		;128-bytes of FAT1
	POP	B
	DCR	C
	JNZ	F1D1
;
;FAT 2
;
	LXI	D,F1DDAT	;Move 3 FAT bytes (FAT 2)
	MVI	B,3
	CALL	MOVDT
	MVI	E,0
	MVI	D,125		;Rest of first 128-bytes of FAT2
	CALL	LOAD

	MVI	C,3		;3 more 128-byte sectors
F2D1:
	PUSH	B
	MVI	E,0
	MVI	D,128
	CALL	LOAD		;128-bytes of FAT2
	POP	B
	DCR	C
	JNZ	F2D1

;
;Directory (up to end of track)
;

	MVI	C,20*4		;20 128-byte sectors
D1DIR1:
	PUSH	B
	MVI	E,0E5H		;Use E5 as marker for erased file
	MVI	D,1
	CALL	LOAD
	MVI	E,0F6H
	MVI	D,31
	CALL	LOAD
	POP	B
	DCR	C
	JNZ	D1DIR1
	XRA	A
	STA	TRACK
	STA	HEAD
	CALL	GEN		;Write the info out to disk
;
;Directory (Side 1 of Track 0)
;
	MVI	A,1		;We'll be writing 2 sectors
	LXI	H,SKEW1
	MVI	B,2
WRT1DB:
	MOV	M,A
	INX	H
	INR	A
	DCR	B
	JNZ	WRT1DB
	MVI	M,255

	LXI	H,TKBUF		;Initialize pointer

	MVI	C,8*4		;8 128-byte sectors
D1DIR2:
	PUSH	B
	MVI	E,0E5H		;Use E5 as marker for erased file
	MVI	D,1
	CALL	LOAD
	MVI	E,0F6H
	MVI	D,31
	CALL	LOAD
	POP	B
	DCR	C
	JNZ	D1DIR2
	XRA	A
	STA	TRACK
	INR	A
	STA	HEAD
	CALL	GEN
	JMP	VFY		;Go do verify

;*****************************************************************************
;
; Write data for IBM PC-DOS version 2.x SSDD
;
;*****************************************************************************
WRT2S:
	MVI	A,1		;We'll be writing 9 sectors
	LXI	H,SKEW1
	MVI	B,9
WRT2SA:
	MOV	M,A
	INX	H
	INR	A
	DCR	B
	JNZ	WRT2SA
	MVI	M,255
;
;Boot record
;
	LXI	H,BPB$BPS$2S	;Move SS-specific data into boot data
	LXI	D,B$DAT
	LXI	B,B$LEN
	DB	0EDH,0B0H

	LXI	D,B2DAT		;Move 512 bytes for boot record
	LXI	H,TKBUF
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
;
;FAT 1
;
	LXI	D,F2SDAT	;Move 3 FAT bytes (FAT 1)
	MVI	B,3
	CALL	MOVDT
	MVI	E,0
	MVI	D,125		;Rest of first 128-bytes of FAT1
	CALL	LOAD

	MVI	C,7		;7 more 128-byte sectors
F1S2:
	PUSH	B
	MVI	E,0
	MVI	D,128
	CALL	LOAD		;128-bytes of FAT1
	POP	B
	DCR	C
	JNZ	F1S2

;
;FAT 2
;
	LXI	D,F2SDAT	;Move 3 FAT bytes (FAT 2)
	MVI	B,3
	CALL	MOVDT
	MVI	E,0
	MVI	D,125		;Rest of first 128-bytes of FAT2
	CALL	LOAD

	MVI	C,7		;7 more 128-byte sectors
F2S2:
	PUSH	B
	MVI	E,0
	MVI	D,128
	CALL	LOAD		;128-bytes of FAT2
	POP	B
	DCR	C
	JNZ	F2S2

;
;Directory
;

	MVI	C,16*4		;16 128-byte sectors
S2DIR:
	PUSH	B
	MVI	E,0		;Use 00 as marker for no more files
	MVI	D,1
	CALL	LOAD
	MVI	E,0F6H
	MVI	D,31
	CALL	LOAD
	POP	B
	DCR	C
	JNZ	S2DIR
	XRA	A
	STA	TRACK
	STA	HEAD
	CALL	GEN		;Write the info out to disk
	JMP	VFY		;Go do verify

;*****************************************************************************
;
; Write data for IBM PC-DOS version 2.x DSDD
;
;*****************************************************************************
WRT2D:
	MVI	A,1		;We'll be writing 9 sectors
	LXI	H,SKEW1
	MVI	B,9
WRT2DA:
	MOV	M,A
	INX	H
	INR	A
	DCR	B
	JNZ	WRT2DA
	MVI	M,255
;
;Boot record
;
	LXI	H,BPB$BPS$2D	;Move DS-specific data into boot data
	LXI	D,B$DAT
	LXI	B,B$LEN
	DB	0EDH,0B0H

	LXI	D,B2DAT		;Move 512 bytes for boot record
	LXI	H,TKBUF
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
	MVI	B,128
	CALL	MOVDT
;
;FAT 1
;
	LXI	D,F2DDAT	;Move 3 FAT bytes (FAT 1)
	MVI	B,3
	CALL	MOVDT
	MVI	E,0
	MVI	D,125		;Rest of first 128-bytes of FAT1
	CALL	LOAD

	MVI	C,7		;7 more 128-byte sectors
F1D2:
	PUSH	B
	MVI	E,0
	MVI	D,128
	CALL	LOAD		;128-bytes of FAT1
	POP	B
	DCR	C
	JNZ	F1D2
;
;FAT 2
;
	LXI	D,F2DDAT	;Move 3 FAT bytes (FAT 2)
	MVI	B,3
	CALL	MOVDT
	MVI	E,0
	MVI	D,125		;Rest of first 128-bytes of FAT2
	CALL	LOAD

	MVI	C,7		;7 more 128-byte sectors
F2D2:
	PUSH	B
	MVI	E,0
	MVI	D,128
	CALL	LOAD		;128-bytes of FAT2
	POP	B
	DCR	C
	JNZ	F2D2

;
;Directory (up to end of track)
;

	MVI	C,16*4		;16 128-byte sectors
D2DIR1:
	PUSH	B
	MVI	E,0		;Use 00 as marker for no more files
	MVI	D,1
	CALL	LOAD
	MVI	E,0F6H
	MVI	D,31
	CALL	LOAD
	POP	B
	DCR	C
	JNZ	D2DIR1
	XRA	A
	STA	TRACK
	STA	HEAD
	CALL	GEN		;Write the info out to disk
;
;Directory (Side 1 of Track 0)
;
	MVI	A,1		;We'll be writing 3 sectors
	LXI	H,SKEW1
	MVI	B,3
WRT2DB:
	MOV	M,A
	INX	H
	INR	A
	DCR	B
	JNZ	WRT2DB
	MVI	M,255
	
	LXI	H,TKBUF		;Initialize pointer

	MVI	C,12*4		;12 128-byte sectors
D2DIR2:
	PUSH	B
	MVI	E,0		;Use 00 as marker for no more files
	MVI	D,1
	CALL	LOAD
	MVI	E,0F6H
	MVI	D,31
	CALL	LOAD
	POP	B
	DCR	C
	JNZ	D2DIR2
	XRA	A
	STA	TRACK
	INR	A
	STA	HEAD
	CALL	GEN
	JMP	VFY		;Go do verify

F1SDAT:
	DB	0FEH,0FFH,0FFH	;FAT marker DOS 1.x SSDD
F1DDAT:
	DB	0FFH,0FFH,0FFH	;FAT marker DOS 1.x DSDD
F2SDAT:
	DB	0FCH,0FFH,0FFH	;FAT marker DOS 2.x SSDD
F2DDAT:
	DB	0FDH,0FFH,0FFH	;FAT marker DOS 2.x DSDD

;
;Boot record for DOS 1.x (SS and DS)
;
B1DAT:
	DB	0EBH,027H,090H,003H,001H,014H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,0CDH
	DB	019H,0FAH,08CH,0C8H,08EH,0D8H,033H,0D2H
	DB	08EH,0D2H,0BCH,000H,07CH,0FBH,0B8H,060H
	DB	000H,08EH,0D8H,08EH,0C0H,033H,0D2H,08BH
	DB	0C2H,0CDH,013H,072H,069H,0E8H,085H,000H
	DB	072H,0DDH,02EH,083H,03EH,003H,07CH,008H
	DB	074H,006H,02EH,0C6H,006H,064H,07DH,002H
	DB	0BBH,000H,000H,02EH,08BH,00EH,003H,07CH
	DB	051H,0B0H,009H,02AH,0C1H,0B4H,000H,08BH
	DB	0F0H,056H,033H,0D2H,033H,0C0H,08AH,0C5H
	DB	02EH,0F6H,036H,064H,07DH,08AH,0E8H,08AH
	DB	0F4H,08BH,0C6H,0B4H,002H,0CDH,013H,072H
	DB	02DH,05EH,059H,02EH,029H,036H,005H,07CH
	DB	074H,01FH,08BH,0C6H,02EH,0F7H,026H,065H
	DB	07DH,003H,0D8H,0FEH,0C5H,0B1H,001H,051H
	DB	0BEH,008H,000H,02EH,03BH,036H,005H,07CH
	DB	07CH,005H,05EH,08BH,036H,005H,07CH,0EBH
	DB	0C0H,0EAH,000H,000H,060H,000H,0BEH,067H
	DB	07DH,0E8H,002H,000H,0EBH,0FEH,032H,0FFH
	DB	02EH,0ACH,024H,07FH,074H,00BH,056H,0B4H
	DB	00EH,0BBH,007H,000H,0CDH,010H,05EH,0EBH
	DB	0EFH,0C3H,0E9H,033H,0FFH,0BBH,000H,000H
	DB	0B9H,004H,000H,0B8H,001H,002H,0CDH,013H
	DB	01EH,072H,033H,08CH,0C8H,08EH,0D8H,0BFH
	DB	000H,000H,0B9H,00BH,000H,026H,080H,00DH
	DB	020H,026H,080H,04DH,020H,020H,047H,0E2H
	DB	0F4H,0BFH,000H,000H,0BEH,08BH,07DH,0B9H
	DB	00BH,000H,0FCH,0F3H,0A6H,075H,00FH,0BFH
	DB	020H,000H,0BEH,097H,07DH,0B9H,00BH,000H
	DB	0F3H,0A6H,075H,002H,01FH,0C3H,0BEH,01BH
	DB	07DH,0E8H,0A2H,0FFH,0B4H,000H,0CDH,016H
	DB	01FH,0F9H,0C3H
	DB	0DH,0AH
	DB	'Non-System disk or disk error'
	DB	0DH,0AH
	DB	'Replace and strike any key when ready'
	DB	0DH,0AH,0
	DB	001H,000H,002H
	DB	0DH,0AH
	DB	'Disk Boot failure'
	DB	0DH,0AH,0
	DB	'Microsoft,Inc '
	DB	'ibmbio  com','0'
	DB	'ibmdos  com','0'
	DB	005H,0C6H,006H,077H,02FH
	DB	0FFH,083H,07EH,0FCH,000H,075H,00BH,080H
	DB	07EH,0F7H,03BH,075H,005H,0C6H,006H,076H
	DB	02FH,0FFH,089H,0ECH,05DH,0CAH,004H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H
;
;Boot record for DOS 2.x (Modified above for SS or DS)
;
B2DAT:
	DB	0EBH,02CH,090H
	DB	'IBM  2.0'
B$DAT:
	DW	512
	DB	1
	DW	1
	Db	2
	DW	64
	DW	9*40
	DB	0FCH
	DW	0
	DW	9
	DW	1
	DW	0
B$LEN	EQU	$-B$DAT
	Dw	000H
	DB	00AH,0DFH,002H,025H,002H,009H,02AH,0FFH
	DB	050H,0F6H,00FH,002H,0CDH,019H,0FAH,033H
	DB	0C0H,08EH,0D0H,0BCH,000H,07CH,08EH,0D8H
	DB	0A3H,07AH,000H,0C7H,006H,078H,000H,021H
	DB	07CH,0FBH,0CDH,013H,073H,003H,0E9H,095H
	DB	000H,00EH,01FH,0A0H,010H,07CH,098H,0F7H
	DB	026H,016H,07CH,003H,006H,01CH,07CH,003H
	DB	006H,00EH,07CH,0A3H,003H,07CH,0A3H,013H
	DB	07CH,0B8H,020H,000H,0F7H,026H,011H,07CH
	DB	005H,0FFH,001H,0BBH,000H,002H,0F7H,0F3H
	DB	001H,006H,013H,07CH,0E8H,07EH,000H,072H
	DB	0B3H,0A1H,013H,07CH,0A3H,07EH,07DH,0B8H
	DB	070H,000H,08EH,0C0H,08EH,0D8H,0BBH,000H
	DB	000H,02EH,0A1H,013H,07CH,0E8H,0B6H,000H
	DB	02EH,0A0H,018H,07CH,02EH,02AH,006H,015H
	DB	07CH,0FEH,0C0H,032H,0E4H,050H,0B4H,002H
	DB	0E8H,0C1H,000H,058H,072H,038H,02EH,028H
	DB	006H,020H,07CH,076H,00EH,02EH,001H,006H
	DB	013H,07CH,02EH,0F7H,026H,00BH,07CH,003H
	DB	0D8H,0EBH,0CEH,00EH,01FH,0CDH,011H,0D0H
	DB	0C0H,0D0H,0C0H,025H,003H,000H,075H,001H
	DB	040H,040H,08BH,0C8H,0F6H,006H,01EH,07CH
	DB	080H,075H,002H,033H,0C0H,08BH,01EH,07EH
	DB	07DH,0EAH,000H,000H,070H,000H,0BEH,0C9H
	DB	07DH,0E8H,002H,000H,0EBH,0FEH,02EH,0ACH
	DB	024H,07FH,074H,04DH,0B4H,00EH,0BBH,007H
	DB	000H,0CDH,010H,0EBH,0F1H,0B8H,050H,000H
	DB	08EH,0C0H,00EH,01FH,02EH,0A1H,003H,07CH
	DB	0E8H,043H,000H,0BBH,000H,000H,0B8H,001H
	DB	002H,0E8H,058H,000H,072H,02CH,033H,0FFH
	DB	0B9H,00BH,000H,026H,080H,00DH,020H,026H
	DB	080H,04DH,020H,020H,047H,0E2H,0F4H,033H
	DB	0FFH,0BEH,0DFH,07DH,0B9H,00BH,000H,0FCH
	DB	0F3H,0A6H,075H,00EH,0BFH,020H,000H,0BEH
	DB	0EBH,07DH,0B9H,00BH,000H,0F3H,0A6H,075H
	DB	001H,0C3H,0BEH,080H,07DH,0E8H,0A6H,0FFH
	DB	0B4H,000H,0CDH,016H,0F9H,0C3H,01EH,00EH
	DB	01FH,033H,0D2H,0F7H,036H,018H,07CH,0FEH
	DB	0C2H,088H,016H,015H,07CH,033H,0D2H,0F7H
	DB	036H,01AH,07CH,088H,016H,01FH,07CH,0A3H
	DB	008H,07CH,01FH,0C3H,02EH,08BH,016H,008H
	DB	07CH,0B1H,006H,0D2H,0E6H,02EH,00AH,036H
	DB	015H,07CH,08BH,0CAH,086H,0E9H,02EH,08BH
	DB	016H,01EH,07CH,0CDH,013H,0C3H,000H,000H
	DB	0DH,0AH
	DB	'Non-System disk or disk error'
	DB	0DH,0AH
	DB	'Replace and strike any key when ready'
	DB	0DH,0AH,0
	DB	0DH,0AH
	DB	'Disk Boot failure'
	DB	0DH,0AH,0
	DB	'ibmbio  com','0'
	DB	'ibmdos  com','0'
	DB	000H
	DB	000H,000H,000H,000H,000H,000H,055H,0AAH

;
;BPB data for DOS 2.x SSDD
;
BPB$BPS$2S:
	DW	512
BPB$SPC$2S:
	DB	1
BPB$RES$2S:
	DW	1
BPB$FAT$2S:
	Db	2
BPB$DIR$2S:
	DW	64
BPB$SEC$2S:
	DW	9*40
BPB$DES$2S:
	DB	0FCH
BPB$FSC$2S:
	DW	2
B$SPT$2S:
	DW	9
B$HDS$2S:
	DW	1
B$HSC$2S:
	DW	0

;
;BPB data for DOS 2.x DSDD
;
BPB$BPS$2D:
	DW	512
BPB$SPC$2D:
	DB	2
BPB$RES$2D:
	DW	1
BPB$FAT$2D:
	Db	2
BPB$DIR$2D:
	DW	112
BPB$SEC$2D:
	DW	9*80
BPB$DES$2D:
	DB	0FDH
BPB$FSC$2D:
	DW	2
B$SPT$2D:
	DW	9
B$HDS$2D:
	DW	2
B$HSC$2D:
	DW	0



NT1:	INR	A
	STA	TRACK
	CALL	STEPIN
	JMP	NEXTRK

	;verify routines begin here
	;
VFY:	MVI	A,0
	STA	HEAD
	LDA	DDRIV
	CALL	SETSEL
	CALL	SETUP
	MVI	A,TRY
	STA	TRIES
V1:	CALL	READID
	JZ	V0
	LXI	H,TRIES
	DCR	M
	JNZ	V1
	CALL	ILPRT
	DB	CR,LF,'VERIFY failed.  Cannot read source disk.',cr,lf,'$'
	RET
V0:
	LDA	TWOSID
	CPI	1
	MVI	A,0
	JC	VF0
	INR	A
VF0:	STA	TWOSID
	XRA	A
	STA	TRACK		; start with track 0
VLOOP:	CALL	KEY
	LXI	H,VFMSG
	CALL	PRINT
	CALL	TMRPRT
	MVI	A,TRY
	STA	TRIES
VL1:	CALL	READTRK
	JZ	VL0
	LXI	H,TRIES
	DCR	M
	JNZ	VL1
	CALL	ILPRT
	DB	CR,'                              '
	DB	CR,LF,'VERIFY failed.  Unrecoverable read error.',CR,LF,'$'
	CALL	REPORT
	RET

VL0:	LDA	TWOSID
	ORA	A
	LDA	TRACK
	JZ	VF1
	LDA	HEAD
	ORA	A
	LDA	TRACK
	JZ	VF2
VF1:	LXI	H,MAXTRK
	CMP	M
	JNZ	VF2
	CALL	ILPRT
	DB	CR,'                              '
	DB	CR,LF,'VERIFY complete.',CR,LF,'$'
	RET

VF2:	INR	A
	STA	TRACK
	CALL	STEPIN
	JMP	VLOOP

	;boot loader routine begin here
	;
	;gen as in sysgen!
	; 
GEN:	LDA	DDRIV		;
	CALL	SETSEL		;
	CALL	SETUP		; setup write  
	LDA	SELBYT
	ANI	SID0
	MOV	B,A
	LDA	HEAD
	ORA	A
	JZ	GEN2
	MOV	A,B
	ORI	SID1
	MOV	B,A
GEN2:
	MOV	A,B
	STA	SELBYT
	OUT	CONT
	LXI	H,TKBUF		; get point
	SHLD	DMAADR		; save buffer pointer
	LXI	H,SKEW1		; point to new skew
	CALL	WTLOOP		; write data
	RET


	;step in the drive
	;
STEPIN:	LDA	TWOSID
	ORA	A
	JZ	STI		; single sided
	LDA	HEAD
	ORA	A
	MVI	A,1
	JZ	STI0
	MVI	A,0
STI0:	STA	HEAD
	JZ	STI1

STI:	LDA	SELBYT
	ANI	SID0		; mask side bit off
	OUT	CONT		; select side 0
	STA	SELBYT
	CALL	WAIT
	MVI	A,STEPI
	CALL	OUTCMD
STILP:	IN	STAT
	RAR
	JC	STILP
	RET

STI1:	LDA	SELBYT
	ORI	SID1
	OUT	CONT		; select side 1
	STA	SELBYT
	LXI	H,TRACK
	DCR	M
	JMP	WAIT

	;write a track
	;
WRITRK:	IN	STAT
	RAR
	JC	WRITRK
	LXI	H,TKBUF
	MVI	A,WRTRK		; write track command
	CALL	OUTCMD
	CALL	WR
	MOV	A,B
	STA	STATUS
	ANI	ERRIII
	RET

WR:	IN	STAT		; get fdc status
	MOV	B,A		; save status
	RAR			; check busy
	RNC			; end of command, return to caller
	RAR			; check for drq
	JNC	WR		; if not
	MOV	A,M		; get a byte from buffer
	OUT	WDAT		; to fdc
	INX	H		; bump hl
	JMP	WR		; again

	;make a track in memory
	;
MAKETRK: LXI	H,TKBUF		; create track image in memory
	MVI	B,60
	MVI	A,4EH
MTLP:	MOV	M,A		; write gap4a
	INX	H
	DCR	B
	JNZ	MTLP
	SHLD	DMAADR		; sector 1 starts here
	LDA	HEAD
	STA	SIDE
	LXI	H,SKEW		;load skew table pointer

LOOP:	MOV	C,M
	INX	H
	INR	C
	JZ	ENDTRK		; if c was 0ffh
	DCR	C
	LDA	SBIAS
	ADD	C
	STA	SECTOR
	PUSH	H		; save skew pointer on stack
	CALL	MAKTRK
	POP	H
	JMP	LOOP

ENDTRK:	LHLD	DMAADR
	LXI	B,1000
ETLP:	MVI	M,4EH		;end track fill data
	INX	H
	DCX	B
	MOV	A,B
	ORA	C
	JNZ	ETLP
	SHLD	DMAADR
	RET

MAKTRK:	LHLD	DMAADR		; track image
	PUSH	H		; save it
	LXI	H,TABLE		; track format table
MAKT1:	MOV	D,M		; get count
	INX	H		; bump pointer
	MOV	E,M		; get data
	INX	H		; bump pointer
	MOV	A,E		; check for end of table (0ffh)
	INR	A		; 0ffh + 1 = 0
	JZ	MAKT2		; if end of table
	XTHL			; point to track buffer
	CALL	LOAD		; fill track buffer
	XTHL			; point to format table
	JMP	MAKT1		; again
MAKT2:	POP	H		; get track buffer address from stack
	SHLD	DMAADR		; save pointer to track buffer
	RET			; to caller

	;write current track from read buffer
	;
WRITETRK:
	LXI	H,RDBUF
	SHLD	DMAADR
	LXI	H,SKEW		; point to skew table	
WTLOOP:	MOV	C,M
	INX	H		; bump pointer
	INR	C
	RZ			; finished, end of table is 0ffh
	DCR	C
	LDA	SBIAS
	ADD	C
	OUT	WSEC		; to fdc
	PUSH	H		; save skew pointer
	CALL	WRITESEC
	POP	H
	JMP	WTLOOP

	;write a sector from DMA buffer
	;
WRITESEC:
	IN	STAT		; clear status
	IN	RDAT		; clear any trash
	LHLD	DMAADR
	MVI	A,WRSEC		; write sector command
	CALL	OUTCMD		; to fdc
	CALL	WR		; write the data
	SHLD	DMAADR		; save pointer
	MOV	A,B		; get status
	STA	STATUS
	ANI	ERRII
	RZ			; return to this caller
	POP	H		; adjust stack from writetrk
	POP	H
	RET			; return to previous caller

	;read current track into read buffer
	;
READTRK: 
	LXI	H,RDBUF
	SHLD	DMAADR
	LXI	H,SKEW		; point to skew table
RTLOOP:	MOV	C,M		; get sector number from table
	INX	H		; bump pointer
	INR	C
	RZ			; finished, end of table is 0ffh
	DCR	C
	LDA	SBIAS
	ADD	C
	STA	SECTOR
	OUT	WSEC		; to fdc
	PUSH	H		; save skew pointer
	CALL	READSEC		; read the sector
RT0:	POP	H
	JMP	RTLOOP

READSEC:
	IN	STAT		; clear status
	IN	RDAT		; clear any trash
	LHLD	DMAADR		; pointer to read buffer
	MVI	A,RDSEC		; read sector command
	CALL	OUTCMD		; to fdc
	CALL	RD		; read the data
	SHLD	DMAADR		; save pointer
	MOV	A,B
	STA	STATUS
	ANI	ERRII
	RZ
	POP	H		; adjust stack from readtrk
	POP	H
	RET			; to previous caller

RD:	IN	STAT		; get fdc status byte
	MOV	B,A		; save status
	RAR			; rotate busy bit to carry
	RNC			; end of command, return to caller
	RAR			; rotate data request to carry
	JNC	RD		; wait for data request
RD0:	IN	RDAT		; get data from fdc
	MOV	M,A		; put it into buffer
	INX	H		; bump hl
	JMP	RD		; again

READID:	IN	STAT
	IN	RDAT
	LXI	H,IDSV
	MVI	A,RDID
	CALL	OUTCMD
	CALL	RD
	MOV	A,B		; get status
	STA	STATUS
	ANI	ERRIII
	RET

	;allow FDC to setup properly
	;
WAIT:	LXI	B,50 * MSEC
WT0:	DCX	B
	MOV	A,B
	ORA	C
	JNZ	WT0
	RET

WAIT10: LXI	B,10 * MSEC
	JMP	WT0

LOAD:	MOV	M,E		; (e) to track buffer
	INX	H		; increment pointer
	DCR	D		; decrement count
	JNZ	LOAD		; again
	RET

CLRSC:	MVI	D,24		; print 24 line feed chars to clear screen
CLS:	MVI	A,LF
	CALL	CONOUT		; out to console
	CALL	WAIT10		; wait 10 ms after line feed
	DCR	D		; decrement count
	JNZ	CLS		; again
	RET

PRINT:	MOV	A,M		; hl points to text string
	INX	H		; bump hl
	CPI	'$'		; check for terminator
	RZ			; return to caller
	CALL	CONOUT		; send byte to console
	JMP	PRINT		; again

pCONOUT:
	PUSH	B		; save
	PUSH	D		;  the
	PUSH	H		;   registers
	MOV	E,A		; text to be printed
	MVI	C,2		; console output function
	CALL	5		; bdos
	POP	H		; restore
	POP	D		;  the
	POP	B		;   registers
	RET

	;prints next byte pointed to by top of stack
	;until delimiter $ is found
	;
ILPRT:	XTHL			; return address to hl points to text
ILP:	MOV	A,M		; get next byte
	INX	H		; bump pointer
	CPI	'$'		; check for string terminator
	JZ	ILPE		; if end of string
	CALL	pCONOUT		; send byte to console
	JMP	ILP		; again
ILPE:	XTHL			; put updated pointer on stack
	RET

CONOUT:	PUSH	B		; save
	PUSH	D		;  the
	PUSH	H		;   registers
	MOV	E,A		; text to be printed
	MVI	C,6		; console output function
	CALL	5		; bdos
	POP	H		; restore
	POP	D		;  the
	POP	B		;   registers
	RET

CONIN:	MVI	A,9		; bios call avoids echo to console
BIOS:	LHLD	1
	MOV	L,A
	PCHL

CONINB:	PUSH	B
	PUSH	D		; save
	PUSH	H		;  registers
	MVI	C,1		; console input function
	CALL	5		; bdos
	POP	H		; restore
	POP	D		;  registers
	POP	B
	RET

	;
	;restore the disk and wait for status
	;

; The current setup routine does a restore with the 1772
; motor on flag enabled.  It exits as soon as the BUSY
; status bit goes away, or after a 4 second timeout.

SETUP:	LDA	SELBYT		; get selected drive
	OUT	CONT		; select the drive
  	MVI	A,REST		; restore command
	CALL	OUTCMD		; output the command
	LXI	H,4000		; 4000 ms timeout setup
DEL0:	MVI	C,0
DEL1:	DCR	C
	JNZ	DEL1
	IN	STAT
	RAR
	JNC	READY		; go on if 1772 done
	DCX	H
	MOV	A,H
	ORA	L
	JNZ     DEL1
	MVI	A,0D0H		; timed out -- force interrupt,
	CALL	OUTCMD		;   then report failure
	JMP	FAILED

; The current ready function checks to see if a diskette
; is inserted in a drive.  A read address command with 
; the motor on flag enabled is used.  If the command
; hangs up, the 1772 is not receiving index pulses,
; indicating the lack of a spinning diskette.

READY:	
	MVI	A,0C0H		; read address command
	CALL	OUTCMD		
	LXI	H,4000		; 4000 mS timeout setup
	MVI	C,0
RDY1:	DCR	C
	JNZ	RDY1
	IN	STAT
	RAR
	RNC			; finished, if 1772 done
	DCX	H
	MOV 	A,H
	ORA	L
	JNZ	RDY1		; loop till timeout
	MVI	A,0D0H		; timeout -- force interrupt,
	CALL	OUTCMD		;   then report failure
	
FAILED:
	LDA	SELBYT
	ANI	0FH
	MVI	C,0
FLD1:	INR	C
	RAR
	JNC	FLD1
	MOV	A,C
	adi	30H		; add ascii bias
	STA	DRI
	CALL	ILPRT		; print following string
	DB	CR,LF,'Drive '
DRI:	DB	'A Not Ready, Insert disk, close door, and try again.',CR,LF,'$'
	POP	B		; adjust stack
        RET

	;send a command to the FDC
	;
OUTCMD:	OUT	CMND
	MVI	A,10
OC0:	DCR	A
	JNZ	OC0		; wait 35 us. for fdc to set-up
	RET

KEY:	push	b
	push	d
	mvi	c,6
	mvi	e,0ffh
	call	5
	pop	d
	pop	b
	rz
	CPI	3
	JZ	EXIT
	PUSH	PSW
	CALL	ILPRT
	DB	CR,'                              ',CR,'$' ; clear the line
	POP	PSW
	CPI	ESC
	RNZ
	POP	H
	RET

EXIT:	JMP	0		; warm boot

TMRPRT:	LDA	TRACK
	LXI	D,TKMSG0
	CALL	BINASC
	LDA	HEAD
	LXI	D,SDMSG0
	CALL	BINASC
	LXI	H,TKMSG
	JMP	PRINT		; print returns to caller

REPORT:	LXI	D,DR		; point to error message
	LDA	SELBYT
	ANI	0FH		; mask upper nybble
	MVI	C,0		; clear counter
R1:	INR	C		; bump it
	RAR			; rotate selbit into carry
	JNC	R1		; again?
	MOV	A,C
	ADI	30H		; add ascii bias
	STAX	D		; store it in message
	STA	WPRMSG0
	LDA	STATUS
	ANI	WPR		; is disk protected?
	JZ	R2
	LXI	H,WPRMSG	; write protected message
	CALL	PRINT
	POP	H		; adjust the stack
	CALL	CONIN		; get response
	CPI	CR		; carriage return?
	JZ	EXEC		; if so
	RET			; get out of here
R2:	LXI	D,TK		; in error message
	LDA	TRACK
	CALL	BINASC
	LXI	D,HD
	LDA	SIDE
	ORA	A		; set flags
	JZ	RPRT1
	MVI	A,1
RPRT1:	CALL	BINASC
	LXI	D,SC
	LDA	SECTOR
	CALL	BINASC
	LXI	D,ST
	LDA	STATUS
	ANI	RNF
	JNZ	SRNF
	LXI	H,CRCER
	CALL	MOV3
	JMP	RPRT2
SDNR:	LXI	H,DNRER
	CALL	MOV3
	JMP	RPRT2
SRNF:	LXI	H,RNFER
	CALL	MOV3
RPRT2:	LXI	H,ERRMSG
RPRT3:	JMP	PRINT		; print returns to caller

MOV3:	MVI	B,3
MOVL:	MOV	A,M
	STAX	D
	INX	H
	INX	D
	DCR	B
	JNZ	MOVL
	RET

BINASC:	PUSH	PSW		; save value
	PUSH	D		; save string ptr
	MVI	A,'0'		; ascii zero
	STAX	D
	LXI	B,2		; b=0, c=2
	XRA	A		; a=0
B0:	INX	D		; bump ptr
	STAX	D		; zero to str
	DCR	C
	JNZ	B0		; again please
	POP	D		; restore de
	LXI	H,TBL		; conversion table
B1:	MVI	C,0		; clear count
	MOV	A,M		; table value
	INR	A
	JZ	BEND		; end of table, conv done
	POP	PSW		; restore value
B3:	SUB	M		; begin division
	JC	B2
	INR	C		; keep count
	JMP	B3
B2:	ADD	M		; restore acc
	PUSH	PSW		; save it
	MOV	A,C		; count
	CPI	0
	JNZ	STSTR		; set ascii value in string
	MOV	A,B
	CPI	0		; 1st time?
	JNZ	STSTR
B4:	INX	H		; bump tbl ptr
	JMP	B1		; next

STSTR:	MVI	B,1		; flag 1st time
	MOV	A,C		; count to c
	ADI	30H		; ascii bias
	STAX	D		; write it into string
	INX	D		; bump str ptr
	JMP	B4

BEND:	POP	PSW		; adjust stack
	RET			; return to caller

TBL:	DB	100
	DB	10
	DB	1
	DB	255		; end of table

	;setup the selbyt
	;
SETSEL:	inr	a
	MOV	C,A
	XRA	A
	STC
STSL:	RAL
	DCR	C
	JNZ	STSL
	ORI	ROMOFF
	STA	SELBYT
	RET

	;error messages...
ERRMSG:
	DB	CR,LF,' Error:  Drive '
DR:	DB	0,':  Track '
TK:	DB	0,0,0,'  Head '
HD:	DB	0,0,0,'  Sector '
SC:	DB	0,0,0,'  Status  '
ST:	DB	0,0,0,CR,LF,'$'
TKMSG:	DB	'Track '
TKMSG0:	DB	0,0,0,'  Side '
SDMSG0:	DB	0,0,0,CR,'$'
VFMSG:	DB	'Verify  $'
FRMSG:	DB	'Format  $'
WPRMSG:	DB	CR,'                              '
	DB	CR,LF,'Remove write protect tab from '
	DB	'destination diskette.'
	DB	CR,LF,'Place diskette in drive '
WPRMSG0:DB	'A, then press <RETURN>.  $'
DNRER:	DB	'DNR'
RNFER:	DB	'RNF'
CRCER:	DB	'CRC'

	;the main data table..
	;
TABLE:	DB	12,0		; defines sector format (#bytes,data)
	DB	3,0F5H		; write 0a1h
	DB	1,0FEH		; id address mark
	DB	1
TRACK:	DB	0
	DB	1
SIDE:	DB	0
	DB	1
SECTOR:	DB	1
	DB	1
SIZE:	DB	3		; always 512 bytes
	DB	1,0F7H		; write crc (2 bytes)
GAP2:	DB	22,4EH		; gap 2 length, data
PREAM:	DB	12,0		; preamble
	DB	3,0F5H		; write 0a1h
	DB	1,0FBH		; data address mark
DAT0:	DB	0,0E5H		; bytes of data fill
	DB	0,0E5H		; bytes of data fill
	DB	0,0E5H		; bytes of data fill
	DB	0,0E5H		; bytes of data fill
	DB	1,0F7H		; write crc (2 bytes)
GAP3:	DB	0,4EH		; gap 3 length, data
	DW	-1		; end of table (0ffffh)

FUNC:	DS	1		; function 1=format, 2=verify, 
MAXTRK:	DB	39		; maximum track
TWOSID:	DB	0		; 0=ss , 1=ds
HEAD:	DB	0		;
SDRIV:	DS	1		; source drive
DDRIV:	DS	1		; destination drive
SELBYT:	DS	1		;
SBIAS:	DB	0		; sector bias  0=ss, 10h=ds, 30h=ds96
TPI96:	DB	1		; 0=48tpi , 1=96tpi
DMAADR:	DS	2		;
STATUS:	DS	1		;
TRIES:	DS	1		;
;
SKEW:	DS	40
SKEW1:	DS	40
;
; Replicated BIOS for ease of use . . .
LB$BIOS$TBL:
LB$WBOOT	DS	3	; Warm boot
LB$CONST	DS	3	; Console status
LB$CONIN	DS	3	; Console input
LB$CONOUT	DS	3	; Console output
LB$LISTOUT	DS	3	; List output
LB$PUNCH	DS	3	; Punch output
LB$READER	DS	3	; Reader input
LB$HOMDSK	DS	3	; Home disk (move to track 00)
LB$SELDSK	DS	3	; Select disk drive
LB$SETTRK	DS	3	; Select track number
LB$SETSEC	DS	3	; Select sector number
LB$SETDMA	DS	3	; Set DMA address
LB$DSKREAD	DS	3	; Disk read
LB$DSKWRITE	DS	3	; Disk write
LB$LISTST	DS	3	; List status
LB$SECTRN	DS	3	; Sector translate routine
; AMPRO-specific BIOS calls
LB$GETNXT	DS	3	; Get bios ver & next tbl address
LB$GETEDSK	DS	3	; Get pointer to E-disk storage
LB$IOINIT	DS	3	; Set new I/O parameters
LB$SCSIDRV	DS	3	; SCSI direct driver

LB$LEN	EQU	$-LB$WBOOT	; Length of bios table

LB$XTBL:
LB$SWAP$DRV	DS	3	; Swap two logical drives
LB$WINDRV	DS	3	; Set/get win drive parameters
LB$PHYTAB	DS	3	; Set/get phytab access
LB$GET$LDTE	DS	3	; Get physical table entry address
LB$RESERVED	DS	3	; Reserved entry

LB$XLEN	EQU	$-LB$XTBL	; Length of extra table

LB$VERS		DS	1

	DS	64		; space for 32 level stack
STACK:	DS	2		; space for ccp stack pointer
IDSV:	DS	6		; id save area
RDBUF:	DS	10 * 512	; read buffer
TKBUF:	END			; end of program

