;******************************************************************************
;******************************************************************************
;***************                				***************
;***************	  BIGBOARD FORMATTER PROGRAM		***************
;***************                  VERSION 2.1			***************
;***************						***************
;***************   WRITTEN BY J.P. JONES   MODIFIED BY G. MION  ***************
;***************   MINOR BUG FIXED BY T.HAMEENHO                ***************
;******************************************************************************


;	THIS PROGRAM WILL FORMAT A DISK IN DRIVE A,B,C OR D AND THEN VERIFY
;	EACH TRACK AND SECTOR.  THIS VERSION OF THE PROGRAM IS DESIGNED TO 
;	WORK WITH ANY TERMINAL OR THE ON-BOARD VIDEO MONITOR.  FEEL FREE TO 
;	EDIT THIS PROGRAM.  IF YOU ARE ABLE TO ADD SOME FUNCTIONS TO IT OR
;	DO SOME OF MINE BETTER, PLEASE LET ME KNOW.


;	THE BASIC FORMAT PROGRAM STILL EXISTS.  ALL I HAVE DONE IS TO MAKE
;	THE PROGRAM MORE USABLE.  IT ASKS WHICH DRIVE YOU HAVE THE DISK IN
;	TO FORMAT, SHOWS YOU THAT IT IS INDEED FORMATTING, AND THEN VERIFIES
;	ALL TRACKS AND SECTORS TELLING YOU WHICH ONES FAILED TO FORMAT.


;******************************************************************************
;***************		EQUATE TABLE			***************
;******************************************************************************


WBOOT	EQU	0			;CP/M JUMP LOCATION FOR A WARM BOOT
MONITR	EQU	0F000H			;BASE OF PFM MONITOR JUMP TABLE

WDSTAT	EQU	10H			;1771 STATUS ADDRESS
WDCTL	EQU	WDSTAT			;CONTROL=STATUS WRITE
WDATA	EQU	13H			;1771 DATA I/O

HOME	EQU	MONITR+1EH		;PFM-80 HEAD HOME ROUTINE
SEEK	EQU	MONITR+21H		;PFM-80 SEEK TRACK ROUTINE
SELECT	EQU	MONITR+1BH		;PFM-80 SELECT DRIVE ROUTINE
READ	EQU	MONITR+24H		;PRM-80 READ SECTOR ROUTINE
OVECTR	EQU	MONITR+0CH		;PFM-80 CONSOLE OUTPUT ROUTINE
CONIN	EQU	MONITR+9H		;PFM-80 CONSOLE INPUT ROUTINE

BDOS	EQU	5			;FDOS ENTRY POINT
BCONIN	EQU	1			;CONSOLE READ CONTROL BYTE
BCONOT	EQU	2			;CONSOLE WRITE CONTROL BYTE
BPSTRG	EQU	9			;PRINT STRING CONTROL BYTE

CR	EQU	0DH			;ASCII CARRIAGE RETURN
LF	EQU	0AH			;ASCII LINE FEED
ESC	EQU	1BH			;ASCII ESCAPE



	ORG	100H			;STANDARD CP/M COM PROGRAM


;	SIGNON WITH FORMAT MESSAGE

	LD	DE,SIGNON		;DE POINTS TO SIGNON MESSAGE
	LD	C,BPSTRG		;FDOS CONTROL TO PRINT STRING
	CALL	BDOS			;DISPLAY MESSAGE

;	DETERMIN WHICH DRIVE TO FORMAT DISK IN

SELAGN:	LD	C,BCONIN		;FDOS CONTROL TO READ CHARACTER
	CALL	BDOS			;WAIT FOR DRIVE CHARACTER
	PUSH	AF			;SAVE DRIVE #
	CP	'A'			;CHECK FOR MIN DRIVE #
	JP	C,SELERR		;IF LESS THEN 'A', ERROR
	CP	'E'			;CHECK FOR MAX DRIVE #
	JP	NC,SELERR		;IF GREATER THAN 'D', ERROR
	AND	07H			;ONLY WANT TO LOOK AT LOWER 3 BITS
	DEC	A			;ASCII CHARACTER 1 GREATER THAN DRIVE #
	LD	C,A
	CALL	SELECT			;IF OK, SELECT DRIVE
	JP	NZ,SELERR

;	PRINT DRIVE STATUS AND THEN WAIT FOR READY SIGNAL

	LD	DE,STATSB		;DE POINTS TO BEGINNING STATUS MESSAGE
	LD	C,BPSTRG		;FDOS CONTROL TO PRINT STRING
	CALL	BDOS			;DISPLAY MESSAGE
	POP	AF			;GET DRIVE # BACK
	LD	E,A			;LOAD DRIVE # IN E FOR FDOS TO PRINT
	LD	C,BCONOT		;FDOS CONTROL TO PRINT CHARACTER
	CALL	BDOS			;PRINT DRIVE #
	LD	DE,STATSE		;DE POINTS TO ENDING STATUS MESSAGE
	LD	C,BPSTRG
	CALL	BDOS			;PRINT REMAINDER OF MESSAGE
	JP	RD			;SEE IF USER WANTS TO FORMAT OR QUIT?


;	START OF FORMATTING ROUTINE

FORMAT:	LD	DE,HEADER		;DE POINTS TO TRACK DISPLAY HEADER
	LD	C,BPSTRG
	CALL	BDOS			;PRINT HEADER

;	FIRST, SET UP ONE TRACK'S DATA IMAGE

	LD	HL,DATA			;POINT TO DATA AREA OF DISK IMAGE
	LD	DE,DATA+1
	LD	(HL),0E5H		;FILL DATA AREA WITH BLANK VALUE
	LD	BC,127			;DATA FIELD IS 128 BYTES LONG
	LDIR				;FILL DATA @ HL TO DE

;	COPY ONE SECTOR 25 TIMES

	LD	HL,SECT1		;START OF SECTOR 1
	LD	DE,SECT2		;START OF SECTOR 2
	LD	BC,186*25		;EACH SECTOR CONTAIN 186 BYTES DATA
	LDIR				;COPY SECTOR 1 25 TIMES

;	NOW SET UP SECTOR NUMBER IN PROPER POSITION

	LD	HL,SECTNO		;POINT TO SLOT IN FIRST IMAGE
	LD	DE,186			;OFFSET INTO NEXT SECTOR
	LD	BC,26*256+1		;B=COUNTER C=SECTOR #
SECTID:	LD	(HL),C			;STORE SECTOR #
	INC	C			;INCREMENT SECTOR #
	ADD	HL,DE			;POINT TO NEXT SECTOR ID
	DJNZ	SECTID			;DO ALL 26 SECTORS

;	NOW PUT TRAILER OF FF'S AFTER WHOLE TRACK

	LD	HL,SECT1+4836		;THAT'S A LOT OF TRACK DATA
	LD	A,-1			;NEED 247 BYTES OR FF, SO DO
					;256 FOR INSURANCE
	LD	B,0
ENDMRK:	LD	(HL),A			;STORE FF
	INC	HL
	DJNZ	ENDMRK			;STORE 256 FF'S

;	NOW SET UP FOR FORMATTING

	LD	A,(66H)			;GET NMI VECTOR BYTE
	PUSH	AF			;SAVE IT
	LD	A,0C9H
	LD	(66H),A			;LOAD RETURN INSTRUCTION AT VECTOR


;	DO THE FORMAT

	DI				;NO INTERRUPTS
	LD	C,0			;START WITH TRACK 0
NXTTRK:	LD	B,26			;26 SECTORS PER TRACK
	PUSH	BC			;WE'LL NEED THEM LATER

;	SEEK NEXT TRACK IN SEQUENCE

	CALL	SEEK

	POP	BC			;GET TRACK # AND SECTOR CTR BACK
	PUSH	BC			;LETS SAVE THEM AGAIN

;	PUT TRACK ID'S IN PLACE

	LD	HL,TRKNO		;POINT TO POSITION IN IMAGE
	LD	DE,186			;OFFSET FOR EACH SECTOR
TRAKID:	LD	(HL),C			;STORE CURRENT TRACK #
	ADD	HL,DE			;POINT TO NEXT SECTOR
	DJNZ	TRAKID


;	DO THE TRACK WRITE

	LD	HL,LEADER		;POINT TO DATA
	LD	D,20			;20*256+36=TOTAL BYTES
	LD	B,36
	LD	C,WDATA			;C POINTS TO 1771 DATA PORT
	LD	A,0F4H			;1771 WRITE TRACK COMMAND
	OUT	(WDCTL),A		;SEND COMMAND

NXTBYT:	HALT				;WHEN 1771 READY, WILL NMI
	OUTI				;SEND DATA
	JR	NZ,NXTBYT
	DEC	D			;OUTER BYTE COUNT
	JR	NZ,NXTBYT

;	PRINT TRACK # AND SETUP FOR NEXT TRACK

	POP	BC			;GET TRACK COUNTER BACK
	LD	A,C			;A=TRACK PRINT OFFSET
	CALL	PNTRK			;PRINT TRACK #
	INC	C			;UPDATE TRACK COUNT
	LD	A,C			;GET NEW TRACK #
	CP	77			;HAVE WE DONE 76 TRACKS
	JR	NZ,NXTTRK		;KEEP FORMATTING IF NOT DONE


;******************************************************************************
;******************************************************************************
;**************							***************
;**************		   VERIFY TRACK/SECTOR			***************
;**************							***************
;******************************************************************************
;******************************************************************************


;	DO A CARRIAGE RETURN-LINE FEED FOR TRACK VERIFICATION MESSAGE

	LD	DE,CRLF
	LD	C,BPSTRG
	CALL	BDOS			;PRINT CR,LF

;	SET TRACK TO 0 AND START TESTING

	LD	E,0			;E=TRACK #

AGAIN:	LD	BC,1A01H		;B=LOOP COUNT C=SECTOR #
	PUSH	BC			;SAVE STATUS DATA
	LD	C,E			;C=TRACK #
	CALL	SEEK			;USE PFM TO SEEK TRACK
	JP	NZ,PNTERR		;JUMP IF SEEK ERROR OCCURS
	POP	BC			;GET STATUS DATA BACK

;	TEST ALL SECTORS ON TRACK

NXTRD:	PUSH	BC			;SAVE STATUS DATA AGAIN
	LD	HL,80H			;DISK READ BUFFER AREA
	CALL	READ			;USE PFM TO READ SECTOR
	JP	NZ,PNTERR		;JUMP IF READ ERROR OCCURS
	POP	BC			;GET STATUS DATA BACK
	INC	C			;INCREMENT SECTOR COUNT
	DJNZ	NXTRD			;CONTINUE TO READ UNTIL ALL
					;26 SECTORS ARE READ

;	PRINT A "V" IF ALL IS WELL FOR THIS TRACK

	LD	A,'V'
	CALL	OVECTR			;USE PFM TO PRINT CHARACTER
	JR	AROUND			;SKIP AROUND ERROR MESSAGE

;	PRINT A "N" IF THERE WAS A TRACK OR SECTOR READ ERROR

PNTERR:	LD	A,'N'
	CALL	OVECTR			;USE PFM TO PRINT CHARACTER

;	INCREMENT TRACK COUNTER AND TEST IF DONE

AROUND:	INC	E			;INCREMENT TRACK #
	LD	A,E			;GET TRACK #
	CP	77			;SEE IF WE HAVE DONE 77 TRACKS
	JR	NZ,AGAIN		;KEEP ON VERIFYING IF NOT DONE

;	SET UP BIGBOARD FOR A RETURN TO CP/M IF THROUGH FORMATTING DISKS

END1:	POP	AF			;GET NMI VECTOR BYTE BACK
	LD	(66H),A			;RESTORE MNI
	EI				;ENABLE INTERUPTS
	LD	DE,NXTFMT		;POINT TO NEXT FORMAT MESSAGE
	LD	C,BPSTRG		;FDOS PRINT STRING COMMAND
	CALL	BDOS			;PRINT STRING
	JP	RD			;TEST USER RESPONSE

;	RETURN TO CP/M IF DONE

END2:	JP	WBOOT


;******************************************************************************
;******************************************************************************
;*************	             SPECIAL ROUTINES			***************
;******************************************************************************
;******************************************************************************

;	ROUTINE TO DISPLAY SELLECT ERROR MESSAGE

SELERR:	LD	DE,SLTERR		;POINT TO ERROR MESSAGE
	LD	C,BPSTRG
	CALL	BDOS			;PRINT STRING
	JP	SELAGN			;TRY AGAIN

;	ROUTINE TO READ USER FORMAT RESPONSES

RD:
	CALL	CONIN			;READ CHARACTER
	CP	0DH			;LOOK FOR CARRIAGE RETURN
	JP	Z,FORMAT		;FORMAT IF CR
	CP	03H			;LOOK FOR CONTROL C
	JP	Z,END2			;EXIT PROGRAM IF ^C
	JR	RD			;WAIT FOR CORRECT RESPONSE

;	ROUTINE TO PRINT TRACK #

PNTRK:
	LD	HL,TRKPNT		;POINT TO BASE OF TRACK #
	ADD	A,L			;ADD OFFSET
	LD	L,A			;SET HL TO POINT TO CORRECT TRACK #
	LD	A,(HL)			;GET TRACK #
	CALL	OVECTR			;PRINT THE #
	RET


;******************************************************************************
;******************************************************************************
;**************	                   MESSAGES			***************
;******************************************************************************
;******************************************************************************


;	SIGNON MESSAGE

SIGNON:
	DEFB	CR,LF,LF
	DEFB	'Bigboard Disk Formatter      version 2.1'
	DEFB	CR,LF,LF
	DEFB	'Disk to format is in drive A,B,C or D? '
	DEFB	'$'

;	SELLECT ERROR MESSAGE

SLTERR:
	DEFB	CR,LF
	DEFB	'WRONG, try again '
	DEFB	'$'

;	STATUS MESSAGE (BEGINNING)

STATSB:
	DEFB	CR,LF,LF
	DEFB	'Disk to format is in drive '
	DEFB	'$'

;	STATUS MESSAGE (ENDING)

STATSE:
	DEFB	':'
	DEFB	CR,LF,LF
	DEFB	'Type <ret> to format (^C to Quit) >'
	DEFB	'$'

;	NEXT FORMAT MESSAGE

NXTFMT:
	DEFB	CR,LF,LF
	DEFB	'FUNCTION COMPLETE!'
	DEFB	CR,LF
	DEFB	'Load next diskette, then type <ret> to format (^C to quit) >'
	DEFB	'$'

;	TRACK HEADER DISPLAY

HEADER:
	DEFB	CR,LF,LF
	DEFB	'0         1         2         3         4         5         6'
	DEFB	'         7'
	DEFB	CR,LF
	DEFB	'$'

;	TRACK #'S

TRKPNT:
	DEFB	'0123456789012345678901234567890123456789012345678901234567890'
	DEFB	'1234567890123456'

;	CARRIAGE RETURN-LINE FEED TO PLACE VERIFY STATUS UNDER TRACK #

CRLF:
	DEFB	CR,LF
	DEFB	'$'


;******************************************************************************
;******************************************************************************
;**************			   TRACK DATA			***************
;******************************************************************************
;******************************************************************************

;	40 BYTES FF AS LEADER

LEADER:
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1

;	6 BYTES OF 0'S

	DEFW	0
	DEFW	0
	DEFW	0

;	WRITE INDEX MARK COMMAND

	DEFB	0FCH

;	26 BYTES OF FF

	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1

;	SECTOR DATA STARTS HERE

SECT1:
	DEFW	0
	DEFW	0
	DEFW	0

;	WRITE ID ADDRESS MARK COMMAND

	DEFB	0FEH

;	TRACK #

TRKNO:
	DEFW	0

;	SECTOR #

SECTNO:
	DEFW	0

;	WRITE CRC COMMAND

	DEFB	0F7H

;	11 BYTES OF FF

	DEFB	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1

;	6 BYTES OF 0'S

	DEFW	0
	DEFW	0
	DEFW	0

;	WRITE DATA ADRESS COMMAND

	DEFB	0FBH

;	128 BYTE DATA AREA (TO BE FILLED WITH E5)

DATA:
	DEFS	128

;	WRITE CRC COMMAND

	DEFB	0F7H

;	27 BYTES OF FF

	DEFB	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1
	DEFW	-1

			;END OF ONE SECTOR'S DATA

;	UPON EXECUTION, THE PRECEDING SECTOR'S DATA WILL BE
;	DUPLICATED 25 TIMES TO GIVE A FULL 26 SECTORS WORTH
;	OF DATA.  THE 256 BYTES FOLLOWING THE FULL TRACK'S
;	DATA WILL BE FILLED WITH FF'S.  THIS FILLS THE AREA
;	BETWEEN THE LAST SECTOR AND THE NEXT INDEX.  THE WD-
;	1771 EXITS THE 'WRITE TRACK' MODE ON RECEIPT OF THE
;	INDEX SIGNAL.


SECT2:					;STARTING POINT FOR REMAIDER OF
					;SECTORS


	END
