
;********************************************************
;*                     DUF05.ASM                        *
;*                DISK UTILITY FUNCTIONS                *	
;*                 USED FOR CP/M & MP/M                 *
;*                 BRUCE JONES 01/13/83                 *
;********************************************************



;	.I8080		;JUST 8080 CODE

	.PABS
	.PHEX
	.XLINK
	.XSYM
	.LOC	100H

	TRUE	==	0FFFFH
	FALSE	==	#TRUE

;USE TDL OR CDL ZASM TO ASSEMBLE

;********************************************************
;	        CP/M INTERFACE FUNCTIONS
;********************************************************

	SRESET	==	0	;RESET DISK SYSTEM
	GETCON	==	1	;GET CONSOLE
	PRTCON	==	2	;OUTPUT CONSOLE
	LIST		==	5	;LIST OUTPUT
	PRINTS	==	9	;PRINT STRING
	GETBUF	==	10	;GET CONSOLE BUFFER
	CONST		==	11	;GET CONSOLE STATUS
	GETVER	==	12	;GET VERSION NUMBER
	DSKRST	==	13	;RESET DISK SYSTEM
	SLDISK	==	14	;SELECT DISK
	OPENF		==	15	;OPEN FILE
	CLOSEF	==	16	;CLOSE FILE
	SEARCH	==	17	;SEARCH FOR MATCH
	SRHNXT	==	18	;SEARCH FOR NEXT
	DELETE	==	19	;DELETE FILE
	READF		==	20	;READ FILE
	WRITEF	==	21	;WRITE FILE
	MAKEF		==	22	;MAKE FILE
	RENAME	==	23	;RENAME FILE
	RETLOG	==	24	;RETURN LOGIN VECTOR
	RETDSK	==	25	;RETURN CURRENT DISK
	DMAF		==	26	;SET DMA ADDRESS
	GETADD	==	27	;GET ALLOCATION VECTOR ADDRESS
	WRTPRO	==	28	;WRITE PROTECT DISK
	SETATT	==	30	;SET FILE ATTRIBUTES
	GETDPB	==	31	;GET ADDRESS OF DPB FOR DISK
	SETUSR	==	32	;GET/SET USER CODE
	RESET		==	37	;RESET DRIVES FOR NEW DISK

	BDOS		==	5	;BDOS ENTRY


;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;	            CONSOLE CHARS
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

	BELL	==	7	;BELL
	TAB	==	9	;TAB OVER 8 CHARS
	CR	==	0DH	;CARRIAGE RETURN
	LF	==	0AH	;LINE FEED
	CLEAR	==	1AH	;CLEAR SCREEN

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;	            PRINTER CHARS
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

	FF	==	0CH	;FORM FEED
	
	EOL	==	'$'	;CP/M END OF LINE MARKER
	TMPBUF	==	80H	;DEFAULT DMA BUFFER


;========== ASSEMBLY TIME SWITCHES =============


;PROTCT IS USED FOR INITIAL TESTING OF DUF
;IF == 0, PROTECTION IS ENABLED AND THE PROGRAM
;HALTS ON ANY SERIOUS DISK ERROR TO PREVENT
;SECTOR MODIFICATION

PROTCT	=\	\ENTER 0 FOR PROTECTION, 1 IF NOT \

;ROMER IS USED TO RUN ONLY FOR THE ZEUS80 CPU BOARD
;IF == 0, A CHECK IS MADE FOR A VALID ROM

;*********** NOTE ***********
;FOR GENERAL CP/M SYSTEM USE SET PROTCT & ROMER TO "1"


ROMER	=\	\ENTER 0 FOR ROM TEST, 1 IF NOT    \

;********************************************************
; STARTUP. MAKE LOCAL BIOS TABLE & RESET PRINTER ECHO
;******************************************************** 

START:
	LXI	SP,STACK	;PUT HERE


;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                 TEST FOR CP/M OR MP/M
;            IF MP/M GET CONTROL OF DISK QUEUE
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::


;		SEE IF CP/M OR MP/M NEXT
;		IF MP/M GET CONTROL OF MXDisk QUEUE


	MVI	C,12	;GET VERSION NUMBER
	CALL	BDOS
	MOV	A,H	;SEE IF CP/M OR MP/M
	STA	VERFLG	;SAVE FOR EXIT
	JZ	CPM	;IF 0 THEN ITS' CP/M

	MVI	A,0FFH
	STA	DSKQ	;SET MXDISK FLAG AS TRUE

	MVI	C,9CH	;GET PROCESS DESC. ADDRESS
	CALL	BDOS
	LXI	D,6	;ADD NAME OFFSET
	DAD	D	;POINT HL TO IT
	MOV	A,M	;GET 1st BYTE
	ANI	7FH	;STRIP BIT 7
	MOV	M,A	;PUT BACK IN DESC. NAME
	

	MVI	C,135	;OPEN QUEUE
	LXI	D,UMXDSK
	CALL	BDOS



	MVI	C,137	;READ QUEUE
	LXI	D,UMXDSK;FOR MXDisk
	CALL	BDOS
	XRA	A
	STA	MSGADD+14	;PUT 0 IN MESSAGE AT 15th BYTE

	JMP	CPM



;		FOLLOWING IS UQCB TO GET MXDisk FOR THIS PROCESS

UMXDSK:
		
	.BYTE	0,0	;TWO BYTES FOR QUEUE ADDRESS
	.WORD	MSGADD	;MESSAGE WRITTEN HERE
	.ASCII	\MXDisk  \	;NAME TO GET
MSGADD:	.BLKB	33	;33 BYTES FOR STORAGE



FREQUE:

;		RELEASE THE MXDisk QUEUE NEXT

	LDA	DSKQ	;SEE IF WE HAD HELD MXDISK
	ORA	A
	JRZ	..NOQU
	MVI	C,139	;WRITE BACK TO QUEUE
	LXI	D,UMXDSK;UFORMS' Q.C.B.
	CALL	BDOS

..NOQU:
	MVI	C,0	;MP/M RESET SYSTEM
	XRA	A
	JMP	BDOS	;EXIT HERE FOR MP/M
	JMP	ZERO

DSKQ:		.WORD	0
VERFLG:	.WORD	0

	

CPM:

	CALL	BVECT		;SET UP BIOS POINTERS
	LXI	H,0
	SHLD	BADNUM	;NO BAD RECORDS YET
	MVI	A,1
	STA	LSTER		;TURN OFF LIST ECHO
	CALL	BADIT		;SET FIRST BAD FILE NAME


	.IFE	PROTCT,[

	LXI	B,7FH
	CALL	SETSEC
	LXI	B,2
	CALL	SETTRK
	LXI	B,FILBUF
	CALL	SETDMA
	CALL	SECRD
	ORA	A
	JZ	SIGON
	HLT
		]


;********************************************************
;        SIGN ON AND GET DRIVE TO TEST
;********************************************************

SIGON:
	MVI	C,PRINTS	;SHOW USER THE PROGRAM
	LXI	D,MESS1		;AND GET TEST DRIVE
	CALL	BDOS		;IF ANY
	CALL	GETDRV
	JNC	SIGON		;IF DRIVE NOT VALID
	STA	TEST		;SAVE DRIVE HERE
	CALL	GETPRM	;GET DPH ETC FOR THIS DRIVE
	JMP	GETOPT


;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;            GET A DRIVE FROM THE USER
;            RETURN WITH IT IN ACC.
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

GETDRV:
	MVI	C,GETCON	;GET ANSWER
	CALL	BDOS
	CPI	3		;IF ^C THEN GO WARM BOOT
	JZ	ZERO
	CPI	27
	JZ	PRMPT
	CPI	'Q'
	JC	UPPER
	SUI	'a'-'A'	;GET UPPER CASE
UPPER:
	CPI	'Q'		;SEE IF VALID
	RNC	
	CPI	'A'
	JC	TOOLOW
	SUI	'A'		;GET HEX VALUE
	CPI	17
	RET
TOOLOW:
	CMC
	RET

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;          GET PARAMETERS FOR DRIVE IN ACC.
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

GETPRM:
	MVI	B,0
	MOV	C,A		;GET THIS DISK
	PUSH	B		;SAVE IT
	LXI	B,DIRBUF	;SET SAFE DMA AREA
	CALL	SETDMA	;HAVE BIOS SET IT
	POP	B		;GET BACK DRIVE
	MVI	E,0		;FIRST SELECT
	CALL	SELDSK	;HAVE BIOS SELECT DRIVE
	SHLD	DPHADD	;SAVE DPH ADDRESS VECTOR
	MOV	A,M		;NOW GET XLATE VECTOR LOW BYTE
	INX	H
	MOV	H,M		;GET HIGH BYTE
	MOV	L,A
	SHLD	XLATE		;SAVE XLATE VECTOR HERE
	LHLD	DPHADD	;GET BACK DPH ADDRESS
	LXI	D,10		;INDEX INTO DPB VECTOR
	DAD	D		;HL NOW HAS DPB VECTOR
	MOV	A,M		;GET LOW BYTE
	INX	H
	MOV	H,M		;GET UPPER BYTE
	MOV	L,A		
	LXI	D,DPB1	;MAKE LOCAL DPB1 THE DESTINATION
	MVI	C,15		;15 BYTES TO MOVE
	CALL	BMOVE		;COPY DPB INTO LOCAL RAM
	RET


;********************************************************
;      DISPLAY PROGRAM OPTIONS & GET USER RESPONCE
;********************************************************

GETOPT:
	LXI	SP,STACK	;RESET FOR MULTIPLE ACTIONS
	MVI	A,1
	STA	REMFLG	;RESET REMOVAL FLAG
	LXI	D,MESS2	;PRINT USER OPTION MESSAGE
	MVI	C,PRINTS
	CALL	BDOS
	LXI	D,INBUFF
	MVI	C,GETBUF
	CALL	BDOS


	.IFE	ROMER,[

	LXI	H,0E000H	;1800H BYTES BELOW MONITOR
	LXI	D,600H	;1/4 OF 1800H
	DAD	D		;NOW MAKE IT 0F800H BY ADDING
	DAD	D
	DAD	D
	DAD	D
	LXI	B,0F30BH	;B HAS FIRST BYTE OF MONITOR, C HAS
				;MONITOR PRONM 'ON' PORT	
	OUTP	A		;TURN IT ON
	MOV	A,M		;GET FIRST BYTE OF MONITOR
	CMP	B		;SEE IF SAME AS B
	JZ	ROMOFF	;IF SO SHUT OFF MONITOR
	HLT			;ELSE QUIT
ROMOFF:
	DCX	B		;MAKE MONITOR 'OFF' PORT
	OUTP	A		;TURN IT OFF
	]

	LDA	INBUFF+1	;GET # OF KEYS PRESSED
	CPI	1		;SEE IF OPTION 1 TO 9
	JZ	NINER
	LDA	INBUFF+3
	SUI	'0'
	ADI	10
	CPI	12
	JNC	GETOPT
	MOV	C,A
	MVI	A,1
	STA	LSTER		;CANCEL PRINTER OUTPUT
	MOV	A,C
	DCR	A
	JMP	ADJUST

NINER:
	LDA	INBUFF+2	;GET 1 TO 9
	CPI	'1'		;TEST FOR VALID ANSWER
	JC	GETOPT
	CPI	':'
	JNC	GETOPT
	CPI	'9'
	JZ	NOFLG
	CPI	'7'
	JNZ	GETECH
NOFLG:
	MVI	A,1
	JMP	DOFLG
GETECH:
	LXI	D,MESS3	;ASK IF THEY WANT TO ECHO ON PRINTER
	MVI	C,PRINTS
	CALL	BDOS
	MVI	C,GETCON
	CALL	BDOS
	STA	ANS1
	CALL	CRLF
	LDA	ANS1
	CPI	'Y'
	JNZ	NOTY
	XRA	A
DOFLG:
	STA	LSTER		;SET PRINTER ECHO FLAG
	JMP	DOFCN

NOTY:
	MVI	A,1
	STA	LSTER
	

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                    PROCESS REQUEST
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DOFCN:
	LDA	INBUFF+2	;GET KEY TYPED
	SUI	'1'		;GET INDEX VALUE
ADJUST:	
	ADD	A		;*2
	LXI	H,OPTTAB	;OPTION TABLE
	MVI	D,0
	MOV	E,A
	DAD	D
	MOV	A,M		;GET LOWER ADDRESS BYTE
	INX	H
	MOV	H,M		;GET UPPER ADDRESS BYTE
	MOV	L,A		;GET LOWER INTO L
	PCHL			;DO IT
	
OPTTAB:
	.WORD	DMPSRN		;DUMP DIRECTORY ON SCREEN
	.WORD	DISP		;DISPLAY ALL INVALID ENTRIES
	.WORD	RENAM		;RENAME INVALID ENTRIES
	.WORD	REMOV		;REMOVE INVALID ENTRIES
	.WORD	SURFAC		;TEST ENTIRE DISK SURFACE
	.WORD	BLOCK		;REMOVE BAD BLOCKS
	.WORD	START		;START OVER
	.WORD	RDSYS		;READ SYSTEM TRACKS
	.WORD	UNERA		;UNERASE ALL FILES
	.WORD	COPY		;COPY DISKS
	.WORD	DUMPT		;DUMP TRACKS
	.WORD	EMPTY

EMPTY:
	JMP	START


;********************************************************
;       DUMP THE DIRECTORY ON THE SYSTEM DISPLAY
;********************************************************

DMPSRN:
	CALL	DIRNIT	;SET UP INITIAL PARAMETERS
	LXI	B,DIRBUF	;READ INTO DIRECTORY BUFFER
	CALL	SETDMA
DMP0:	
	CALL	READ		;READ THE SECTOR
	CALL	DUMP		;SHOW ON SCREEN
	CALL	UPDATE	;POINT TO NEXT POSSIBLE READ
	JZ	PRMPT		;IF DONE NOW
	JMP	DMP0


;********************************************************
;           READ A SECTOR FROM A GIVEN TRACK
;********************************************************

READ:
	LHLD	CURTRK	;GET CURRENT TRACK
	PUSH	H
	POP	B
	CALL	SETTRK	;SET IT IN BIOS
	LHLD	CURSEC	;GET CURRENT SECTOR #
	PUSH	H
	POP	B
	LHLD	XLATE		;PICK UP TRANSLATE VECTOR
	PUSH	H
	POP	D		;GET XLATE TABLE INTO DE
	CALL	SECTRN		;GET BIOS SECTOR VALUE
	MOV	B,H		;MAKE IT SELECTABLE
	MOV	C,L
	CALL	SETSEC		;NOW SET TRANSLATED SECTOR
	CALL	SECRD		;READ ONE SECTOR
	RET


;********************************************************
;   POINT TO NEXT SECTOR & TRACK OR SHOW ALL DONE
;********************************************************

UPDATE:
	LDA	CURSEC	;GET CURRENT SECTOR
	INR	A		;UPDATE IT
	STA	CURSEC
	MOV	C,A		;SAVE IN C
	LDA	SPT		;GET MAX SECTORS PER TRACK
	CMP	C		;TEST WITH UPDATE
	JNZ	SECEND
	XRA	A
	STA	CURSEC	;ZERO SECTOR FOR NEXT TRACK TO READ
	LHLD	CURTRK	;AND GET CURRENT TRACK
	INX	H		;MAKE NEXT
	SHLD	CURTRK	;SAVE IT
SECEND:
	LHLD	NUMSEC	;GET SECTORS TO READ
	DCX	H		;UPDATE THEM
	SHLD	NUMSEC
	MOV	A,H		;SEE IF LAST SECTOR READ
	ORA	L
	RET			;SHOW WHEN DONE


;********************************************************
;               DUMP TRACK ON SCREEN
;********************************************************

FRSTS:	.WORD	1
HDFLG:	.BYTE	1
DMPSRC:	.BYTE	0

DUMPT:
	MVI	A,1		;SET DUMP SECTOR TO SCREEN FLAG
	STA	DMPSRC
	CALL	DIRNIT	;INIT DRIVE DPH AND DPB
	CALL	GETREC	;GET MAXIMUM RECORDS

TELDMP:
	LXI	D,MESS17	;TELL USER TO ENTER STARTING TRACK #	
	MVI	C,PRINTS
	CALL	BDOS
	CALL	LDHL		;GET TWO HEX BYTES IN HL FOR STARTING TRACK
	SHLD	CURTRK	;SAVE IT AS CURRENT TRACK


	LXI	H,DIRBUF	;SET DIRBUF AS DMA FOR DUMP
	SHLD	CURDMA
	PUSH	H
	POP	B
	CALL	SETDMA
	LHLD	CURTRK	;SEE WHICH STARTING TRACK WE HAVE
	MOV	A,H		;SEE IF READLY HIGH
	CPI	0
	JNZ	DUMPT1	;IF SO GO DO MAJOR DUMP
	MOV	C,L		;SAVE IN C
	LDA	OFF		;GET OFFSET TRACK
	CMP	C		;SEE IF SYSTEM TRACK
	JC	DUMPT1	;IF NOT DO MAJOR DUMP
	CALL	RDSYS1	;ELSE READ SYSTEM TRACKS

	LDA	OFF		;GET OFFSET
	MOV	L,A
	MVI	H,0		;MAKE IT NEXT TRACK
	SHLD	CURTRK
	MVI	A,0		;SET NEXT SECTOR
	STA	CURSEC

DUMPT1:

;		COMPUTE REMAINIG RECORDS TO DO READS

	LHLD	CURTRK	;GET OUR TRACK
	MOV	A,H		;TEST IF OUR TRACK = OFF TRACK
	CPI	0
	JNZ	ITSUP		;MUST BE QUITE HIGH
	MOV	C,L
	LDA	OFF
	CMP	C
	JZ	DUMPT2	;MAX RECS ARE O.K.
ITSUP:
	LDA	OFF		;GET OFF TRACKS
	
DOOFF:
	DCX	H		;REMOVE SYSTEM TRACKS
	DCR	A
	JNZ	DOOFF
	LXI	D,0		;DE WILL HOLD RECORDS WHEN DONE
	
RCLOP:
	LDA	SPT
	MOV	B,A
RCLOP1:
	INX	D		;UPDATE RECORDS
	DCR	B		;UPDATE SPT
	JNZ	RCLOP1			
	DCX	H		;UPDATE TRACKS
	MOV	A,H
	ORA	L
	JNZ	RCLOP

	LHLD	MAXREC	;GET MAX RECORDS
	MOV	A,H
	CMP	D
	JC	DUMPT		;TOO BIG
	JNZ	SIZOK
	MOV	A,L
	CMP	E
	JC	DUMPT		;TOO BIG
SIZOK:
	MOV	A,L
	SUB	E
	MOV	L,A
	MOV	A,H
	SBB	D
	MOV	H,A
	SHLD	CURREC

	MVI	A,0
	STA	CURSEC
	
DUMPT2:
	CALL	READ
	CALL	DUMP
	LHLD	CURREC
	DCX	H
	SHLD	CURREC
	MOV	A,H
	ORA	L
	JZ	PRMPTF
	LDA	CURSEC
	INR	A
	STA	CURSEC
	MOV	C,A
	LDA	SPT
	CMP	C
	JNZ	DUMPT2
	LHLD	CURTRK
	INX	H
	SHLD	CURTRK
	MVI	A,0
	STA	CURSEC		
	JMP	DUMPT2

PRMPTF:
	XRA	A
	STA	DMPSRC
	JMP	PRMPT


;*****************************************************
;*      GET TWO BYTES OF HEX DATA FROM K.B.
;*        & RETURN WITH THEM IN HL REGS
;*****************************************************

LDHL:
	CALL 	HEXIN	;GET K.B. AND MAKE HEX
     	MOV  	H,A	;THATS THE HI BYTE
	CALL 	HEXIN	;DO HEX AGAIN
      MOV  	L,A	;THATS THE LOW BYTE
      RET		;GO BACK WITH ADDRESS  


;*****************************************************
;*        GET K.B. DATA & MAKE IT 'HEX'
;*****************************************************

HEXIN:
        CALL 	NIBL	;DO A NIBBLE
        RLC		;MOVE FIRST BYTE UPPER NIBBLE  
        RLC  
        RLC  
        RLC  
        MOV  B,A	;SAVE ROTATED BYTE
        CALL NIBL	;DO NEXT NIBBLE
        ADD  B	;COMBINE NIBBLES IN ACC.
        RET		;DONE  

NIBL:   
	CALL 	KIN	;GET K.B. DATA
      CPI   40H	;TEST FOR ALPHA
	JRNC	ALPH
	ANI	0FH	;GET THE BITS
	RET
ALPH:
	ANI	0FH
	ADI	09H	;MAKE IT HEX A-F
	RET

KIN:
	PUSH	H
	PUSH	B
	MVI	C,GETCON
	CALL	BDOS
	POP	B
	POP	H
	RET
		


;********************************************************
;               COPY FROM DISK TO DISK
;********************************************************

COPY:
	LXI	D,MESS13	;ASK FOR SOURCE DRIVE
	MVI	C,PRINTS
	CALL	BDOS
	CALL	GETDRV
	STA	DRVONE
	LXI	D,MESS14	;ASK FOR DESTINATION DRIVE
	MVI	C,PRINTS
	CALL	BDOS
	CALL	GETDRV
	STA	DRVTWO

	LDA	DRVONE	;GET DPH ETC. FOR DRIVE ONE
	CALL	GETPRM
	LHLD	XLATE
	SHLD	XLATE1
	LXI	H,DPB1	;DPB WAS PUT HERE
	LXI	D,DPB2	;PUT IT HERE	
	MVI	C,15
	CALL	BMOVE

	LDA	DRVTWO	;GET SAME FOR DRIVE TWO
	CALL	GETPRM
	LHLD	XLATE
	SHLD	XLATE2
	LXI	H,DPB1
	LXI	D,DPB3
	MVI	C,15
	CALL	BMOVE

	LXI	H,DPB2	;TEST DPBS FOR COMPATABILITY
	LXI	D,DPB3
	MVI	C,15
DPHCMP:
	LDAX	D
	CMP	M
	JNZ	DRVDIF	;IF DRIVES ARE NOT SAME	
	INX	H
	INX	D
	DCR	C
	JNZ	DPHCMP

COPY1:
	CALL	DIRNIT	;INITIALIZE RECORDS TO COPY
	LHLD	OFF		;GET OFFSET
	SHLD	CURTRK	;SET FIRST TRACK
	CALL	GETREC	;COMPUTE MAX RECORDS
	LHLD	MAXREC
	SHLD	CURREC
	LXI	H,0
	SHLD	CURSEC
	LXI	D,MESS8
	MVI	C,PRINTS
	CALL	BDOS

COPY3:

	MVI	A,CR
	CALL	COUT
	LHLD	CURTRK
	CALL	PHLD

	MVI	A,3
	STA	RETRY

COPY30:
	LXI	H,COPBF
	SHLD	CURDMA
	PUSH	H
	POP	B
	CALL	SETDMA
	LDA	DRVONE
	MOV	C,A
	MVI	E,1
	CALL	SELDSK

;	READ A FULL TRACK NEXT

COPY4:
	CALL	READ
	LHLD	CURDMA
	LXI	D,128
	DAD	D
	SHLD	CURDMA
	PUSH	H
	POP	B
	CALL	SETDMA
	LDA	CURSEC
	INR	A
	STA	CURSEC
	MOV	C,A
	LDA	SPT
	CMP	C
	JNZ	COPY4
	XRA	A
	STA	CURSEC

;	WRITE A FULL TRACK NEXT

COPY5:
	LDA	DRVTWO
	MOV	C,A
	MVI	E,1
	CALL	SELDSK
	LXI	H,COPBF
	SHLD	CURDMA
	PUSH	H
	POP	B
	CALL	SETDMA

COPY6:
	CALL	WRITE0
	LHLD	CURDMA
	LXI	D,128
	DAD	D
	SHLD	CURDMA
	PUSH	H
	POP	B
	CALL	SETDMA

	LDA	CURSEC
	INR	A
	STA	CURSEC
	MOV	C,A
	LDA	SPT
	CMP	C
	JNZ	COPY6
	XRA	A
	STA	CURSEC

COPY7:
	LXI	H,COPBF1
	SHLD	CURDMA
	PUSH	H
	POP	B
	CALL	SETDMA

;	READ THE TRACK JUST WRITTEN AN VERIFY ITS' DATA

COPY8:
	CALL	READ
	LHLD	CURDMA
	LXI	D,128
	DAD	D
	SHLD	CURDMA
	PUSH	H
	POP	B
	CALL	SETDMA
	LHLD	CURREC
	DCX	H
	SHLD	CURREC
	MOV	A,H
	ORA	L
	JZ	COPY9
	LDA	CURSEC
	INR	A
	STA	CURSEC
	MOV	C,A
	LDA	SPT
	CMP	C
	JNZ	COPY8

	LXI	H,COPBF
	LXI	D,COPBF1
	LDA	SPT
	MOV	C,A
VLOP:
	MVI	B,128

VLOP0:
	LDAX	D		;GET DATA READ FROM DESTINATION
	CMP	M		;TEST WITH DATA WRITTEN
	JNZ	OHOH
	INX	H
	INX	D
	DCR	B		;UPDATE BYTES PER RECORD
	JNZ	VLOP0
	DCR	C		;LAST SECTOR DONE
	JNZ	VLOP		;IF NOT COMPARE NEXT

	XRA	A
	STA	CURSEC
	LHLD	CURTRK
	INX	H
	SHLD	CURTRK
	JMP	COPY3
		
OHOH:
	LDA	RETRY
	DCR	A
	STA	RETRY
	JNZ	COPY30

	LXI	D,MESS16
	MVI	C,PRINTS
	CALL	BDOS
	JMP	PRMPT


DRVDIF:
	LXI	D,MESS15
	MVI	C,PRINTS
	CALL	BDOS

COPY9:
	JMP	PRMPT

RETRY:	.BLKB	1


;********************************************************
;            UNERASE ALL DIRECTORY ENTRIES
;********************************************************

UNERA:
	MVI	C,PRINTS
	LXI	D,UMESS
	CALL	BDOS
	CALL	DIRNIT
	LXI	B,DIRBUF
	CALL	SETDMA
	
UNERLP:
	CALL	READ
	CALL	RECOV
	CALL	UPDATE
	JZ	PRMPT
	JMP	UNERLP

RECOV:
	MVI	A,4		;4 DIRECTORY ENTRIES PER SECTOR
	STA	RECCNT
	LXI	H,DIRBUF	;READ INTO HERE	
	SHLD	DIRPTR
REVLOP:
	LHLD	DIRPTR
	MOV	A,M
	CPI	0E5H
	JNZ	NOMAT
	INX	H		;TEST NEXT BYTE
	MOV	A,M
	CPI	0E5H		;SEE IF UNINITIALIZED AREA
	JZ	NOMAT		;IF SO SKIP IT
	DCX	H		;GET BACK TO ERASE BYTE
	MVI	A,0		;SET UP FOR NORMAL ENTRY
	MOV	M,A		;UNERASE IT

NOMAT:
	LHLD	DIRPTR	;UPDATE DIRECTORY POINTER
	LXI	D,32
	DAD	D
	SHLD	DIRPTR
	LDA	RECCNT	;UPDATE DIRECTORY ENTRY
	DCR	A
	STA	RECCNT
	JZ	FIXOO
	JMP	REVLOP
FIXOO:
	CALL	WRITE0	;WRITE OUT 4 ENTRIES
	RET


UMESS:
	.BYTE	CLEAR
	.ASCII	\Will recover all erased files. Make a backup as soon as possible$\



;********************************************************
;         DISPLAY ALL INVALID DIRECTORY ENTRIES
;********************************************************

DISP:
	CALL	DIRNIT	;GET INITIAL POINTERS
DIRLP:
	CALL	READ		;GET A SECTOR
	CALL	CHECK
	CALL	UPDATE
	JZ	PRMPT
	JMP	DIRLP

CHECK:
	MVI	A,4
	STA	RECCNT
	LXI	H,DIRBUF
	SHLD	DIRPTR
DIRLP0:
	LHLD	DIRPTR	;SAVE DIRECTORY POINTER
	MOV	A,M		;GET FIRST BYTE
	CPI	0E5H		;SEE IF ERASED
	SHLD	DIRPTR
	CNZ	TSTNAM	;IF NOT ERASED CHECK FOR VALID NAME
	LHLD	DIRNUM	;UPDATE DIRECTORY COUNTER
	INX	H
	SHLD	DIRNUM
	LHLD	DIRPTR
	LXI	B,32		
	DAD	B		;GET NEXT LOCATION
	SHLD	DIRPTR
	LHLD	DIRLEN	;GET DIRCTORY SIZE
	DCX	H		;COUNT DOWN ENTRIES
	SHLD	DIRLEN
	MOV	A,H
	ORA	L
	JZ	PRMPT		;DO NEXT NAME IF MORE
	LDA	RECCNT
	DCR	A
	STA	RECCNT
	JNZ	DIRLP0
	RET


;	TEST IF HL POINTS TO A VALID DIRECTORY ENTRY
;	HL ENTERS WITH LOCATION OF DIRECTORY ENTRY

TSTNAM:
	LXI	D,TESTBF	;MOVE NAME TO A SAFE LOCATION
	MVI	C,12
	CALL	BMOVE
	CALL	VIOLAT	;TEST FOR BAD ALLOCATION

	LXI	H,TESTBF	;POINT TO NAME TO TEST	
	INX	H		;START OF NAME
	MVI	D,11		;11 VALID BYTES
NAMLP:
	MOV	A,M	;GET NAME BYTE
TSTCHR:
	CPI	'0'		;FIRST RANGE TEST
	JC	NOTFAR
	INX	H
	DCR	D
	JNZ	NAMLP
	RET
NOTFAR:
	LXI	H,TESTBF
	CALL	SCANIT	;TEST FOR BAD SPACE FORM IN NAME
	LDA	VILFLG
	MOV	C,A
	LDA	SPCERR
	ORA	C
	RZ			;IF ZERO SET IT WAS GOOD
	CALL	VRYBAD
	XRA	A
	CPI	2
	RET


SCANIT:
;	CHECK THE FILE NAME FOR BAD CHARACTER FORM
	
	PUSH	H
	XRA	A
	STA	SCNFLG	;SHOW WE HAVE A SPACE
	STA	SPCERR	;SET SPACE ERROR FLAGE O.K.
	LXI	B,8
	DAD	B		;START AT END OF PRIMARY NAME
	MVI	B,8		;8 BYTES TO TEST


;	FIRST TEST PRIMARY NAME

SCNLP0:
	MOV	A,M
	ANI	7FH
	CPI	' '
	JC	..FLGB	;TOTALLY UNACCEPTABLE BYTE
	JNZ	NOSPC
	LDA	SCNFLG	;SEE IF WE HAD A SPACE
	ORA	A
	JZ	NXTSP		;NO SPACE VIOLATION
..FLGB:
	MVI	A,':'		;FLAG A BAD CHARACTER
	MOV	M,A
	STA	SPCERR
NOSPC:
	MVI	A,1
	STA	SCNFLG	;SHOW NO MORE SPACES ALLOWED
NXTSP:
	DCX	H
	DCR	B
	JNZ	SCNLP0	;FINISH PRIMARY NAME

;	NOW TEST NAME EXTENSION

	MVI	A,0		;SHOW A SPACE FOUND
	STA	SCNFLG
	POP	H		;RECOVER NAME POINTER
	LXI	B,11
	DAD	B		;MAKE END OF NAME
	MVI	B,3		;3 BYTES TO TEST

SCNLP1:
	MOV	A,M
	ANI	7FH
	CPI	' '
	JC	..FLGB	;TOTALLY UNACCEPTABLE
	JNZ	NOSPC0
	LDA	SCNFLG
	ORA	A
	JZ	NXTSP0
..FLGB:
	MVI	A,':'
	MOV	M,A
	STA	SPCERR
NOSPC0:
	MVI	A,1		;WE HAVE A NON-SPACE CHARACTER
	STA	SCNFLG	;SO SET THE FLAG
NXTSP0:
	DCX	H	;POINT NEXT
	DCR	B
	JNZ	SCNLP1
	LDA	SPCERR	;SHOW CALLING PROGRAM IF SPACE VIOLATED
	ORA	A
	RET
			


VRYBAD:
	LXI	H,BDAT
	CALL	MSG
	CALL	CRLF

	LXI	H,TESTBF	;GET NAME POINTER
	INX	H
	MVI	B,11

;	NOW PRINT NAME ON SCREEN

SHOW:
	MOV	A,B		;GET CHARACTER COUNTER
	CPI	3		;SEE IF START OF EXTENSION
	CZ	PERD		;IF SO PERIODE IT
	MOV	A,M
	ANI	7FH
	CPI	' '
	JNC	COUT1
	MVI	A,':'
COUT1:	CALL	COUT
	INX	H
	DCR	B
	JNZ	SHOW
	LHLD	DIRPTR	;GET DIRECTORY POINTER
	CALL	FDAT0		;SHOW FILE DATA
	LDA	VILFLG	;SEE IF DISK SIZE VIOLATION
	ORA	A
	JZ	NOVILR
	LXI	H,SIZVIL	;IF SO PRINT VIOLATION MESSAGE	
	CALL	MSG
NOVILR:
	CALL	CRLF
	CALL	CRLF
	RET





;********************************************************
;   SET INITIAL POINTERS & VALUES FOR DISRECTORY SCAN
;********************************************************

DIRNIT:
	LHLD	DRM		;GET # OF DIRECTORY ENTRIES
	INX	H		;MAKE ACTUAL
	SHLD	DIRLEN
	LXI	B,0		;SECTOR COUNTER

;	     COMPUTE TOTAL SECTORS IN DIRECTORY

ENTRY:
	DCX	H		;4 ENTRIES PER SECTOR
	DCX	H
	DCX	H
	DCX	H
	INX	B		;UPDATE SECTOR COUNTER
	MOV	A,H		;TEST IF ALL ENTRIES DONE
	ORA	L
	JNZ	ENTRY
	MOV	A,C		;GET LOW SECTOR COUNT
	STA	NUMSEC	;SAVE LOW BYTE SECTORS TO READ
	MOV	A,B		;GET HIGH SECTOR COUNT
	STA	NUMSEC+1	;SAVE HIGH BYTE S.T.R.
	LHLD	NUMSEC
	SHLD	DIRENT	;SAVE AS RECORDS IN DIRECTORY
	LXI	H,0
	SHLD	DIRNUM	;INITIAL DIRECTORY RECORD
	SHLD	CURSEC	;INITIAL SECTOR
	LHLD	OFF		;DIRECTORY TRACK
	SHLD	CURTRK
	RET



;********************************************************
;       SEE IF DIRECTORY ENTRY VIOLATES DISK SIZE
;********************************************************

VIOLAT:
	XRA	A
	STA	VILFLG	;SHOW NO VIOLATION YET
	MVI	B,8		;CHECK 8 ENTRIES

	LHLD	DSM		;GET BLOCKS IN DISK
	PUSH	H		;SAVE DISK SIZE
	
	LHLD	DIRPTR	;GET FILE POINTER
	LXI	D,31		;GET BLOCK MAP END
	DAD	D		;HL PONTS TO END OF ALLOCATION MAP
	POP	D		;GET DISK SIZE INTO DE


;	FIRST TEST IF ALLOCATION MAP RUNS OFF THE DISK

VIOLOP:
	MOV	A,M		;GET HIGH BYTE ENTRY
	CMP	D		;COMPARE WITH DISK SIZE HIGH
	JC	OK		;IF SMALLER THEN O.K.
	JNZ	BADSIZ	;IF NOT ZERO THEN TOO BIG

;	HIGH BYTE IS SAME SO TEST IF LOW BYTE MUST BE SAME OR LESS
	
	DCX	H		;POINT TO DIRECTORY LOW BYTE
	MOV	A,M		;GET LOW BYTE
	CMP	E		;COMPARE WITH DSM LOW BYTE
	JC	OK1		;IF SMALLER O.K.
	JZ	OK1		;IF SAME SIZE THEN O.K.

BADSIZ:
	MVI	A,1
	STA	VILFLG	;SHOW SIZE VIOLATION
	RET

OK:
	DCX	H		;RESET FOR ENTIRE FIELD

OK1:
	DCX	H		;POINT NEXT MAP AREA
	DCR	B		;UPDATE FIELD COUNTER
	RZ			;IF AT END
	JMP	VIOLOP	;TRY NEXT

	
;	PRINT A PERIODE

PERD:
	MVI	A,'.'
	CALL	COUT
	RET
					

;********************************************************
;      RENAME ALL INVALID DIRECTORY ENTRIES
;********************************************************

RENAM:
	CALL	DIRNIT		;SET INITIAL VALUES
	MVI	A,'A'			;SETUP NAME VARIABLES
	STA	BADFNM
	STA	BADFNM+1
	LXI	D,MESS4		;TELL USER OPTIONS HERE
	MVI	C,PRINTS
	CALL	BDOS
	LXI	D,INBUFF
	MVI	C,GETBUF		;GET SEED NAME FOR FILE	
	CALL	BDOS
	LXI	H,INBUFF+1		;GET CHARACTERS ENTERED
	MOV	A,M
	CPI	5
	JZ	FINE
	JMP	RENAM
FINE:
	CALL	CRLF
	CALL	CRLF
	MVI	C,DSKRST		;RESET DISK SYSTEM
	CALL	BDOS
	LDA	TEST			;GET DISK FOR TEST
	MVI	C,SLDISK		;HAVE BDOS LOG IT ON
	MOV	E,A
	CALL	BDOS
	CALL	CLEARF		;CLEAR FCB
	LXI	H,INBUFF+2		;GET SEED NAME LOCATION
	MVI	C,5
	LXI	D,FCB3+1		;POINT TO NAME AREA IN FCB
	CALL	BMOVE			;MOVE IT IN
	LXI	H,HUH			;POINT TO ANY NAME
	MVI	C,6
	CALL	BMOVE
	CALL	DMATCH		;SEE IF A MATCH
	JNZ	RENAM			;IF FILE IS DUPLICATED

RENAM0:
	LXI	SP,STACK
	LXI	B,DIRBUF
	CALL	SETDMA
	CALL	READ			;READ A SECTOR
	CALL	RCHECK		;SEE IF ANY BAD ENTRIES
	CALL	UPDATE		;POINT TO NEXT SECTOR
	JZ	EPRMPT		;IF ALL DONE
	JMP	RENAM0


;	CHECK THE DIRECTORY ENTRIES IN CURRENT SECTOR FOR VALID FILES

RCHECK:
	MVI	A,4
	STA	RECCNT
	LXI	H,DIRBUF
	SHLD	DIRPTR
RCHKLP:
	LHLD	DIRPTR
	MOV	A,M
	CPI	0E5H
	CNZ	TSTNAM
	LDA	VILFLG		;GET SIZE VIOLATION FLAG
	ORA	A			;SEE IF OFF DISK
	JZ	..NOVL		;WE CAN HANDLE IT ALWAYS
	CALL	KILL			;WE MIGHT BE REMOVING
	JMP	..DRUP		;IF NOT KILLED WE CAN'T HANDLE NOW
..NOVL:
	LDA	SPCERR	;SEE IF FILE NAME WAS BAD
	ORA	A
	CNZ	RENAM1		;IF FILE NAME BAD RENAME IT
..DRUP:
	LHLD	DIRNUM		;UPDATE DIRECTORY ENTRY
	INX	H
	SHLD	DIRNUM
	LHLD	DIRPTR
	LXI	B,32
	DAD	B
	SHLD	DIRPTR
	LHLD	DIRLEN
	DCX	H
	SHLD	DIRLEN
	MOV	A,H
	ORA	L
	JZ	PRMPT
	LDA	RECCNT
	DCR	A
	STA	RECCNT
	JNZ	RCHKLP
	RET



RENAM1:
	LDA	REMFLG	;SEE IF WE ARE REMOVING
	ORA	A
	JZ	KILL		;JUST GET RID OF ENTRY

	CALL	CLEARF	;CLEAR FCB
	LHLD	DIRPTR	;GET FILE LOCATION
	MOV	A,M		;GETUSER NUMBER
	ANI	0FH

	MVI	C,SETUSR	;SET TO THIS USER
	MOV	E,A
	CALL	BDOS
	LHLD	DIRPTR	;POINT BACK TO FILE
	INX	H		;POINT TO NAME FIELD
	LXI	D,FCB3+1	;MOVE TO HERE
	MVI	C,8
	CALL	BMOVE
	MVI	C,3		;READY TO GET EXTENSION
	CALL	BMOVES	;STRIP BIT 7 LOW IN EXTENSION
	MVI	C,SETATT	;SET ATTRIBUTES AS STANDARD		
	LXI	D,FCB3
	CALL	BDOS
	INR	A
	JZ	ATTFAL
	CALL	CLEARU		;CLEAR UPPER SEGMENT OF FCB

;	NOW MOVE IN NEW NAME

	LXI	D,FCB3+17	;POINT TO RENAME FIELD
	LXI	H,INBUFF+2	;POINT TO SEED NAME
	MVI	C,5
	CALL	BMOVE		;MOVE RENAME CHARACTERS IN
	PUSH	D		;SAVE DESTINATION
	CALL	GETTWO	;GET TWO NEW CHARACTERS
	MOV	A,H
	STA	NAMCNT
	MOV	A,L
	STA	NAMCNT+1
	POP	D		;RECOVER DESTINATION
	LXI	H,NAMCNT
	MVI	C,3
	CALL	BMOVE		;MOVE IN SEED NAME UPDATE

	LXI	H,EXTENS	;POINT TO EXTENSION
	MVI	C,3
	CALL	BMOVE

	LXI	H,FCB3+17	;SHOW RENAME ON SCREEN
	MVI	C,11
..MOV:
	MOV	A,M
	CALL	COUT
	INX	H
	DCR	C
	JNZ	..MOV
	CALL	CRLF

	LXI	D,READBF
	MVI	C,DMAF
	CALL	BDOS

	MVI	C,RENAME	;RENAME THIS FILE
	LXI	D,FCB3
	CALL	BDOS
	INR	A
	JNZ	USRZR0

	MVI	C,SETUSR
	MVI	E,0
	CALL	BDOS
	JMP	RENFAL
USRZR0:
	LXI	B,0
	CALL	SETTRK
	LXI	B,1
	CALL	SETSEC
	LXI	B,80H
	CALL	SETDMA
	CALL	SECRD

	MVI	E,0
	MVI	C,SETUSR
	CALL	BDOS
	RET

EPRMPT:
	MVI	C,DSKRST
	CALL	BDOS
	MVI	E,0
	MVI	C,SETUSR
	CALL	BDOS
	JMP	PRMPT


;********************************************************
;   ERASE THE HOPELESS FILES FROM DISK DIRECTORY
;********************************************************

REMOV:
	CALL	DIRNIT
	XRA	A
	STA	REMFLG	;SHOW WE ARE REMOVING 'FILES'
	JMP	RENAM0

KILL:
	LDA	REMFLG
	ORA	A
	RNZ
	LHLD	DIRPTR
	MVI	A,0E5H
	MOV	M,A
	LXI	H,DIRBUF
	PUSH	H
	POP	B
	CALL	SETDMA
	MVI	C,1
	CALL	SECWRT
	RET
	

;********************************************************
;         SET UP ADDRESSES FOR DIRECT BIOS ENTRY 
;         TO PRODUCE A LOCAL JUMP TABLE ACCESSED
;              VIA A CALL TO PCHL ROUTINE
;********************************************************

BVECT:

	LHLD	1		;GET BIOS POINTER
	MOV	A,M		;GET FIRST JUMP
	CPI	0C3H		;SEE IF IT IS A 'JMP'
	JNZ	START		;SOMETHING'S WRONG
	LXI	D,3
	DAD	D
	SHLD	BCONST	;BIOS CONSOLE STATUS
	DAD	D
	SHLD	BCONIN	;BIOS CONSOLE INPUT
	DAD	D
	SHLD	BCONOT	;BIOS CONSOLE OUTPUT

	LHLD	1		;GET BACK BIOS VECTOR FOR DISK I/O
	LXI	D,21		;SET FIRST OFFSET
	DAD	D		;SET HOME VALUE
	SHLD	BHOME		;BIOS HOME DISK
	LXI	D,3
	DAD	D
	SHLD	BSEL		;BIOS SELECT DISK
	DAD	D
	SHLD	BTRACK	;BIOS SET TRACK
	DAD	D
	SHLD	BSEC		;BIOS SET SECTOR
	DAD	D
	SHLD	BDMA		;BIOS SET DMA
	DAD	D
	SHLD	BREAD		;BIOS SECTOR READ
	DAD	D
	SHLD	BWRITE	;BIOS SECTOR WRITE
	DAD	D
	DAD	D
	SHLD	BSTRAN	;BIOS SECTOR TRANSLATE
	RET


;********************************************************
;            MEMORY DATA BLOCK MOVE ROUTINE
;   HL IS SOURCE POINTER, DE HAS DESTINATION POINTER
;	     C HAS NUMBER OF BYTES TO MOVE
;********************************************************

BMOVE:
MLOP:
	MOV	A,M
	STAX	D
	INX	D
	INX	H
	DCR	C
	JNZ	MLOP
	RET

BMOVES:
	MOV	A,M
	ANI	7FH
	STAX	D
	INX	H
	INX	D
	DCR	C
	JNZ	BMOVES
	RET

;********************************************************
;            TEST ENTIRE DISK SURFACE NEXT
;********************************************************

SURFAC:
	LXI	H,WRITBF	;ZERO FILL WRITE BUFFER	
	MVI	C,128
	MVI	A,0E5H
FILWRT:
	MOV	M,A
	INX	H
	DCR	C
	JNZ	FILWRT

	LDA	TEST		;GET DRIVE TO TEST
	ORA	A
	JZ	NOSYS		;DON'T USE SYSTEM DRIVE

	LXI	D,MESS7	;WARN USER ABOUT DISK WRITES
	MVI	C,PRINTS
	CALL	BDOS
	MVI	C,GETCON	;GET ANSWER	
	CALL	BDOS
	CPI	'Y'
	JNZ	START
	CALL	GETREC	;SET UP DISK SIZE

;	NOW PREPARE TO WRITE DATA ON DISK

	LHLD	MAXREC
	SHLD	CURREC
	LXI	H,0
	SHLD	CURSEC
	LXI	D,MESS8
	MVI	C,PRINTS
	CALL	BDOS
	LHLD	OFF
	SHLD	CURTRK
	MVI	A,CR
	CALL	COUT
	LHLD	CURTRK
	CALL	PHLD
	LXI	B,WRITBF
	CALL	SETDMA

;	WRITE TRACK & SECTOR ADDRESS ON SECTOR

WADLOP:
	LHLD	CURTRK
	SHLD	WRITBF
	LDA	CURSEC
	STA	WRITBF+2
	CALL	WRITE0
	LHLD	CURREC
	DCX	H
	SHLD	CURREC
	MOV	A,H
	ORA	L
	JZ	RADCHK
	LDA	CURSEC
	INR	A
	STA	CURSEC
	MOV	C,A
	LDA	SPT
	CMP	C
	JNZ	WADLOP
	XRA	A
	STA	CURSEC
	LHLD	CURTRK
	INX	H
	SHLD	CURTRK
	MVI	A,CR
	CALL	COUT
	LHLD	CURTRK
	CALL	PHLD
	JMP	WADLOP

;	READ BACK & CHECK ALL ADDRESSES NEXT

RADCHK:
	LXI	D,MESS8
	MVI	C,PRINTS
	CALL	BDOS

	LXI	H,0
	SHLD	CURSEC
	LHLD	MAXREC
	SHLD	CURREC
	LHLD	OFF
	SHLD	CURTRK
	MVI	A,CR
	CALL	COUT
	LHLD	CURTRK
	CALL	PHLD
	
	LXI	B,READBF
	CALL	SETDMA

RADLOP:
	CALL	READ		;READ A SECTOR
	LHLD	READBF
	XCHG
	LHLD	CURTRK
	MOV	A,H
	CMP	D
	JNZ	BADADD
	MOV	A,L
	CMP	E
	JNZ	BADADD
	LDA	READBF+2
	MOV	C,A
	LDA	CURSEC
	CMP	C
	JZ	GOODAD
BADADD:
	CALL	PRTBAD
GOODAD:
	LHLD	CURREC
	DCX	H
	SHLD	CURREC
	MOV	A,H
	ORA	L
	JZ	PRMPT

	LDA	CURSEC
	INR	A
	MOV	C,A
	STA	CURSEC
	LDA	SPT
	CMP	C
	JNZ	RADLOP
	
;	MOVE TO NEXT TRACK

	XRA	A
	STA	CURSEC
	LHLD	CURTRK
	INX	H
	SHLD	CURTRK
	MVI	A,CR
	CALL	COUT
	LHLD	CURTRK
	CALL	PHLD
	JMP	RADLOP


;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;       SHOW MISS-MATCH IN SECTOR DATA FOR COMPARE
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

PRTBAD:
	LXI	H,MESS10
	CALL	MSG
	LHLD	CURTRK
	CALL	PHLD
	CALL	FIVSPC
	LDA	CURSEC
	CALL	HXOUT
	CALL	FIVSPC
	LHLD	READBF
	CALL	PHLD
	CALL	FIVSPC
	LDA	READBF+2
	CALL	HXOUT
	MVI	A,CR
	CALL	COUT
	MVI	A,LF
	CALL	COUT
	RET

FIVSPC:
	LXI	H,MESS9
	CALL	MSG
	RET


;********************************************************
;         WRITE TO THE CURRENT SECTOR & TRACK
;********************************************************

WRITE0:
	LHLD	CURTRK
	PUSH	H
	POP	B
	CALL	SETTRK
	LHLD	CURSEC
	PUSH	H
	POP	B
	CALL	SETSEC
	LHLD	XLATE
	PUSH	H
	POP	D
	CALL	SECTRN
	MOV	B,H
	MOV	C,L
	CALL	SETSEC
	MVI	C,2
	CALL	SECWRT
	RET


GETREC:
;	CALCULATE NUMBER OF RECORDS TO TEST
	
	LDA	BSH		;GET BSH FOR DISK
	MOV	C,A		;GET RECORDS PER BLOCK FACTOR INTO C
	LHLD	DSM		;WE HAVE BLOCKS PER DISK IN HL

RECLOP:
	DAD	H		;COMPUTE RECORDS
	DCR	C
	JNZ	RECLOP
	SHLD	MAXREC	;SAVE RECORDS TO TEST
	LDA	BLM		;GET RECORDS PER BLOCK
	INR	A
	STA	RECPB

;		CALCULATE TOTAL DATA TRACKS

	LXI	D,0		;SET DE TO ZERO FOR TOTAL TRACKS
TTLOP:
	LDA	SPT
	MOV	B,A
TTLOP1:
	DCX	H		;COUNT DOWN RECORDS
	MOV	A,H
	ORA	L
	JZ	TTEXIT
	DCR	B		;AGAINST SPT
	JNZ	TTLOP1	;NOT FINISHED A TRACK
	INX	D		;ADD A TRACK
	JMP	TTLOP
TTEXIT:
	PUSH	D
	POP	H
	SHLD	MAXTRK	;SAVE DATA TRACKS
	RET

NOSYS:
	LXI	D,MESS12
	MVI	C,PRINTS
	CALL	BDOS
	JMP	PRMPT

;********************************************************
;                 READ SYSTEM TRACKS
;********************************************************

RDSYS:

;		ENTRY FOR OPTION SELECTION

	LXI	H,0
	SHLD	CURTRK

;	ENTRY FOR OTHER SELECTION

RDSYS1:
	LXI	H,1		;SET AS A FLOPPY FIRST
	SHLD	FRST+1
	SHLD	FRST1+1
	CALL	GETREC	;CALCULATE RECORDS ON DISK
	LHLD	MAXREC	;GET MAXIMUM RECORDS
	MOV	A,H		;NOW TEST HIGH BYTE
	CPI	8		;SEE IF S.S.S.D.
	JC	SSSPT		;IF SO DO NORMAL SECTOR READS
	CPI	40H		;SEE IF 2 MEG. OR UP
	JC	NOTBIG
	LXI	H,0		;IF HARD DISK SET FOR SAME
	SHLD	FRST+1
	SHLD	FRST1+1
	JMP	SSSPT

NOTBIG:
	MVI	A,36		;ELSE READ 36 SECTORS PER SYSTEM TRACK
	STA	SYSSEC
	JMP	RDSYST
SSSPT:
	LDA	SPT
	STA	SYSSEC
RDSYST:
	LXI	D,MESS8
	MVI	C,PRINTS
	CALL	BDOS


FRST:
	LXI	H,1
	SHLD	CURSEC
	MVI	A,CR
	CALL	COUT
	LHLD	CURTRK
	CALL	PHLD
	LXI	B,DIRBUF
	CALL	SETDMA

SYSLOP:
	CALL	SREAD		;TEST FOR SECTOR DUMP
	LDA	DMPSRC
	ORA	A
	JZ	NODMP
	CALL	DUMP

NODMP:
	LDA	CURSEC
	INR	A
	MOV	C,A
	STA	CURSEC
	LDA	SYSSEC
	CMP	C
	JNZ	SYSLOP

;	READ NEXT SYSTEM TRACK

FRST1:
	LXI	H,1
	SHLD	CURSEC
	LHLD	CURTRK
	INX	H
	SHLD	CURTRK
	MOV	A,L
	MOV	C,A
	LDA	OFF
	CMP	C
	JZ	DMPCHK
	MVI	A,CR
	CALL	COUT
	LHLD	CURTRK
	CALL	PHLD
	JMP	SYSLOP

DMPCHK:
	LDA	DMPSRC
	ORA	A
	JZ	PRMPT
	RET


;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;           READ A CP/M RECORD ON A SYSTEM TRACK
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

SREAD:
	LHLD	CURTRK
	PUSH	H
	POP	B
	CALL	SETTRK
	LHLD	CURSEC
	PUSH	H
	POP	B
	CALL	SETSEC
	CALL	SECRD
	RET


;********************************************************
;        ALLOCATE BAD BLOCKS TO A FILE 'JUNKY'
;********************************************************

BLOCK:
;	SET UP STARTING PARAMETERS

	LXI	D,MESS8
	MVI	C,PRINTS
	CALL	BDOS

	
	LHLD	OFF
	SHLD	CURTRK		;FIRST TRACK	
	LXI	H,0
	SHLD	CURSEC		;FIRST SECTOR
	SHLD	BLKNUM		;FIRST BLOCK
	SHLD	RECNUM		;FIRST RECORD
	CALL	GETREC
	LHLD	MAXREC		;GET DISK SIZE
	SHLD	CURREC
	LDA	RECPB			;GET RECORDS/BLOCK
	STA	RPBNUM		;SET RPB COUNTER
	LXI	B,READBF
	CALL	SETDMA

	LHLD	CURTRK
	MVI	A,CR
	CALL	COUT
	LHLD	CURTRK
	CALL	PHLD


;	READ ALL OF DISK SURFACE & FLAG BAD BLOCKS

BLOCK0:
	LXI	SP,STACK
	CALL	READ		;READ A SECTOR
	ORA	A		;TEST IF READ O.K.
	CNZ	SETBAD
	LXI	H,RPBNUM	;POINT TO RECORDS PER BLOCK
	DCR	M		;UPDATE
	JNZ	GETR		;IF STILL SAME BLOCK SKIP NEXT
	LDA	RECPB		;ELSE GET RECORDS PER BLOCK THIS DISK
	STA	RPBNUM	;RESET COUNTER
	LHLD	BLKNUM	;GET ACTUAL BLOCK NUMBER
	INX	H		;AND UPDATE IT
	SHLD	BLKNUM
GETR:
	LHLD	RECNUM	;GET RECORD NUMBER
	INX	H		;UPDATE IT
	SHLD	RECNUM
	LHLD	CURREC	;GET TOTAL RECORDS
	DCX	H		;UPDATE
	SHLD	CURREC
	MOV	A,H		;TEST IF DISK DONE
	ORA	L
	JZ	SEEBAD	;IF DONE CHECK FOR BAD BLOCKS
	LDA	CURSEC	;UPDATE SECTOR
	INR	A
	STA	CURSEC
	MOV	C,A
	LDA	SPT
	CMP	C		;SEE IF LAST SECTOR
	JNZ	BLOCK0

;	SET NEXT TRACK

	XRA	A
	STA	CURSEC
	LHLD	CURTRK	;GET CURRENT TRACK
	INX	H		;UPDATE IT
	SHLD	CURTRK
	MVI	A,CR
	CALL	COUT
	LHLD	CURTRK
	CALL	PHLD
	JMP	BLOCK0
	
SEEBAD:
	LDA	BADNUM	;SEE IF ANY BAD BLOCKS
	ORA	A
	JZ	PRMPT
	XRA	A
	STA	FILCNT	;SAVE FILES CREATED
	
FILOP:
	LXI	SP,STACK

	CALL	DIRNIT
	
	MVI	C,DSKRST	;RESET DISK SYSTEM
	CALL	BDOS	
	MVI	C,SETUSR
	MVI	E,15
	CALL	BDOS		;DO FILES ON USER AREA 15
	LDA	TEST		;GET TEST DISK
	MOV	E,A
	MVI	C,SLDISK
	CALL	BDOS

NAMLOP:
	CALL	CLEARF	;CLEAR OUT FCB
	CALL	GETTWO	;GET UNIQUE TWO CHARACTER STRING
	MOV	A,H		;AND PUT IN FCB PRIMARY NAME
	STA	BADNAM+5
	MOV	A,L
	STA	BADNAM+6

;	MOVE NAME INTO FCB

	LXI	H,BADNAM
	LXI	D,FCB3+1
	MVI	C,11
	CALL	BMOVE
	
	LXI	D,FCB3
	MVI	C,SEARCH	;SEE IF IT EXISTS
	CALL	BDOS
	INR	A
	JNZ	NAMLOP	;IF SO TRY ANOTHER NAME

;	NAME IS UNIQUE SO CREATE A DIRECTORY ENTRY

	LXI	D,FCB3
	MVI	C,MAKEF
	CALL	BDOS
	LXI	D,FCB3	;NOW CLOSE ENTRY
	MVI	C,CLOSEF
	CALL	BDOS

;	NOW SCAN DIRECTORY FOR NAME & FILL ALLOCATION MAP WITH BAD BLOCKS

	LHLD	OFF
	SHLD	CURTRK	;FIRST TRACK
	LXI	H,0		;FIRST SECTOR
	SHLD	CURSEC
	LXI	B,DIRBUF	;USE DIRECTORY BUFFER	
	CALL	SETDMA
	
FIXLOP:
	CALL	READ		;READ A SECTOR
	CALL	CMPTST	;COMPARE FOR NEW FILE NAME
	JZ	FILOP		;IF FOUND DO NEXT FILE	
	CALL	UPDATE	;IF NOT FOUND SET NEXT SECTOR
	JZ	FILOP		;RETURN IF DIRECTORY SCANNED
	JMP	FIXLOP	;ELSE CONTINUE


;	SCAN CURRENT SECTOR FOR THIS FILE NAME

CMPTST:
	MVI	A,4		;4 ENTRIES PER SECTOR
	STA	RECCNT
	LXI	H,DIRBUF	;FROM THIS BUFFER	
	SHLD	DIRPTR

CMPTS0:
	LHLD	DIRPTR	;GET BUFFER POINTER
	INX	H		;SET AT START OF NAME
	LXI	D,FCB3+1	;COMPARE WITH OUR FCB	
	MVI	C,11		;11 BYTES MUST BE SAME
	CALL	COMPNM	;DO COMPARE ROUTINE
	JZ	BLKOUT	;IF MATCH GO DO ALLOCATION
	LHLD	DIRPTR	;MAKE NEXT ENTRY ADDRESS
	LXI	B,32
	DAD	B
	SHLD	DIRPTR		
	LHLD	DIRLEN	;UPDATE DIRECTORY ENTRIES
	DCX	H
	SHLD	DIRLEN
	MOV	A,H
	ORA	L
	JZ	FILOP		;WE HAVE SCANNED ALL OF DIRECTORY
	LDA	RECCNT	;GET ENTRIES\SECTOR
	DCR	A		;UPDATE
	STA	RECCNT
	JNZ	CMPTS0		
	CPI	2		;SHOW FILE NOT FOUND HERE
	RET			;DO NEXT SECTOR


BLKOUT:
;	PUT BAD BLOCKS INTO FCB ALLOCATION MAP, SET RECS AS 8

	CALL	FILALL	;FIX UP FCB TO HOLD NEXT 8 BAD BLOCKS
	MVI	C,1		;SET DIRECTORY WRITE FLAG
	CALL	SECWRT	;WRITE THIS SECTOR
	LDA	FILCNT	;UPDATE FILE COUNT
	INR	A
	STA	FILCNT
	LDA	BADNUM	;SEE IF BAD BLOCKS LEFT
	ORA	A
	JZ	PRMPT		;IF ALL DONE
	XRA	A
	RET


FILALL:
	LHLD	DIRPTR	;GET CURRENT ENTRY	
	LXI	D,15
	DAD	D		;POINT TO RECORD BYTE
	MVI	A,8		;SET FOR 8 RECORDS WRITTEN
	MOV	M,A
	INX	H		;POINT TO ALLOCATION MAP ENTRY
	PUSH	H		;SAVE IT FOR NOW

;	MAKE POINTER TO BAD BLOCK TABLE

	MVI	H,0
	LDA	FILCNT	;GET THIS FILE #
	MOV	L,A		;INDEX FOR NEXT 8 BAD BLOCKS
	DAD	H		;*2
	DAD	H		;*4
	DAD	H		;*8
	DAD	H		;*16
	XCHG			;INDEX VALUE IN DE
	LXI	H,BLKTAB	;START OF BAD BLOCK TABLE	
	DAD	D		;HL HAS BAD BLOCK TABLE ENTRY
	POP	D		;DE HAS FCB ALLOCATION ENTRY
BLKMOV:
	MVI	B,8		;DO UP TO 8 BLOCKS
BLKMV:
	MVI	C,2		;TWO BYTES PER ALLOCATION ENTRY
	CALL	BMOVE		;MOVE IN A BLOCK
	LDA	BADNUM	;GET BAD BLOCK COUNTER
	DCR	A		;UPDATE
	STA	BADNUM
	RZ			;RETURN IF DONE
	DCR	B		;ELSE DO ANOTHER BLOCK
	JNZ	BLKMV
	RET
	
	
COMPNM:
;	COMPARE CHARACTER STRINGS AT HL AND DE FOR C BYTES

	LDAX	D
	CMP	M
	RNZ
	INX	H
	INX	D
	DCR	C
	RZ
	JMP	COMPNM


;	RESET USER AREA TO 0

PPRMPT:
	MVI	C,SETUSR
	MVI	E,0
	CALL	BDOS
	JMP	PRMPT


;	MOVE UP TO 8 BAD BLOCKS INTO ALLOCATION MAP

BLKIT:
	LDA	FILCNT	;GET CURRENT FILE NUMBER
	MOV	L,A
	MVI	H,0
	DAD	H		;*2
	DAD	H		;*4
	DAD	H		;*8
	DAD	H		;*16
	XCHG
	LXI	H,BLKTAB
	DAD	D		;HL POINTS TO START OF BLOCKS
	MVI	B,8		;DO UP TO EIGHT BLOCKS

;	MOVE BLOCKS INTO PLACE

	LXI	D,FCB3+16	;START OF ALLOCATION MAP
BLKIT0:
	MVI	C,2
	CALL	BMOVE
	DCR	B		;TEST IF LAST BLOCK
	RZ
	LDA	BADNUM
	DCR	A		;TEST IF ACTUAL LAST BLOCK
	STA	BADNUM
	RZ
	JMP	BLKIT0
	
		
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;               INITIALIZE BAD FILE NAME
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
BADIT:
	MVI	A,'A'		;SET INITIAL BAD FILE NAME
	STA	BADFNM
	STA	BADFNM+1
	RET


;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;        GENERATE TWO CHARACTERS FOR A FILE NAME
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

GETTWO:
	LDA	BADFNM
	INR	A
	CPI	5BH
	JNC	..UPIT
	STA	BADFNM
	LHLD	BADFNM
	RET
..UPIT:
	MVI	A,'A'
	STA	BADFNM
	LDA	BADFNM+1
	INR	A
	STA	BADFNM+1
	LHLD	BADFNM
	RET

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;              KEEP A RECORD OF BAD BLOCKS
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

SETBAD:
	LDA	BADNUM	;GET CURRENT NUMBER OF BAD BLOCKS
	INR	A		;UPDATE IT	
	STA	BADNUM
	JZ	ZERO		;TOO MANY BAD BLOCKS
	LXI	H,BLKTAB	;POINT TO BAD RECORD SAVE AREA
	DCR	A		;FOR NOW TEST WITH LAST ENTRY
	ADD	A		;FOR TWO BYTE INDEX
	MVI	D,0
	MOV	E,A
	DAD	D		;POINT TO LAST BLOCK ENTRY
	MOV	C,M		;GET LOW BYTE
	INX	H		;POINT TO HIGH BYTE
	MOV	B,M		;GET HIGH BYTE
	LHLD	BLKNUM	;GET CURRENT BLOCK NUMBER
	MOV	A,H		;TEST IF SAME AS LAST
	CMP	B
	JNZ	..NOPE
	MOV	A,L
	CMP	C
	JNZ	..NOPE
	LDA	BADNUM	;SET BLOCK COUNTER SAME AS BEFORE
	DCR	A
	STA	BADNUM
..NOPE:
	LHLD	BLKNUM	;GET BACK BLOCK NUMBER
	PUSH	H		;SAVE IT
	POP	B		;INTO BC
	LXI	H,BLKTAB	;POINT TO SAVE AREA
	DAD	D		;INDEX IN
	MOV	M,C		;SAVE LOW BYTE
	INX	H
	MOV	M,B		;SAVE HIGH BYTE
	RET

;********************************************************
;     LOCAL ENTRY TABLE FOR BIOS ACCESS STARTS HERE
;********************************************************

HOME:
	LHLD	BHOME	;HOME DRIVE
	PCHL

SELDSK:
	LHLD	BSEL		;SELECT DRIVE
	PCHL

SETTRK:
	LHLD	BTRACK	;SET TRACK
	PCHL

SETDMA:
	LHLD	BDMA		;SET DMA ADDRESS
	PCHL

SETSEC:
	LHLD	BSEC		;SET SECTOR
	PCHL

SECRD:
	LHLD	BREAD		;READ SECTOR
	PCHL

SECWRT:
	LHLD	BWRITE	;WRITE SECTOR
	PCHL

SECTRN:
	LHLD	BSTRAN	;TRANSLATE SECTOR
	PCHL



;********************************************************
;           BIOS ADDRESS VECTORS STORED HERE
;********************************************************

BCONST:	.BLKW	1	;BIOS CONSOLE STATUS
BCONIN:	.BLKW	1	;BIOS CONSOLE INPUT
BCONOT:	.BLKW	1	;BIOS CONSOLE OUTPUT
BHOME:	.BLKW	1	;HOME THE DRIVE
BSEL:		.BLKW	1	;SELECT THE DRIVE	
BTRACK:	.BLKW	1	;SET TRACK TO R/W
BSEC:		.BLKW	1	;SET SECTOR TO R/W
BDMA:		.BLKW	1	;SET DMA ADDRESS
BREAD:	.BLKW	1	;READ SECTOR
BWRITE:	.BLKW	1	;WRITE SECTOR
BSTRAN:	.BLKW	1	;GET SECTOR TRANSLATION


;********************************************************
;  THE DPB FOR THE SELECTED DRIVE IS COPIED TO HERE
;********************************************************

DPB1:
SPT:	.BYTE	0,0	;SECTORS PER TRACK
BSH:	.BYTE	0	;BLOCK SHIFT FACTOR
BLM:	.BYTE	0	;RECORDS/BLOCK-1
EXM:	.BYTE	0	;EXTENT MASK
DSM:	.BYTE	0,0	;BLOCKS/DISK
DRM:	.BYTE	0,0	;DIRECTORY ENTRIES-1	
AL0:	.BYTE	0	;RESRVED DATA BLOCKS FOR DIR. #0
AL1:	.BYTE	0	;  '      '     '     '   '   #1
CKS:	.BYTE	0,0	;CHECKSUM VECTOR SIZE
OFF:	.BYTE	0,0	;RESERVED TRACKS


DPB2:	.BLKB	15
DPB3:	.BLKB	15

XLATE1:	.BLKB	2
XLATE2:	.BLKB	2


;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;         CARRIAGE RETURN & LINE FEED OUTPUT
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

CRLF:
	MVI	E,CR
	CALL	OUTPUT
	MVI	E,LF
	CALL	OUTPUT
	RET

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;          OUTPUT A SPACE CHARACTER TO DISPLAY
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

SPACE:
	MVI	E,' '
	CALL	OUTPUT
	RET


;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;        OUTPUT THE ACCUMULATOR TO SYTEM DISPLAY
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

COUT:
;	CHARACTER OUTPUT ENTRY

	MOV	E,A
	CALL	OUTPUT
	RET


DONEIT:
DONAM:
	JMP	ZERO




;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;          PRINT A FORM FEED (FOR LIST DEVICE)
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::

FORMF:
	MVI	E,FF
	CALL	OUTPUT
	RET



OUTPUT:
	PUSH	PSW
	PUSH	B
	PUSH	D
	PUSH	H
	LDA	LISTO
	ORA	A
	JZ	CONIT
	MVI	C,LIST
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	POP	PSW
	RET

CONIT:
	MOV	A,E		;SAVE CONSOLE CHAR
	PUSH	PSW	
	MVI	C,PRTCON
	CALL	BDOS
	POP	PSW		;GET BACK CONSOLE CHAR
	MOV	E,A		;PUT IN E
	LDA	LSTER		;SEE IF LIST ECHO
	ORA	A
	JNZ	RETRN		;IF NOT JUST RETURN
	MVI	C,LIST	;ELSE ECHO IT
	CALL	BDOS
RETRN:
	POP	H
	POP	D
	POP	B
	POP	PSW
	RET


;********************************************************
;  ROUTINE TO DUMP HEX AND ASCII SECTOR DATA TO DISPLAY
;********************************************************

DUMP:
	CALL	CRLF		;DROP DOWN A LINE
	LXI	H,TRAKNR	;PRINT TRACK NUMBER
	CALL	MSG
	LHLD	CURTRK	;GET TRACK TO DUMP
	CALL	PHLD
	CALL	SPACE
DUMP1:
	LXI	H,SECNUM	;PRINT SECTOR # INFO	
	CALL	MSG
	LDA	CURSEC	;GET THE SECTOR #
	CALL	HXOUT		;PRINT IT
	LXI	H,FILDAT	;FILE DATA MESSAGE
	CALL	MSG		;SET IT UP	
	CALL	CRLF
	CALL	CRLF
	LXI	H,DIRBUF	;GET BUFFER AREA TO DUMP
	SHLD	DMPBUF
	MVI	B,8		;8 DUMPED LINES PER SECTOR
BLKRD:
	MVI	C,16		;DUMP 16 BYTES PER LINE 
	PUSH	H		;SAVE STARTING HL
NXTONE:
	MOV	A,M		;GET BYTE TO DUMP
	CALL	HXOUT		;PRINT IT IN HEX
	CALL	SPACE
UPDH:
	INX	H		;POINT TO NEXT BYTE
	DCR	C		;UPDATE LINE BYTE COUNT
	JNZ	NXTONE	;IF LINE NOT DONE

;       NOW PRINT 'DECODED' DATA TO RIGHT OF DUMP
	
DECODE:
	MVI	C,16		;SET FOR 16 BYTES
	POP	H		;GET BACK START OF THIS LINE
	PUSH	H		;AND RESAVE FOR FILE DATA

DECOD0:
	MOV	A,M		;GET BYTE
	ANI	7FH		;STRIP HIGH BIT
	CPI	' '		;SEE IF PRINTABLE
	JNC	OKCHRS	;IF PRINTABLE
DOT:
	MVI	A,'.'		;LOAD A DOT	
OKCHRS:	CALL	COUT	;PRINT IT
	INX	H		;POINT TO NEXT BYTE
	DCR	C		;UPDATE CHAR. COUNTER
	JNZ	DECOD0	;DO NEXT

;	PRINT FILE DATA

CONTD:
	SHLD	DMPBUF		;UPDATE DUMP BUFFER
	POP	H		;GET BACK POINTER
	MOV	A,B		;GET LINE COUNTER
	RAR			;SEE IF ENTRY LINE
	JC	DOCRLF
	MOV	A,M		;GET ERASE BYTE
	CPI	0E5H
	JZ	DOCRLF	;NOT A VALID FILE
	CALL	FDAT0		;PRINT FILE DATA
	
DOCRLF:	CALL	CRLF
	MOV	A,B
	RAR			;SEE IF DIRECTORY LINE
	JC	NOTSO
	LHLD	DIRNUM	;GET DIRECTORY NUMBER
	INX	H		;UPDATE IT
	SHLD	DIRNUM
NOTSO:
	LHLD	DMPBUF	;GET UPDATED BUFFER POINTER
	DCR	B		;UPDATE LINE COUNTER (8 PER SECTOR)
	JZ	HOLDR
	JMP	BLKRD		;ELSE DUMP REST OF SECTOR

;	WAIT A SHORT WHILE SO USER CAN READ

HOLDR:
	MVI	B,2		;WAIT A WHILE HERE
HLOP:
	LXI	H,0
HLOP0:
	DCX	H
	MOV	A,H
	ORA	L
	JNZ	HLOP0
	DCR	B
	JNZ	HLOP
TSTCON:
	CALL	DHOLD
	RET


;********************************************************
;        UPDATE FILE DATA FIELDS FOR DISPLAY
;********************************************************

FDAT0:
	PUSH	H		;SAVE DIRECTORY POINTER
	CALL	SPACE
	LHLD	DIRNUM	;GET CURRENT DIRECTORY NUMBER
	CALL	PHLD		;PRINT ENTRY NUMBER
	CALL	SPACE
	POP	H
	PUSH	H
	MOV	A,M		;GET USER NUMBER
	ANI	0FH
	CALL	HXOUT		;PRINT IT
	CALL	SPACE
	CALL	SPACE
	POP	H		;GET POINTER BACK
	PUSH	H
	LXI	D,12		;GET EXTENT #
	DAD	D
	MOV	A,M
	CALL	HXOUT
	CALL	SPACE
	POP	H
	LXI	D,15
	DAD	D
	MOV	A,M
	CALL	HXOUT
	RET



;********************************************************
;      PRINT THE ACCUMULATOR CONTENTS AS HEX DATA
;********************************************************

HXOUT:
	PUSH 	B		;SAVE BC
	MOV	B,A
        RLC			;DO HIGH NIBBLE FIRST  
        RLC  
        RLC  
        RLC  
        ANI  	0FH		;ONLY THIS NOW
        ADI  	30H		;TRY A NUMBER
        CPI  	3AH		;TEST IT
        JC   	OUT1		;IF CY SET PRINT 'NUMBER'
        ADI  	07H		;MAKE IT AN ALPHA

OUT1:
	MOV	C,A
	CALL 	COUT		;SCREEN IT
      MOV  	A,B		;NEXT NIBBLE
      ANI  	0FH		;JUST THIS
      ADI  	30H		;TRY A NUMBER
      CPI  	3AH		;TEST IT
      JC   	OUT2		;PRINT 'NUMBER'
      ADI  	07H		;MAKE IT ALPHA

OUT2:
	MOV	C,A
   	CALL 	COUT		;SCREEN IT
      POP  	B		;RESTORE BC
	RET


;********************************************************
;            PRINT THE HL REGS AS HEX DATA
;********************************************************

PHLD:
   	MOV  	A,H		;GET HI BYTE
      CALL 	HXOUT		;DO HEX OUT ROUTINE
      MOV  	A,L		;GET LOW BYTE
      CALL 	HXOUT		;HEX IT
	CALL	DHOLD
	RET

;********************************************************
;    PRINT A MESSAGE STRING UNTIL BIT 7 IS SET IN CHAR
;********************************************************

MSG:
	MOV	A,M
	CALL	COUT
	MOV	A,M
	ANI	80H
	INX	H
	JZ	MSG
	RET


;	RENAME ORIGINAL FILE, THEN READ IT IN

KEEPIT:

;	SEE IF FILE EXISTS

	MVI	C,OPENF		;OPEN FUNCTION FOR WSO.COM
	LXI	D,FCB3
	CALL	BDOS
	INR	A		;TEST RESULT
	JNZ	GETWSO		;WE HAVE IT SO USE IT


;	NO WSO.COM CREATED YET SO NOW TEST FOR WS.COM

	CALL	CLEARF		;CLEAR FCB
	LXI	H,OLDNAM	;PUT IN WS.COM
	LXI	D,FCB3+1
	MVI	C,8
	CALL	BMOVE
	LXI	D,FCB3		;NOW OPEN IT
	MVI	C,OPENF
	CALL	BDOS
	INR	A
	JZ	OPFAIL		;IF NO FILE
	
;	O.K. RENAME WS.COM FOR BACKUP USE	

	CALL	CLEARF
	LXI	H,OLDNAM
	LXI	D,FCB3+1
	MVI	C,8
	CALL	BMOVE		;INSERT WS.COM AS OLD
	LXI	H,NEWNAM
	LXI	D,FCB3+16
	MVI	C,16
	CALL	BMOVE		;INSERT WSO.COM AS NEW
	LXI	D,FCB3
	MVI	C,RENAME	;HAVE CP/M RENAME IT
	CALL	BDOS
	INR	A
	JZ	RENFAL
	CALL	CLEARF
	LXI	H,NEWNAM+1	;OMIT ZERO LEADER
	LXI	D,FCB3+1
	MVI	C,8
	CALL	BMOVE
	MVI	C,OPENF		;NOW OPEN WSO.COM
	LXI	D,FCB3
	CALL	BDOS
	INR	A
	JZ	WOPFAL


;	NOW READ IN THE ENTIRE FILE
	
GETWSO:
	LXI	H,FILBUF	;START OF WS BUFFER
RDLOP:
	XCHG			;PUT INTO DE
	PUSH	D		;SAVE DMA LOCATION
	MVI	C,DMAF	;SET DMA FUNCTION
	CALL	BDOS		;TELL BDOS
	MVI	C,READF	;NOW READ A RECORD
	LXI	D,FCB3	;FOR FILE IN FCB
	CALL	BDOS
	ORA	A		;TEST FOR END OF FILE
	JNZ	DONEIT	;WE HAVE THE FILE

	LHLD	RRECS		;UPDATE RECORD COUNTER
	INX	H
	SHLD	RRECS
	POP	H		;GET LAST DMA ADDRESS
	LXI	D,80H
	DAD	D		;MAKE IT THE NEXT DMA ADDRESS
	JMP	RDLOP		;GET NEXT RECORD

;************************************************
;*	      SAVE THE FILE IN FCB      	
;************************************************


SAVFIL:
GO0:
	MVI	C,PRINTS	;TELL USER WE WANT FILE NAME INFO
	LXI	D,MESS11		
	CALL	BDOS
SINP:
	LXI	D,INBUFF	;POINT TO NAME BUFFER
	MVI	C,GETBUF	;LOAD READ BUFFER FUNCTION
	CALL	BDOS
	LDA	INBUFF+1	;SEE CHARS ENTERED
	ORA	A
	JZ	GO0
	
	LXI	H,INBUFF+2	;POINT TO NAME IN BUFFER
	MOV	B,A		;GET # OF CHARACTERS IN NAME
	MVI	C,8		;ALLOW FOR UP TO 8
NXTCHR:
	MOV	A,M		;GET CHARACTER
	CPI	30H		;SEE IF VALID
	JC	GO0		;WE DON'T WANT THIS NAME
	DCR	C		;COUNT DOWN
	DCR	B		;NEXT CHARACTER
	JNZ	NXTCHR
	

;	CLEAR OUT FCB NEXT

	CALL	CLEARF


;	PUT NAME IN FCB & SAVE THE IMAGE NEXT

FILFCB:
	LXI	H,INBUFF+2	;POINT TO SAVE NAME
	LXI	D,FCB3+1	;POINT TO FCB NAME LOC
	LDA	INBUFF+1	;GET NUMBER OF CHARACTERS
	CPI	9		;TEST MAX LENGTH
	JC	FILOK
	MVI	A,8
FILOKš
	MOV	C,A		;PUT CHAR. COUNT IN C
MOVLOP:
	MOV	A,M		;GET USER NAME
	STAX	D		;MAKE FILE NAME
	INX	H
	INX	D
	DCR	C
	JNZ	MOVLOP

;	NOW TEST IF SAME AS WSO.COM

	JMP	DONAM


;**********************************************************
;*            TEST TO SEE IF FILE EXISTS	
;**********************************************************

DMATCH:
	LDA	TEST
	MOV	E,A
	MVI	C,SLDISK
	CALL	BDOS
	MVI	C,DMAF	;SET UP DMA AREA
	LXI	D,TMPBUF	;POINT DMA BUFFER
	CALL	BDOS

	LXI	D,FCB3
	MVI	C,SEARCH	;SEARCH FIRST FUNCTION
	CALL	BDOS
	CPI	0FFH
	RZ

	LXI	D,NMATCH	;POINT TO FILE MATCH MESS.
	MVI	C,PRINTS	;TELL USER OF MATCH
	CALL	BDOS
	MVI	C,GETCON	;NOW GET ANSWER
	CALL	BDOS
	CPI	7FH		;DUMMY TEST
	RNZ			;SHOW A MATCH WAS FORUND


MAKE1:
	MVI	C,MAKEF	;NOW MAKE FILE IN FCB NAME FIELD
	LXI	D,FCB3
	CALL	BDOS		;DO IT
	CPI	0FFH		;SEE IF MAKE FAILED
	JZ	FAIL		;IF SO SHOW FAILURE


;*************************************************************
;*             NOW WRITE THE FILE TO DISK 	
;*************************************************************

	LXI	H,FILBUF

WRTLOP:
	XCHG			;PUT DMA ADDRESS INTO DE
	MVI	C,DMAF	;SET DMA FUNCTION
	PUSH	D		;SAVE DMA ADDRESS
	CALL	BDOS

	MVI	C,WRITEF	;WRITE RECORD FUNCTION
	LXI	D,FCB3	;POINT FCB
	CALL	BDOS
	CPI	0
	JNZ	FAIL1		;IF FAILURE SHOW IT

	LHLD	RRECS		;GET RECORDS
	DCX	H
	SHLD	RRECS
	MOV	A,H
	ORA	L
	JZ	CLOSE1	;CLOSE OPERATION

	POP	H		;GET BACK DMA ADDRESS
	LXI	D,80H		;ADD A RECORD LENGTH
	DAD	D		;UPDATE POINTER
	JMP	WRTLOP

CLOSE1:
	MVI	C,CLOSEF	;CLOSE FUNCTION
	LXI	D,FCB3	;THIS FCB
	CALL	BDOS		;DO IT
	CPI	0FFH
	JZ	FAIL2		;SHOW IF FAILED
	LXI	D,MESS11	;ELSE SHOW WE ARE DONE
	MVI	C,PRINTS
	CALL	BDOS
	JMP	ZERO


;*****************************************************
;*              FILE I/O MESSAGES FOLLOW
;*****************************************************

FAIL:	
	LXI	D,MAKFAL
	MVI	C,PRINTS
	CALL	BDOS
	JMP	ZERO

FAIL1:
	LXI	D,WRTFAL
	MVI	C,PRINTS
	CALL	BDOS
	JMP	ZERO

FAIL2:
	LXI	D,CLSFAL
	MVI	C,PRINTS
	CALL	BDOS
	JMP	ZERO

OPFAIL:
	LXI	D,OPNFAL
	MVI	C,PRINTS
	CALL	BDOS
	JMP	ZERO
	

;*****************************************************
;*         USER PROMPTING MESSAGES FOLLOW
;*****************************************************


PRMPT:
	XRA	A
	STA	DMPSRC
	LXI	SP,STACK
	CALL	CRLF
	MVI	A,1
	STA	DMPFLG
	STA	REMFLG
	
	XRA	A
	STA	DMPSEC
	MVI	A,'*'
	CALL	COUT

CONLOP:
	MVI	C,GETCON
	CALL	BDOS
	CPI	3
	JZ	ZERO
	CPI	CR
	JNZ	CONLOP
	JMP	GETOPT	;SEE WHATS NEXT


;**********************************************************
;          CLEAR FCB INCASE OF FILE RE-NAME
;**********************************************************

CLEARF:
;	FIRST CLEAR OUT NAME FIELD

	LXI	H,FCB3+1	;POINT TO NAME
	MVI	B,8		;8 POSSIBLE CHARS
	MVI	A,' '		;A SPACE
PAD:
	MOV	M,A		;CLEAR OUT ALL 8 NAME BYTES
	INX	H
	DCR	B
	JNZ	PAD
CLEARU:
;	NOW CLEAR OUT CONTROL FIELDS

	XRA	A		;PREPARE TO ZERO FCB FIELDS
	LXI	H,FCB3+12	;POINT TO CONTROL FIELDS
	MVI	B,36-12	;GET LENGTH TO CLEAR
PAD1:	MOV	M,A		;FILL BYTE
	INX	H
	DCR	B
	JNZ	PAD1
	RET


;*****************************************************
;           FILE I/O ERROR MESSAGES
;*****************************************************
				
MAKFAL:
	.BYTE	CR,LF,LF
	.ASCII	\MAKE FILE FAILED$\

WRTFAL:
	.BYTE	CR,LF,LF
	.ASCII	\WRITE FILE FAILED$\

CLSFAL:
	.BYTE	CR,LF,LF
	.ASCII	\CLOSE FILE FAILED$\
		
OPNFAL:
	.BYTE	CR,LF,LF
	.ASCII	\CAN'T FIND THAT FILE $\

WOPFAL:
	LXI	D,WOPEN
	MVI	C,PRINTS
	CALL	BDOS
	JMP	ZERO

WOPEN:
	.BYTE	CLEAR,TAB,TAB,TAB,TAB
	.ASCII	\CAN'T OPEN WSO.COM$\

NMATCH:
	.BYTE	CR,LF,LF
	.ASCII	\A File With That (Seed) Name Already Exists\
	.BYTE	CR,LF
	.ASCII	\You Must Use Another Name, Enter 'CR' when Ready $\


RENFAL:
	LXI	D,REFAL
	MVI	C,PRINTS
	CALL	BDOS
	JMP	ZERO

REFAL:
	.BYTE	CR,LF,LF
	.ASCII	\FAILED TO RENAME FILE $\

ATTFAL:
	LXI	D,ATTFL
	MVI	C,PRINTS
	JMP	ZERO

ATTFL:
	.BYTE	CR,LF,LF
	.ASCII	\FAILED TO SET ATTRIBUTES $\

REDFIL:
	LXI	D,BADRED
	MVI	C,PRINTS
	CALL	BDOS
	JMP	ZERO

BADRED:
	.BYTE	CR,LF,LF
	.ASCII	\BIOS READ FAILURE$\


WRITF:
	LXI	D,ERASR
	MVI	C,PRINTS
	CALL	BDOS
	JMP	ZERO

ERASR:
	.BYTE	CR,LF,LF
	.ASCII	\DISK WRITE ERROR ON ERASE $\

DHOLD:
	LXI	H,RETST	;POINT TO RETURN
	PUSH	H		;MAKE IT STACK
	LHLD	BCONST	;CONSOLE STATUS TEST
	PCHL
RETST:
	ORA	A		;SEE IF KEY PRESSED
	RZ			;RETURN IF NOT
	LXI	H,RETST1
	PUSH	H
	LHLD	BCONIN
	PCHL
RETST1:
	CPI	' '
	JZ	AGAIN
	CPI	27
	JZ	PRMPT
AGAIN:
	LXI	H,RETST2
	PUSH	H
	LHLD	BCONST
	PCHL
RETST2:
	ORA	A
	JZ	AGAIN
	LXI	H,RETST3
	PUSH	H
	LHLD	BCONIN
	PCHL
RETST3:
	CPI	27
	JZ	PRMPT
	RET	


ZERO:
	LDA	DSKQ
	ORA	A
	JNZ	FREQUE
	JMP	0




;***************************************************
;         PROGRAM STORAGE AREA FOLLOWS
;***************************************************


OLDNAM:
	.BYTE	' ',' ',' ',' ',' ',' ',' ',' '

EXTENS:
	.ASCII	\BAD\

HUH:
	.ASCII	\???BAD\

NEWNAM:
	.BYTE	0
	.BYTE	' ',' ',' ',' ',' ',' ',' ',' '
	.ASCII	\   \
	.BYTE	0,0,0,0,0,0,0


FCB3:
	.BYTE	0
	.BYTE	' ',' ',' ',' ',' ',' ',' ',' '
	.ASCII	\   \
	.BYTE	0,0,0,0,0,0,0,0,0,0,0,0
	.BYTE	0,0,0,0,0,0,0,0,0,0,0,0
	.BYTE	0,0,0,0,0,0,0,0,0,0,0,0
		


;********************************************************
;          USER PROMPTING MESSAGES FOLLOW
;********************************************************

MESS1:
	.BYTE	CLEAR
	.ASCII	\CP/M Disk Utility Functions Ver. 1.04\
	.BYTE	CR,LF
	.ASCII	\Enter a Drive To Run Tests On A: to P: $\


MESS2:
	.BYTE	CLEAR,TAB,TAB,TAB,TAB
	.ASCII	\Program Options\
	.BYTE	CR,LF,LF
	.ASCII	\1...Dump Directory on Screen\
	.BYTE	CR,LF
	.ASCII	\2...Display All Invalid Directory Entries\
	.BYTE	CR,LF
	.ASCII	\3...Rename All Invalid Directory Entries\
	.BYTE	CR,LF
	.ASCII	\4...Remove All Invalid Directory Entries\
	.BYTE	CR,LF
	.ASCII	\5...Test Entire Disk Surface\
	.BYTE	CR,LF	
	.ASCII	\6...Remove Bad Blocks On Drive\
	.BYTE	CR,LF
	.ASCII	\7...Select Another Drive\
	.BYTE	CR,LF
	.ASCII	\8...Read System Tracks\
	.BYTE	CR,LF
	.ASCII	\9...Unerase All Erased Files\
	.BYTE	CR,LF
	.ASCII	\10..Disk to Disk Copy\
	.BYTE	CR,LF
	.ASCII	\11..Dump Disk on Screen\
	.BYTE	CR,LF
	.ASCII	\Enter <Control C> to Quit\
	.BYTE	CR,LF,LF
	.ASCII	\Enter Your Choice... $\

MESS3:
	.BYTE	CR,LF,LF
	.ASCII	\Do You Want to ECHO this on the Printer (Y/N) $\


MESS4:
	.BYTE	CLEAR
	.ASCIi	\All Bad Files Will be Renamed in Increasing Sequence\
	.BYTE	CR,LF
	.ASCII	\From a Seed Name You Enter, With a Default Extension of BAD\
	.BYTE	CR,LF
	.ASCII	\NOTE:  Files With Bad Allocation Parameters Will be Bypassed\
	.BYTE	CR,LF
	.ASCII	\You Will use Option 4 to Remove Them ( Remove Option)\
	.BYTE	CR,LF
	.ASCII	\Please Enter Seed Name of 5 Chars.   $\


MESS7:
	.BYTE	CLEAR
	.ASCII	\All data on selected disk will be DESTROYED\
	.BYTE	CR,LF
	.ASCII	\Enter 'Y' if O.K. to continue, or 'N' if not $\


MESS8:
	.BYTE	CR,LF,LF
	.ASCII	\TRACK\
	.BYTE	CR,LF,LF+80H,EOL


MESS9:
	.BYTE	' ',' ',' ',' ',' '+80H,EOL


MESS10:
	.BYTE	CR,LF
	.ASCII	\TRACK    SECTOR TRACK    SECTOR\
	.BYTE	CR,LF+80H,EOL

MESS11:
	.BYTE	CLEAR
	.ASCII	\Please Enter Name for this File $\


MESS12:
	.BYTE	CR,LF,LF
	.ASCII	\You may not use the SYSTEM DRIVE for this function $\

MESS13:
	.BYTE	CLEAR
	.ASCII	\Please enter drive to copy from ( A: to P:) $\

MESS14:
	.BYTE	CR,LF
	.ASCII	\Please enter drive to copy to ( A: to P:) $\

MESS15:
	.BYTE	CR,LF,LF
	.ASCII	\Sorry but those drives have different characteristics $\

MESS16:
	.BYTE	CR,LF,LF,LF
	.ASCII	\The destination drive did not copy the data correctly.\
	.BYTE	CR,LF
	.ASCII	\The copy operation will terminate now $\

MESS17:
	.BYTE	CLEAR
	.ASCII	\Enter starting track to dump in 4 hex digits (eg: 0000)  $\
SECNUM:
	.ASCIS	\SECTOR #  \


TRAKNR:
	.ASCIS	\TRACK # \


FILDAT:
	.ASCIS	\--------------------------------------- DIR# USR EX RW\


BDAT:
	.ASCIS	\             DIR# USR EX RW\


SIZVIL:
	.ASCIS	\    File Allocation Map Not in Data Area\



;********************************************************
;              PROGRAM STORAGE AREA FOLLOWS
;********************************************************

;CONSOLE INPUT BUFFER & SINGLE CHARACTER STORAGE

ANS:
	.BLKB	1		;ONE BYE FOR CONSOLE INPUT DATA
ANS1:
	.BLKB	1


INBUFF:
	.BYTE	16		;16 CHARACTER BUFFER
	.BLKB	18


;PROGRAM STORAGE

RRECS:	.BLKW	1	;RECORS READ IN (TO WRITE BACK)

BADFNM:	.BYTE	'A','A'	;INITIAL BAD FILE NAME
TEST:		.BYTE	0	;DRIVE TO TEST
CURTRK:	.BLKB	2	;CURRENT TRACK TO READ/WRITE
CURSEC:	.BLKB	2	;CURRENT SECTOR TO READ/WRITE
CURDMA:	.BLKB	2	;CURRENT DMA
DIRENT:	.BLKB	2	;DIRECTORY ENTRIES
DMALOC:	.BLKB	2	;DMA STORAGE
DIRLEN:	.BLKB	2	;LENGTH OF DIRECTORY
DPHADD:	.BLKB	2	;DPH VECTOR ADDRESS
XLATE:	.BLKB	2	;XLATE TABLE ADDRESS
LISTO:	.BYTE	0	;0 = CONSOLE, 1 = LIST
DMPFLG:	.BYTE	1	;DUMP FLAG 0 = DUMP
DIRPTR:	.BLKB	2	;CURRENT DIRECTORY ENTRY
LSTER:	.BLKB	1	;0 TO LIST, 1 IF NOT
SECTR:	.BLKB	1	;SECTOR #
RECCNT:	.BLKB	2	;RECORDS TO READ/WRITE
DMPREC:	.BLKB	2	;RECORDS TO DUMP
DMPSEC:	.BLKB	2	;SECTOR TO DUMP
DMPBUF:	.BLKB	2	;BUFFER TO DUMP
DMPTRK:	.BLKB	2	;TRACK TO DUMP
NUMSEC:	.BLKB	2	;NUMBER OF SECTORS TO R/W
SCNFLG:	.BLKB	1	;SPACE IN NAME FLAG
SPCERR:	.BLKB	1	;ERROR IN SPACE POSITION OF FILE NAME
DIRNUM:	.BLKB	2	;CURRENT DIRECTORY ENTRY BEING R/W
VILFLG:	.BLKB	1	;DISK SIZE VIOLATION FLAG
SECCNT:	.BLKB	2	;DISK SECTOR COUNTER FOR REMOVE
REMFLG:	.BLKB	1	;FILE REMOVAL FLAG
MAXREC:	.BLKB	2	;RECORDS ON DISK
CURREC:	.BLKB	2	;CURRENT RECORD COUNTER
RECNUM:	.BLKB	2	;CURRENT WORKING RECORD
RECPB:	.BLKB	1	;RECORDS PER BLOCK
RPBNUM:	.BLKB	1	;CURRENT RECORD IN BLOCK
BLKNUM:	.BLKB	2	;CURRENT BLOCK
BADNUM:	.BLKB	2	;NUMBER OF BAD RECORDS
FILNUM:	.BLKB	1	;NUMBER OF BAD FILES TO CREATE
FILCNT:	.BLKB	1	;BAD FILES CREATED
BLKPTR:	.BLKB	2	;POINTER TO CURRENT BLOCK ENTRY
SYSSEC:	.BLKB	1	;NUMBER OF SYSTEM TRACK SECTORS
DRVONE:	.BLKB	1	;DRIVE TO COPY FROM
DRVTWO:	.BLKB	1	;DRIVE TO COPY TO
CDMA:		.BLKB	2	;COPY DMA ADDRESS
MAXTRK:	.BLKB	2	;TOTAL TRACKS ON DRIVE

.ASCII	\TRACKS REMAINING====================\

REMTRK:	.BLKB	2	;REMAINING TRACKS ON DRIVE


NAMCNT:	.BYTE	'@',' ',' '	;FILE NAME COUNTER

TESTBF:	.BLKB	12	;TEST NAME GOES HERE	


;********************************************************
;         F.C.B USED TO FIXUP BAD FILE NAMES
;********************************************************

BADNAM:
	.ASCII	\JUNKY      \



FIXFCB:
	.BYTE	0
	.BLKB	36


	.BLKW	256
STACK:
	.BLKB	2


DIRBUF:	.BLKB	128
READBF:	.BLKB	128
WRITBF:	.BLKB	128

.ASCII	\BAD BLOCKS\

BLKTAB:

FILBUF	==	BLKTAB+512

COPBF		==	FILBUF+1024
COPBF1	==	COPBF+(128*150)


	.END

