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

                              .LCTL



;                          **********
	.TITLE            "VERIFY.COM"
;                          **********


;                        Version:    1.00

;                  First Written:    06/10/90

;                  Last Modified:    06/10/90



;	LABEL DATA:
                      VERSION	=       '1'
                      MODIF	=	'00'
                      CHANGE	=	' '

                      MONTH	=	'06'
                      DAY	=	'10'
                      YEAR	=	'90'



;                            ******
;                            SAMPLE
;                            DIALOG:
;                            ******



;	>



;                           *******
;                           HISTORY:
;                           *******



;	06/10/90:	Q & D modification of COPYDISK
;			("CLONE"), to do verify-read 
;			of formatted floppy disks.
;			Takes about a minute per disk.



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



;                          ********
;                          ASSEMBLY
;                          CONTROLS:
;                          ********



			.PABS
			.PHEX

			.RADIX	16
			.LADDR



;                         **********
;                          SYMBOLIC
;                         REFERENCES:
;                         **********



;                        CP/M  SYSTEM:
;                        ----  ------


		PAGE.0		==	0000
		BIOS.JUMP	==	PAGE.0 + 0001
		IO.BYTE		==	PAGE.0 + 0003
		USER.DRIVE	==	PAGE.0 + 0004
		BDOS.JUMP	==	PAGE.0 + 0005
		SYSTEM		==	BDOS.JUMP
		DEF.FCB		==	PAGE.0 + 005C
		DEF.DISK.BUFF	==	PAGE.0 + 0080
		TPA		==	PAGE.0 + 0100


;                        CHARACTER  I/O:
;                        ---------  ---


		WARM.BOOT	==	0
		CONS.INPUT	==	1
		CONS.OUTPUT	==	2
		LIST.CHAR	==	5
		CONS.DIRECT	==	6
		STRING.PRINT	==	9
		  END.MESSAGE	==	0
		READ.BUFFER	==	0A
		CONS.STATUS	==	0B

		BREAK		==	''


;                            ASCII:
;                            -----


		NULL		==	00
		BEL		==	07
		BACKSPACE	==	08
		LF		==	0A
		CR		==	0D
		SPACE		==	20
		FORMFEED	==	0C
		RUBOUT		==	7F
		DEL		==	RUBOUT
		QUESTION.MARK	==	'?'
		HUH		==	QUESTION.MARK
		CNTRL.CHAR	==	'^'


;                           UTILITY:
;                           -------


		ZERO		==	0000
		OFF		=	ZERO
		ON		=	#ZERO
		CLEAR		=	OFF
		SET		=	ON
		OK		=	ZERO
		NOT.OK		=	#ZERO


;                            MAPPING:
;                            -------


		LOAD.POINT	==	TPA

		STACK.SIZE	==	20 ; words


;                           PROGRAM:
;                           -------


		HOME		==	0F218
		SELDSK		==	HOME + 3
		SETTRK		==	HOME + 6
		SETSEC		==	HOME + 9
		SETDMA		==	HOME + 0C
		READ		==	HOME + 0F
		WRITE		==	HOME + 12
		SECTRAN		==	HOME + 18
		


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



;                          *********
;                          PROCEDURE:
;                          *********



		       .LOC   LOAD.POINT


			     FIRST:
	JMP	START


;                            LABEL:
;                            -----


..NAME:
		.ASCII	'  VERIFY.COM'
		.BYTE	END.MESSAGE

VERS.NUMBER:
		.ASCII	'Version:  '
		.BYTE	VERSION
		.BYTE	'.'
		.BYTE	MODIF / 100
		.BYTE	MODIF @ 100
		.BYTE	CHANGE
		.BYTE	END.MESSAGE

..DATE:
		.ASCII	'Date:  '
		.BYTE	MONTH / 100
		.BYTE	MONTH @ 100
		.BYTE	'/'
		.BYTE	DAY / 100
		.BYTE	DAY @ 100
		.BYTE	'/'
		.BYTE	YEAR / 100
		.BYTE	YEAR @ 100
		.BYTE	END.MESSAGE



START:
	LXI	SP, TOP.STACK

MAIN:
	LXI	D, HELLO
	CALL	FLASH
	LXI	D, VERS.NUMBER
	CALL	FLASH
	CALL	CRLF
	CALL	LFEED
	CALL	LFEED

	LXI	D, CUE.SWAP
	CALL	FLASH
	CALL	WAIT.CUE
	CALL	LFEED

VERIFY.OBJECT.DISK:
	LXI	D, CHECKING.COPY
	CALL	FLASH

	MVI	A, CLEAR
	STA	ERROR.FLAG

	LXI	H, 00
	SHLD	TRACKS.COMPLETED

	LXI	D, VERIF.MESSAGE
	CALL	FLASH
	CALL	MARK.PROGRESS
	CALL	SPC1

	LXI	H, TRANSFER.BUFFER
	SHLD	BUFFER.POINTER

	CALL	LOAD.TRACK.0

	LXI	H, 01
	SHLD	TRACK.NUMBER
	SHLD	TRACKS.COMPLETED

	MVI	A, 4C			; 76 D/D Tracks
	STA	$TRACKS

..LOOP:
	LXI	H, TRANSFER.BUFFER
	SHLD	BUFFER.POINTER

	CALL	LOAD.1.TRACK

	MVI	A, BACKSPACE
	CALL	PUTCHAR
	CALL	PUTCHAR
	CALL	PUTCHAR
	CALL	MARK.PROGRESS
	CALL	SPC1

	CALL	IF.KEY.GET
	CPI	CLEAR
	JRZ	..KEEP.GOING
	CPI	BREAK
	JRNZ	..KEEP.GOING

	LXI	D, ERAS.MESSAGE
	CALL	FLASH
	LXI	D, ABORT.MESSAGE
	CALL	FLASH
	CALL	MARK.PROGRESS
	CALL	CRLF
	CALL	LFEED

	LDA	ERROR.FLAG
	CPI	CLEAR
	JRZ	EXIT

	LXI	D, FAILED.VERIFY
	CALL	FLASH
	JMPR	EXIT

..KEEP.GOING:
	LXI	H, TRACKS.COMPLETED
	INR	M

	LXI	H, $TRACKS
	DCR	M
	JRNZ	..LOOP

	LXI	D, ERAS.MESSAGE
	CALL	FLASH

	LDA	ERROR.FLAG
	CPI	CLEAR
	JRZ	..OK

	LXI	D, FAILED.VERIFY
	CALL	FLASH
	JMPR	EXIT

..OK:
	LXI	D, PASSED.VERIFY
	CALL	FLASH

EXIT:
	LXI	D, REPEAT.ASK
	CALL	FLASH

..WAIT:
	CALL	GETCH
	CALL	TO.UPPER

	CPI	'Y'
	JRZ	..YES

	CPI	'N'
	JRZ	..NO
	CPI	CR
	JRZ	..NO
	CPI	BREAK
	JRZ	..NO

	JMPR	..WAIT

..YES:
	CALL	ECHO

	JMP	MAIN

..NO:
	MVI	A, 'N'
	CALL	PUTCHAR
	CALL	CRLF
	CALL	LFEED

	LXI	D,DISK.PROMPT
	CALL	FLASH

	CALL	WAIT.CUE

	CALL	LFEED
	LXI	D, GOODBYE
	CALL	FLASH

	JMP	WARM.BOOT

	

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



;                           ********
;                           MESSAGES:
;                           ********



HELLO:
	.BYTE	FORMFEED
	.ASCII	'          '
	.ASCII	'    FLOPPY DISK VERIFICATION UTILITY    '
	.BYTE	END.MESSAGE

CUE.SWAP:
	.ASCII	'     Put The Test Disk In Drive "A" <CR>:   '
	.BYTE	END.MESSAGE

CHECKING.COPY:
	.ASCII	'     VERIFYING  .  .  .  '
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE

VERIF.MESSAGE:
	.ASCII	'     TESTING TRACK '
	.BYTE	END.MESSAGE

ERAS.MESSAGE:
	.BYTE	CR
	.ASCII	'                     '
	.BYTE	CR
	.BYTE	END.MESSAGE

ABORT.MESSAGE:
	.ASCII	'     ABORTED AT TRACK  '
	.BYTE	END.MESSAGE

BUM.READ:
	.BYTE	CR, LF, LF
	.ASCII	'             *** READ '
	.BYTE	END.MESSAGE

ERROR:
		.ASCII	' ERROR AT TRACK  '

	ERR.TRACK:
		.BLKB	2

		.ASCII	'  :  SECTOR  '

	ERR.SECTOR:
		.BLKB	2

		.ASCII	' ***'
		.BYTE	CR, LF, LF
		.BYTE	END.MESSAGE

PASSED.VERIFY:
	.ASCII	'     ALL TRACKS VERIFIED'
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE

FAILED.VERIFY:
	.ASCII	/                     *** CAN'T VERIFY THIS DISK! ***/
	.BYTE	CR, LF, LF
	.BYTE	BEL
	.BYTE	END.MESSAGE

REPEAT.ASK:
	.ASCII	'     More Diskettes?    (Yes or No):   '
	.BYTE	END.MESSAGE

DISK.PROMPT:
	.ASCII	'     Re-Insert The System Disk <CR>:   '
	.BYTE	END.MESSAGE

GOODBYE:
	.ASCII	'     EXIT TO CP/M'
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE



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



;                         ***********
;                         SUBROUTINES:
;                         ***********



;                     CP/M  CHARACTER  I/O:
;                     ----  ---------  ---


IF.KEY.GET:

;		GET CHARACTER, IF AVAILABLE.
;		IF NOT, RETURN ZERO IN "A":

	CALL	REG.SAVE

Š	MVI	C, CONS.DIRECT
	MVI	E, SET
	CALL	SYSTEM
	CPI	ZERO

	CALL	REG.RESTORE

	RET

GETCH:
	CALL	REG.SAVE

GETC1:
	MVI	C, CONS.DIRECT
	MVI	E, SET
	CALL	SYSTEM
	CPI	ZERO
	JZ	GETC1

	CALL	REG.RESTORE

	RET

TO.UPPER:
	CPI	'a'
	RM
	CPI	'z' + 1
	RP
	SUI	20H

        RET

PUTCHAR:
ECHO:
	PUSH	PSW
	CALL	REG.SAVE

	MOV	E, A
	MVI	C, CONS.OUTPUT
	CALL	SYSTEM

	CALL	REG.RESTORE
	POP	PSW

	RET

FLASH:
	CALL 	REG.SAVE

..FL1:
	LDAX	D
	CPI	END.MESSAGE
	JRZ	..FL2

	CALL	PUTCHAR
	INX	D
	JMPR	..FL1

..FL2:
	CALL	REG.RESTORE

	RET

REG.SAVE:
	XTHL
	PUSH	D
	PUSH	B
	PUSH	H

	RET

REG.RESTORE:
	POP	H
	POP	B
	POP	D
	XTHL

	RET


;                  CONSOLE UTILITY:
;                  ------- -------


CRLF:
	MVI	A, CR
	CALL	PUTCHAR
	MVI	A, LF
	CALL	PUTCHAR

	RET

LFEED:
	MVI	A, LF
	CALL	PUTCHAR

	RET

BEEP:
	MVI	A, BEL
	CALL	PUTCHAR

	RET

SPC1:
	PUSH	PSW

	MVI	A, SPACE
	CALL	PUTCHAR

	POP	PSW

	RET

SPC5:
	MVI	B, 5
	CALL	SSPC

	RET

SSPC:
	MVI	A, SPACE
	CALL	PUTCHAR
	DCR	B
	JNZ	SSPC

	RET


;                           PROGRAM:
;                           -------


WAIT.CUE:
	CALL	GETCH
	CPI	BREAK
	JNZ	..CUE1

	CALL	LFEED
	CALL	LFEED

	JMP	WARM.BOOT

..CUE1:
	CPI	CR
	JRZ	..CUE2

	JMPR	WAIT.CUE

..CUE2:
	LXI	D, ..VISIBLE
	CALL	FLASH
	CALL	CRLF

	RET

..VISIBLE:
	.ASCII	'<CR>'
	.BYTE	END.MESSAGE

LOAD.1.TRACK:
	LBCD	TRACK.NUMBER
	CALL	SETTRK

	MVI	A, 1
	STA	SECTOR.NUMBER

LOOP.LOAD:
	LBCD	SECTOR.NUMBER
	CALL	SETSEC

	LBCD	BUFFER.POINTER
	CALL	SETDMA

	CALL	READ

	CPI	OK
	JZ	..OK

	MVI	A, SET
	STA	ERROR.FLAG

	LDA	TRACK.NUMBER
	CALL	CONVERT
	MOV	A, B
	ORI	30
	STA	ERR.TRACK
	MOV	A, C
	ORI	30
	STA	ERR.TRACK + 1

	LDA	SECTOR.NUMBER
	CALL	CONVERT
	MOV	A, B
	ORI	30
	STA	ERR.SECTOR
	MOV	A, C
	ORI	30
	STA	ERR.SECTOR + 1

	LXI	D, BUM.READ
	CALL	FLASH
	LXI	D, ERROR
	CALL	FLASH

	LXI	D, VERIF.MESSAGE  ; CLEAN UP AFTER
	CALL	FLASH		  ; THE BIOS MESSAGE
	CALL	MARK.PROGRESS
	CALL	SPC1

..OK:
	LHLD	BUFFER.POINTER
	LXI	D, 80
	DAD	D
	SHLD	BUFFER.POINTER

	LXI	H, SECTOR.NUMBER
	MOV	A, M
	INR	M

CODE.1.MARKER:
	CPI	34
	JNZ	LOOP.LOAD

	LXI	H, TRACK.NUMBER
	INR	M

	RET

MARK.PROGRESS:
	LDA	TRACKS.COMPLETED
	CALL	CONVERT
	MOV	A, B
	ORI	30
	CALL	PUTCHAR
	MOV	A, C
	ORI	30
	CALL	PUTCHAR

	RET

CONVERT:

;	CONVERTS BYTE IN "ACC" ( < 100 )
;	TO TWO 16-BIT NYBBLES IN "BC":

	MVI	B, ZERO

..LOOP:
	SUI	0A
	JM	..STOP
	INR	B
	JMPR	..LOOP

..STOP:
	ADI	0A
	MOV	C, A
	MOV	A, B

	RET

LOAD.TRACK.0:

;		Y-e-e-s  .  .  .  Self-Modifying Code:

	LXI	H, 0
	SHLD	TRACK.NUMBER
	MVI	A, 1A			; 26 Sectors
	STA	CODE.1.MARKER + 1
	CALL	LOAD.1.TRACK
	MVI	A, 34			; Normally 52
	STA	CODE.1.MARKER + 1

	RET



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



;                             ***
;                             RAM:
;                             ***



		  .LOC   ( . + 0F ) & 0FFF0


			RAM.VARIABLES:



TRACK.NUMBER:
		.WORD	0

SECTOR.NUMBER:
		.WORD	0

SKEW.TABLE.POINTER:
		.WORD	0	; SECTOR SKEW FACTOR

BUFFER.POINTER:
		.WORD	0

ERROR.FLAG:
		.BYTE	0

TRACKS.COMPLETED:
		.BYTE	0

$REPEATS:
		.BYTE	0

$TRACKS:
		.BYTE	0



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



;                            *****
;                            STACK:
;                            *****



		    .LOC  ( . + 0F ) & 0FFF0


		   .BLKW	STACK.SIZE


			   TOP.STACK:



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



;                          ********
;                          TRANSFER
;                           BUFFER:
;                          ********



	               TRANSFER.BUFFER:

;		     BDOS BEGINS AT E300



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



;                        ************
;                          ASSEMBLY
;                        TERMINATION:
;                        ************



			     LAST:


	      SIZE.PROGRAM   ==   LAST - FIRST



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



			.END	FIRST


