; 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