home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ZSYS
/
SIMTEL20
/
ZCPR3
/
UNERASE.MAC
< prev
next >
Wrap
Text File
|
2000-06-30
|
14KB
|
727 lines
; PROGRAM: UNERASE for ZCPR3
; AUTHOR: RICHARD CONN
; VERSION: 1.0
; DATE: 18 May 84
; DERIVATION: UNERA 2.2 (25 July 83) for ZCPR2
; DERIVATION: UNERA BY GENE COTTON
;
VERS EQU 10 ;version number
z3env SET 0f400h
;
; 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
; v1.0 - 05/18/84 Modified to be consistent in the ZCPR3 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
;
;
; SYSLIB AND Z3LIB ROUTINES
;
EXT Z3INIT,CODEND
EXT PRINT,COUT,CRLF
;
; 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
;
; Environment Definition
;
if z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
jmp start
db 'Z3ENV' ;This is a ZCPR3 Utility
db 1 ;External Environment Descriptor
z3eadr:
dw z3env
start:
lhld z3eadr ;pt to ZCPR3 environment
;
else
;
; Internal ZCPR3 Environment Descriptor
;
MACLIB Z3BASE.LIB
MACLIB SYSENV.LIB
z3eadr:
jmp start
SYSENV
start:
lxi h,z3eadr ;pt to ZCPR3 environment
endif
;
; Start of Program -- Initialize ZCPR3 Environment
;
call z3init ;initialize the ZCPR3 Env and the VLIB Env
LXI H,0 ;SAVE STACK PTR
DAD SP
SHLD STACK
CALL CODEND ;DETERMINE FREE SPACE
SHLD FNTAB ;SET PTR TO FILE NAME TABLE
LXI D,512 ;1/2 K
DAD D
SPHL ;NEW STACK
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 'UNERASE 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
LHLD FNTAB ;PT TO TABLE
XCHG ;... IN DE
POP H ;GET PTR TO FIRST CHAR
CALL SBLANK ;SKIP BLANKS
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 COUT
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
PUSH H
LHLD FNTAB ;PT TO POTENTIAL FILES
XCHG
POP H
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
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
;
; DETERMINE NUMBER OF DIRECTORY ENTRIES
;
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,'Syntax:'
DB CR,LF,' UNERASE afn,afn,afn,... o'
db cr,lf,'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 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
;
; 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 PRINT ;NEW LINE WITH 2 LEADING SPACES
DB CR,LF,' ',0
INX H
MVI B,8
CALL PR1
MVI A,'.'
CALL COUT
MVI B,3
PR1:
MOV A,M
ANI 7FH
CPI ' ' ;Check for blanks
CNZ COUT
INX H
DCR B
JNZ PR1
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
;
; 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
;
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 2 ;FILE NAME BUFFER
END