; PROGRAM:  UNERA for ZCPR2
; AUTHOR:  RICHARD CONN
; VERSION:  2.2
; DATE:  25 July 83
; PREVIOUS VERSIONS: 2.1 (24 JULY 83), 2.0 (23 JULY 83)
; DERIVATION:  UNERA BY GENE COTTON

VERS	EQU	22		;version number

;
; PROGRAM TO RECOVER ERASED FILES, BY GENE COTTON
;
; From Interface Age December 1981 pg 146
;
; v2.0 - 07/23/83  Modified to be consistent in the ZCPR2 tool set.
;					- Rick Conn
;
; Contributors:
;	v1.6 - Dave Rand
;	v1.5 - Irv Hoff
;	v1.4 - Paul Traina
;	v1.3 - Irv Hoff
;	v1.2 - Charlie Strom
;	v1.1 - Bruce Blakeslee
; 	v1.0 - Retyped from Interface Age (Dec 81).  - Henry Rothberg
;

;
; System equates:
;
BOOT	EQU	0000H		;CP/M WARM BOOT JUMP VECTOR
BDOS	EQU	BOOT+05H	;CP/M BDOS CALL JUMP VECTOR
TBUFF	EQU	BOOT+80H	;DISK I/O BUFFER
FCB	EQU	BOOT+5CH	;DEFAULT FILE CONTROL BLOCK
FCB2	EQU	BOOT+6CH	;SECONDARY FILE CONTROL AREA
CR	EQU	'M'-'@'		;CTL-M FOR CARRIAGE RETURN
LF	EQU	'J'-'@'		;CTL-J FOR LINE FEED
CTRLC	EQU	'C'-'@'		;ABORT

;
;	ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;

;
;  Branch to Start of Program
;
	ORG	BOOT+100H
	JMP	START

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;	This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
	DB	0FFH	; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
	DW	40H	; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
	DB	0,0	; DISK, USER FOR FIRST PATH ELEMENT
			; DISK = 1 FOR A, '$' FOR CURRENT
			; USER = NUMBER, '$' FOR CURRENT
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0	; DISK, USER FOR 8TH PATH ELEMENT
	DB	0	; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
	DB	0FFH	; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
	DW	0FF00H	; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
	DB	4	; MAXIMUM NUMBER OF DISKS
MUSER:
	DB	31	; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
	DB	0FFH	; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
	DB	0FFH	; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
	DB	10	; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
	DB	'chdir',0	; PASSWORD FOR MOVING INTO PRIV USER AREAS
	DS	41-($-PPASS)	; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
	DB	'$'	; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
	DW	80H	; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
	DW	00000H	; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
	DB	64	; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
	DB	'NAMES   '	; NAME OF DISK NAME FILE
	DB	'DIR'		; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
	DB	000H	; EXTERNAL PATH?
MCREQD:
	DB	000H	; MULTIPLE COMMAND LINE?
MXREQD:
	DB	000H	; MAX USER/DISK?
UDREQD:
	DB	000H	; ALLOW USER/DISK CHANGE?
PUREQD:
	DB	000H	; PRIVILEGED USER?
CDREQD:
	DB	000H	; CURRENT INDIC AND DMA?
NDREQD:
	DB	000H	; NAMED DIRECTORIES?
Z2CLASS:
	DB	0	; CLASS 0
	DB	'ZCPR2'
	DS	10	; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;

;
;  Start of Program
;
START:
;
	LXI	H,0		;SAVE STACK PTR
	DAD	SP
	SHLD	STACK
	LXI	SP,STACK	;SET STACK POINTER
	CALL 	HELLO		;SIGN ON MESSAGE
	CALL	HELPCHK		;CHECK FOR AND PRINT HELP MESSAGE
	CALL	PCHECK		;CHECK PARAMETERS
	LDA	FNCOUNT		;NUMBER OF FILES SPECIFIED
	ORA	A		;0=NONE
	CNZ	TRYFIX		;DO THE RECOVERY
	CALL	BYE		;SIGN OFF MESSAGE
	JMP	BOOT		;RETURN TO CP/M
;
; ** Main Routines **
;

;
; SAY WHO WE ARE
;
HELLO:
	CALL	PRINT
	DB	'UNERA, Version '
	DB	(VERS/10)+'0','.',(VERS MOD 10)+'0',0
	RET
;
; CHECK FOR VALID PARAMETERS AND SAY WHICH CP?M VERSION
;
PCHECK:
	CALL	OPTCHK		;CHECK FOR OPTIONS AND SET FLAGS
	CALL	FCBCHK		;MAKE SURE FILE SPECIFIED
	CALL	CPMCHK		;ESTABLISH CP/M PARAMETERS
	CALL	PUSCHK		;CHECK IF USER WANTS TO CHANGE DISK
	RET
;
; LOOK THROUGH DIRECTORY
;
TRYFIX:
	CALL	NXTSEC		;GET A DIRECTORY SECTOR
	RZ			;RETURNS ZERO FLAG IF NO MORE
	CALL	CHKENT		;CHECK IT OUT AND MAYBE FIX
	JMP	TRYFIX		;KEEP IT UP TILL DONE
;
; SIGN OFF AND RESET SYSTEM
;
BYE:
	MVI	C,13		;SYSTEM RESET
	CALL	BDOS
	LDA	LISTFL		;LIST ONLY?
	ORA	A		;0=NO
	JNZ	PRNF
	LDA	FIXCNT		;CHECK FOR ACTIVITY
	ORA	A
	JZ	PRNF		;SAY NONE FOUND
	CALL	PRINT
	DB	CR,LF,'File(s) Recovered - DOUBLE CHECK Before Using',0
	RET
PRNF:
	CALL	PRINT
	DB	CR,LF,'NO Files Recovered',0
	RET
;
; CHECKS FOR P AND 0 OPTIONS IN COMMAND LINE
;
OPTCHK:
	XRA	A	;TURN OFF FLAGS
	STA	CURUSR
	STA	PAUSE
	STA	FIXCNT
	STA	LISTFL
	STA	FNCOUNT	;NO FILE NAMES
	LXI	H,1	;SET SECTOR 1
	SHLD	SECTOR
	LXI	H,TBUFF	;SCAN THRU TBUFF, BUILDING A FILE NAME TABLE
	MOV	A,M	;GET CHAR COUNT
	INX	H	;PT TO FIRST CHAR
	PUSH	H	;SAVE PTR
	ADD	L	;PT TO AFTER LAST CHAR
	MOV	L,A
	MVI	M,0	;STORE ENDING ZERO
	POP	H	;GET PTR TO FIRST CHAR
	CALL	SBLANK	;SKIP BLANKS
	LXI	D,FNTAB	;PT TO TABLE
FNLOOP:
	PUSH	D	;SAVE TABLE PTR
	CALL	GETFN	;EXTRACT FILE NAME
	POP	D
	PUSH	H
	LXI	H,11	;PT TO NEXT TABLE ENTRY
	DAD	D
	XCHG
	POP	H
	LDA	FNCOUNT	;INCREMENT COUNT
	INR	A
	STA	FNCOUNT
	MOV	A,M	;GET TERMINATING CHAR
	INX	H	;PT TO NEXT
	CPI	','	;ANOTHER FOLLOWS?
	JZ	FNLOOP
	DCX	H	;POINT BACK TO DELIM
	CALL	SBLANK	;SKIP TO NON-BLANK
OPTCK1:
	MOV	A,M	;GET OPTION
	CALL	DELCHK	;DONE IF DELIM
	RZ
	CPI	'L'	;LIST ONLY?
	JZ	OPTCKL
	CPI	'P'	;PAUSE?
	JZ	OPTCKP
	CPI	'Z'	;USER 0?
	JZ	OPTCKZ
	CALL	PRINT
	DB	CR,LF,'Invalid Option -- ',0
	MOV	A,M
	CALL	TYPE
	JMP	HCK1
OPTCKL:
	MVI	A,0FFH	;SET FLAG
	STA	LISTFL
	INX	H	;PT TO NEXT
	JMP	OPTCK1
OPTCKP:
	MVI	A,0FFH	;SET FLAG
	STA	PAUSE
	INX	H	;PT TO NEXT
	JMP	OPTCK1
OPTCKZ:
	MVI	A,0FFH	;SET FLAG
	STA	CURUSR
	INX	H
	JMP	OPTCK1
GETFN:
	PUSH	D	;FILL TARGET FCB
	MVI	B,11	;11 BYTES
	MVI	A,' '	;SPACE FILL
GETFN0:
	STAX	D	;PUT SPACE
	INX	D
	DCR	B
	JNZ	GETFN0
	POP	D	;PT TO ENTRY AGAIN
	CALL	SCANCOL	;SCAN FOR COLON
	MVI	B,8	;8 CHARS MAX
	CALL	GETFN1	;GET AND FILL ENTRY
	MOV	A,M	;GET CHAR
	CPI	'.'	;DELIM?
	RNZ		;DONE
	INX	H	;PT TO AFTER PERIOD
	MVI	B,3	;3 CHARS MAX AND DO IT AGAIN
GETFN1:
	MOV	A,M	;GET CHAR
	CPI	'.'	;END OF FIELD?
	JZ	GETFN3
	CALL	DELCHK	;CHECK DELIMITER
	RZ
	CPI	'*'	;WILD?
	JZ	GETFNQ
	STAX	D	;STORE CHAR
	INX	H	;PT TO NEXT
	INX	D
	DCR	B	;COUNT DOWN
	JNZ	GETFN1
GETFN2:
	MOV	A,M	;FLUSH CHARS TO DELIM
	CALL	DELCHK	;CHECK FOR DELIMITER
	RZ
	INX	H	;PT TO NEXT
	JMP	GETFN2
GETFN3:
	INX	D	;PT TO AFTER FIELD
	DCR	B	;COUNT DOWN
	JNZ	GETFN3
	RET
GETFNQ:
	MVI	A,'?'	;FILL WITH QUESTION MARKS
	STAX	D
	INX	D
	DCR	B
	JNZ	GETFNQ
	JMP	GETFN2	;SKIP TO DELIM
DELCHK:
	ORA	A	;END OF LINE?
	RZ
	CPI	'.'	;END OF FIELD?
	RZ
	CPI	','	;END OF ENTRY?
	RZ
	CPI	' '
	RET
SBLANK:
	MOV	A,M	;SKIP TO NON-BLANK
	CPI	' '
	RNZ
	INX	H
	JMP	SBLANK
SCANCOL:
	PUSH	D	;SAVE TABLE PTR
	PUSH	H	;SAVE PTR
SCOL1:
	MOV	A,M	;GET CHAR
	INX	H	;PT TO NEXT
	CPI	':'	;COLON?
	JZ	SCOLX
	CALL	DELCHK	;CHECK FOR DELIMITER
	JNZ	SCOL1
SCOL2:
	POP	H	;RESTORE
	POP	D
	RET
SCOLX:
	XCHG		;DE PTS TO AFTER COLON
	POP	H	;GET OLD PTR
	XCHG		;REPLACE IT
	POP	D	;GET TABLE PTR
	RET
;
; CHECKS THE CURRENT 4 DIRECTORY ENTRIES AGAINST ARGUMENT
; IF MATCH, REWRITES SECTOR WITH REACTIVATED 1ST BYTES
;
CHKENT:
	XRA	A		;ASSUME NO REWRITE
	STA	REWRT
	MVI	B,4		;NUMBER OF ENTRIES PER SECTOR
	LXI 	H,TBUFF		;BEGINNING OF BUFFER
CKLUP:
	PUSH	B
	MOV	A,M
	CPI	0E5H		;CHECK FOR UNUSED
	JNZ	CKINC
	LXI	D,FNTAB		;PT TO POTENTIAL FILES
	LDA	FNCOUNT		;NUMBER OF ENTRIES TO COUNT
	MOV	B,A		;... IN B
CKLUP0:
	PUSH 	H		;SAVE BEGINNING ADDRESS
	PUSH	D		;SAVE PTR
	PUSH	B		;SET NAME COUNT
	CALL	COMPAR		;COMPARE WITH ARGUMENT
	POP	B		;GET NAME COUNT
	POP	D		;GET PTR
	POP	H
	JZ	CKLUP1		;MATCH!
	PUSH	H		;SAVE PTR
	LXI	H,11		;PT TO NEXT ENTRY
	DAD	D
	XCHG
	POP	H
	DCR	B		;COUNT DOWN
	JNZ	CKLUP0
	JMP	CKINC
CKLUP1:
	LDA	LISTFL		;LIST ONLY?
	ORA	A		;0=NO
	JNZ	CKINC
	MVI	M,0		;SET USER 0
	LDA	CURUSR		;CHECK FOR CURRENT USER
	CPI	0FFH
	JZ	CKLUP2
	PUSH	H		;SAVE HL
	MVI	E,0FFH		;GET USER VALUE
	MVI	C,32		;GET USER AREA FUNCTION
	CALL	BDOS		;BDOS RETURNS CURRENT AREA IN 'A' REG.
	POP	H		;RESTORE HL
	MOV	M,A		;POKE IN CURRENT USER AREA
CKLUP2:
	MVI	A,0FH		;SAY NEED REWRITE
	STA	REWRT
	MVI	A,0FFH		;SET COUNT FLAG
	STA	FIXCNT
CKINC:
	POP	B
	LXI	D,32		;LENGTH OF ENTRY
	DAD	D
	DCR	B
	JNZ	CKLUP
	LDA	REWRT		;SEE IF NEED REWRITE
	ORA	A
	JZ	CKDONE		;NO - DONE
;
; WRITE THE DIRECTORY SECTOR BACK TO THE DISK
;
	LHLD	TRACK		;SET TRACK
	MOV	C,L
	MOV	B,H
	CALL	SETTRK
	LHLD	SECTOR		;SET SECTOR
	MOV	B,H
	MOV	C,L
	CALL	TRNSLT
	CALL 	SETSEC
	CALL	WRITE		;WRITE THE SECTOR BACK
	ORA	A
	JNZ	ERRWRT		;ABORT IF ERROR
CKDONE:
	LHLD	DIRMAX
	DCX	H		;REDUCE SECTORS LEFT
	SHLD	DIRMAX
	LHLD	SECTOR		;POINT TO NEXT SECTOR
	INX	H
	SHLD	SECTOR
	XCHG
	LHLD	MAXSEC		;REACHED LIMIT?
	INX	H		;ONE MORE
	MOV	A,H		;CHECK HIGH
	CMP	D
	RNZ
	MOV	A,L		;CHECK LOW
	CMP	E
	RNZ
	LHLD	TRACK		;NEXT TRACK
	INX	H
	SHLD	TRACK
	LXI	H,1		;FIRST SECTOR OF NEXT TRACK
	SHLD	SECTOR
	RET
;
; COMPARE 11 BYTES OF DIRECTORY ENTRY AGAINST ARGUMENT
;
COMPAR:
	SHLD	TEMP		;Hold pointer in case of match
	INX	H
	XCHG
	MVI	C,11
CMPR1:
	LDAX	D		;GET DIRECTORY ENTRY CHARACTER
	ANI	7FH		;STRIP ANY FLAGS
	CMP	M
	JNZ	CMPCKAM
CMPR2:
	INX	D
	INX	H		;BUMP TO NEXT CHARACTER
	DCR	C
	JNZ	CMPR1		;LOOP FOR 11 CHARACTERS
	LDA	FIXCNT		;CHECK FLAG
	ORA	A		;0=FIRST TIME
	CZ	PRFIX
	LHLD	TEMP
	CALL	PRINTFCB
	XRA	A
	RET			;RETURNS 'ZERO' FLAG SET FOR MATCH
PRFIX:
	LDA	LISTFL	;LIST ONLY?
	ORA	A	;0=NO
	JNZ	PRFIX1
	CALL	PRINT
	DB	CR,LF,'File(s) Recovered --',0
	RET
PRFIX1:
	MVI	A,0FFH	;DON'T PRINT THIS AGAIN
	STA	FIXCNT
	CALL	PRINT
	DB	CR,LF,'Erased File(s) --',0
	RET
CMPCKAM:
	LDAX	D
	CPI	0E5H		;NON-ALLOCATED ENTRY?
	JZ	SKIP
	MOV	A,M
	CPI	'?'
	RNZ
	JMP	CMPR2
SKIP:
	ORA	A
	RET			;SET NZ FLAG
;
; CHECK FOR CP/M VERSION AND SET THINGS
;
CPMCHK:
	LXI	D,80H		;SET DMA TO TBUFF
	MVI	C,26
	CALL	BDOS
	MVI	C,12		;VERSION NUMBER REQUEST
	CALL 	BDOS
	CPI	20H		;EARLIER THAN 2.2?
	JC	VERERR
	CALL	CPM22		;IF 2.2 GO SET THINGS
	CALL	GTBIOS		;ESTABLISH BIOS JUMP VECTOR
;
; SELECT DISK AND SETUP DISK PARAMETER HEADER
;
	LDA	FCB		;GET THE DISK
	MOV	E,A
	MVI	C,14
	CALL	BDOS
	LDA	FCB
	MOV	C,A
	MVI	B,0
	CALL	SELDSK		;MAKE SURE DRIVE IS
	MOV	A,H		;  SELECTED
	ORA	L
	JZ	ILDISK
	MOV	E,M		;GET THE ADDRESS
	INX	H		;  OF THE XLTO
	MOV	D,M	
	XCHG
	SHLD	DPH		;SAVE THE ADDRESS
	RET
VERERR:
	CALL	PRINT
	DB	CR,LF,'ABORT - Prior to CP/M 2.x',0
	JMP	BOOT
;
; IF CP/M 2.2 DETERMINE NUMBER OF DIRECTORY ENTRIES ALSO
;
CPM22:
	MVI	C,31		;GET DISK PARAMETERS ADDRESS
	CALL	BDOS		;DPB ADDRESS IN 'HL' ON RETURN
	MOV	E,M		;NUMBER OF SECTORS/TRACK
	INX	H		;AS 2-BYTE QUANTITY IN DE
	MOV	D,M
	INX	H
	XCHG
	SHLD	MAXSEC		;SET MAX SECTORS/TRACK
	XCHG
	INX	H
	INX	H
	MOV	A,M		;GET EXM
	STA	EXTENT
	INX	H		;PT TO DRM
	INX	H
	INX	H
	MOV	E,M		;GET NUMBER OF
	INX	H		;  DIRECTORY ENTRIES
	MOV	D,M
	XCHG
	INX	H		;ACCOUNT FOR - 1
	CALL	SHFHL2		;SHIFT 'HL' RIGHT 2
	SHLD	DIRMAX		;SAVE NUMBER DIRECTORY SECTORS
	LXI	H,5		;NOW POINT TO SYSTEM
	DAD	D		;  TRACK OFFSET
	MOV	A,M		;PICK UP NUMBER OF
	INX	H
	MOV	H,M
	MOV	L,A
	SHLD	TRACK
	RET
;
; ERROR OCCURED DURING DISK WRITE - ABORT
;
ERRWRT:
	CALL	PRINT
	DB	CR,LF,'ABORT - Error During Disk Write',0
	JMP	BOOT		;ABORT
;
; MAKE SURE A LEGAL DISK IS SPECIFIED AND CHECK FOR HELP
;
FCBCHK:
	LDA	FCB		;GET DRIVE SPECIFICATION
	ORA 	A		;SEE IF DEFAULT
	JNZ	FCBCK1		;NO, GO CHECK FILENAME
	MVI	C,25		;ASK FOR CURRENT DRIVE
	CALL	BDOS
	INR	A		;OFFSET FOR NEXT INSTRUCTION
FCBCK1:
	DCR	A		;CURRENT DRIVE NUMBER
	STA	FCB		;SAVE IT
	RET
;
;  CHECK FOR HELP REQUEST
;
HELPCHK:
	LDA	FCB+1		;GET 1ST BYTE OF FILENAME
	CPI	'/'		;HELP?
	JZ	HCK1
	CPI	' '		;MAKE SURE IT IS NON-BLANK
	RNZ			;OK - KEEP GOING
;	
; IF NO FILE NAME IS SPECIFIED, ABORT WITH NOTICE
;
HCK1:
	CALL 	PRINT
	DB	CR,LF
	DB	CR,LF,'	UNERA is used to Unerase Files.  It must be used'
	DB	CR,LF,'IMMEDIATELY after the file is erased (before any'
	DB	CR,LF,'new files are created).  It is invoked by a command'
	DB	CR,LF,'of the form:'
	DB	CR,LF,'		UNERA afn,afn,afn,... o'
	DB	CR,LF,'where "afn" is an ambigous file name which'
	DB	CR,LF,'specifies the files to be unerased and "o" is'
	DB	CR,LF,'none or more of the following options:'
	DB	CR,LF,'		L - List Erased Files Only'
	DB	CR,LF,'		P - Pause for disk change'
	DB	CR,LF,'		Z - Place file in User 0 '
	DB	'(default is current)'
	DB	CR,LF,'	The forms:'
	DB	CR,LF,'		UNERA or UNERA //'
	DB	CR,LF,'present this Help message.'
	DB	CR,LF,'	Drive prefixes (DU:) are ignored.'
	DB	CR,LF,0
CLEANRET:
	LHLD	STACK		;QUIET RETURN
	SPHL
	RET
;
; GET BIOS JUMPS VECTORS FOR EASY REFERENCE
;
GTBIOS:
	LHLD	BOOT+1		;POINTS TO BIOS JUMP TABLE+3
	LXI	D,WBOOT		;WHERE WE WILL KEEP A COPY
	MVI	B,16*3		;MOVE 48 BYTES AND FALL THRU TO MOVE
;
; GENERAL PURPOSE MOVE ROUTINE
; FROM 'HL' TO 'DE' FOR COUNT OF 8
;
MOVE:
	MOV	A,M		;GET A BYTE
	STAX	D		;PUT A BYTE
	INX	D		;INCREMENT TO NEXT
	INX	H
	DCR	B		;COUNT DOWN
	JNZ	MOVE
	RET
;
;SPECIFIED AN ILLEGAL DISK DRIVE - ABORT
;
ILDISK:
	CALL	PRINT
	DB	CR,LF,'ABORT - Illegal Disk Requested',0
	JMP	BOOT		;ABORT
;
; READS NEXT SECTOR (GROUP OF FOUR DIRECTORY ENTRIES)
; RETURNS WITH ZERO FLAG SET IF NO MORE
;
NXTSEC:
	LHLD	DIRMAX		;SEE IF MORE SECTORS
	MOV	A,H
	ORA	L
	RZ			;RETURNS ZERO FLAG IF NO MORE
	LHLD	TRACK		;SET TRACK
	MOV	C,L
	MOV	B,H
	CALL	SETTRK
	LHLD	SECTOR		;SET SECTOR
	MOV	B,H
	MOV	C,L
	CALL	TRNSLT
	CALL	SETSEC
	CALL	READ		;READ A SECTOR
	ANI	1		;REVERSE SENSE OF ERROR FLAG
	XRI	1		;RETURNS WITH ZERO FLAG SET
	RET			;IF BAD READ
;
;  PRINT STRING PTED TO BY RET ADR
;
PRINT:
	XTHL
PRINTL:
	MOV	A,M		;GET CHAR
	INX	H		;PT TO NEXT
	ANI	7FH		;MASK
	JZ	PRINTD
	CALL	TYPE		;PRINT
	JMP	PRINTL
PRINTD:
	XTHL
	RET
;
; FCB PRINTING ROUTINE
;
PRINTFCB:
	PUSH	H
	LXI	D,1+8+3
	DAD	D
	LDA	EXTENT		;GET EXTENT MASK
	CMP	M		;COMPARE TO TARGET
	POP	H
	RC			;PRINT ONLY FIRST EXTENT
	CALL	CRLF		;NEW LINE
	MVI	A,' '		;SPACE IN
	CALL	TYPE
	CALL	TYPE
	INX	H
	MVI	B,8
	CALL	PR1
	MVI	A,'.'
	CALL	TYPE
	MVI	B,3
PR1:
	MOV	A,M
	ANI	7FH
	CPI	' '		;Check for blanks
	CNZ	TYPE
	INX	H
	DCR	B
	JNZ	PR1	
	RET
;
;  PRINT CHAR IN A ON TERMINAL; AFFECT NO REGS
;
TYPE:
	PUSH	H	;SAVE REGS
	PUSH	D
	PUSH	B
	PUSH	PSW
	MOV	E,A	;CHAR IN E
	MVI	C,2	;BDOS ROUTINE
	CALL	BDOS
	POP	PSW	;RESTORE REGS
	POP	B
	POP	D
	POP	H
	RET
;
; DOES USER WANT TO PAUSE TO CHANGE DISKS OR SELECT USER 0?
;
PUSCHK:
	LDA	PAUSE		;GET OPTION
	ORA	A
	RZ			;NOPE, SO RETURN
	CALL	PRINT		;PRINT PAUSE MESSAGE
	DB	CR,LF,'Change Disk - Hit ^C to Abort, Anything Else to Cont - '
	DB	0
	MVI	C,01
	CALL	BDOS		;INPUT A CHAR
	CPI	CTRLC		;ABORT?
	JZ	CLEANRET
	CALL	CRLF
	MVI	C,0DH
	JMP	BDOS		;RESET THE DISK
;
;  NEW LINE
;
CRLF:
	MVI	A,0DH		;NEW LINE
	CALL	TYPE
	MVI	A,0AH
	JMP	TYPE
;
; SHIFT REGS 'HL' RIGHT 2 BITS LOGICAL
;
SHFHL2:
	CALL	SHFHL		;ROTATE RIGHT 1 BIT AND FALL THRU
SHFHL:
	XRA	A		;CLEAR CARRY
	MOV	A,H
	RAR			;SHIFTED BIT IN CARRY
	MOV	H,A
	MOV	A,L
	RAR
	MOV	L,A
	RET
;
; TRANSLATE REG 'BC' FROM LOGICAL TO PHYSICAL SECTOR NUMBER
;
TRNSLT:
	LHLD	DPH		;GET ADDRESS OF XLTO
	XCHG
	CALL	SECTRAN		;USE BIOS ROUTINE
	MOV	C,L		;RETURN VALUE IN BC
	MOV	B,H
	RET
;
; THIS IS THE WORKING COPY OF THE BIOS JUMP TABLE
;
WBOOT:	 DS	3
CONST:	 DS	3
CONIN:	 DS	3
CONOUT:	 DS	3
LIST:	 DS	3
PUNCH:	 DS	3
READER:	 DS	3
HOME:	 DS	3
SELDSK:	 DS	3
SETTRK:	 DS	3
SETSEC:	 DS	3
SETDMA:	 DS  	3
READ:	 DS	3
WRITE:	 DS	3
LISTST:	 DS	3
SECTRAN: DS	3
;
 	DS	100		;STACK DEPTH
STACK:
	DS	2		;LOCATION OF STACK
;
; DATA AREAS
;
FNCOUNT:
	DS	1		;NUMBER OF FILE NAMES IN COMMAND LINE
CURUSR:	DS	1		;0 IF NOT IN CURRENT USER
PAUSE:	DS	1		;0 IF NO PAUSE FOR DISK CHANGE
LISTFL:	DS	1		;0 IF NOT LIST ONLY
DIRMAX:	DS	2		;NUMBER OF SECTORS IN DIRECTORY =
;				;   MAXIMUM NUMBER OF DIRECTORY ENTRIES
;				;   DIVIDED BY 4 (ENTRIES PER SECTOR)
TEMP:	DS	2		;TEMP STORAGE FOR FCB PRINT
EXTENT:	DS	1		;EXTENT MASK
MAXSEC:	DS	2		;MAXIMUM NUMBER OF SECTORS/TRACK
FIXCNT:	DS	1		;CHANGE FLAG
REWRT:	DS	1		;REWRITE FLAG  0=NO, F=YES
SECTOR:	DS	2		;CURRENT SECTOR NUMBER
TRACK:	DS	2		;TRACK NUMBER OF DIRECTORY
;
;    ADDRESS OF THE TRANSLATE TABLE
;
DPH: 	DS	16

FNTAB:	DS	11*40		;FILE NAME BUFFER

	END
