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
/
ENTERPRS
/
CPM
/
UTILS
/
S
/
UN33.ZIP
/
UN33.MAC
< prev
Wrap
Text File
|
1986-02-27
|
14KB
|
600 lines
.Z80
ASEG
; UN33.MAC - CP/M v3.0 UTILITY FOR RECOVERING ERASED FILES - 02/27/86
;
; This program is based on UNERASE.COM in the public domain. It has
; been modified to work with CP/M 3.0 and later, to change the user area
; of a file and to accept ambiguous files names. It currently works
; with sector sizes of 128, 256 512 and 1024 bytes. It is placed in the
; public domain by Advanced Logic Systems for public use. Advanced Logic
; Systems makes no warrantee on the operation or use of this program or
; its applicability for any given application.
;
; U3 DOES NOT DOES NOT WORK WITH VERSIONS OF CP/M PRIOR TO CP/M 3.0
;
; The U3 command line takes the form:
;
; U3 [d:]afn.aft [user area]
;
; If no user area is specified U3 recovers all erased files on drive D:
; (or the default if D: is not specified) matching afn.aft and places
; them in the current user area. If a user area is specified, U3 moves
; all files in the current user area on drive D: (or the default if D:
; is not specified) matching afn.aft to the specified user area.
;
;
;-----------------------------------------------------------------------
;
; 02/27/86 Rewritten in standard Zilog Z80 code. No external macro li-
; v3.3 braries need to be found/used now. Minor changes. Can now
; be assembled with a normal Z80 assember such as SLR's Z80ASM
; or Microsoft's M80. - Irv Hoff
;
; 12/24/84 Revised code to permit UN3 to be used to either recorver an
; 3.2 erased file or change the user area of a file. Added ambig-
; uous file specifications. Revised code to work with disks
; having more than one directory track. Moved CP/M v3.0 ver-
; sion chec code toa beginning of program and corrected error
; test in NODEF. - R. Saeks
;
; 06/16/84 Revised to work with 1024 byte sectors and to place recover-
; v3.1 ed files in the currently logged-in user area.
; - R. Saeks
;
; 12/29/83 First pass at disassembly of UNERASE.COM and modifications
; v3.0 to make it compatible with CP/M v3.0. Did a 'select disk'
; in DSKPRM so that if you try to recover a file from a disk
; that is a differenta format from the one that you are cur-
; rently logged to, it gets the right DPH. Also changed the
; size of the area where the number of reserved system tracks
; is kept. This allows the number of reserved tracks to be
; greater than 256. - Gale Wolfenbarger
;
;-----------------------------------------------------------------------
;
; Addresses
;
BDOS EQU 05H ; BDOS vector address
WRMBOOT EQU 00H ; Warm boot vector address
DEFFCB EQU 5CH ; Address of the default FCB
DEFFCB2 EQU 6CH ; Address of the second default FCB
;
;
; BDOS functions
;
DIRCALL EQU 32H ; CP/M 3.0 direct BIOS call
DRESET EQU 0DH ; Reset disk system
GETCUR EQU 19H ; Get currently logged in disk
GETUSR EQU 20H ; Get current user
CONIN EQU 01H ; Get a character from the console
CONOUT EQU 02H ; Print a character to the console
SETDMA EQU 1AH ; Set DMA function
GETVER EQU 0CH ; Get CP/M version #
GETPARM EQU 1FH ; Get address of disk parameters
PRINT EQU 09H ; Print string to console
;
;
; ASCII characters
;
CR EQU 0DH ; Carriage return
LF EQU 0AH ; Line feed
;
;-----------------------------------------------------------------------
;
;
ORG 0100H
;
;
JP START
DEFB 'UN 3.3 for CP/M v3.0 - 02/27/86'
;
;
ORG 0200H
;
;
START: LD SP,START
CALL SETUP
CALL RDDIR
CALL FINISH
JP WRMBOOT
;.....
;
;
SETUP: CALL CKVERS ; Check for CP/M 3.0 or later
CALL CKNAME ; Check for valid file name
CALL SETSRCDST ; Set source and destination users
CALL SETBIOS ; Copy BIOS jump vector
RET
;.....
;
;
RDDIR: CALL GETDIR ; Read a directory sector
RET Z ; End or read error
CALL CKENT ; Check entries for file
JP RDDIR
;.....
;
;
FINISH: LD C,DRESET ; Reset disk system
CALL BDOS
LD A,(NOREC) ; Get number of directory found
OR A
JP Z,NOTFND ; Non-found
LD A,(SRCUSR)
CP 0E5H
JP Z,RECOVMSG
LD DE,CHGMSG
JP PRINTMSG
;.....
;
;
RECOVMSG:
LD DE,RECMSG
;
PRINTMSG:
CALL PRTMSG ; Print success message
RET
;.....
;
;
NOTFND: LD DE,FILERR
CALL PRTMSG
RET
;.....
;
;
CKVERS: LD C,GETVER ; Get CP/M version #
CALL BDOS
CP 30H ; Is it 3.0 or greater
JP C,ONLY30 ; This version for CP/M 3.0 and later
RET
;.....
;
;
CKNAME: LD A,(DEFFCB) ; Get drive for file
OR A ; Use default?
JP NZ,NODEF ; No, convert to FCB format
LD C,GETCUR ; Get current disk
CALL BDOS
INC A ; Set up for decrement
;
NODEF: DEC A ; Convert to FCB format
LD (DEFFCB),A ; Save it
LD A,(DEFFCB+1) ; Check for no file
CP ' '+1
RET NC ; Return if ok
LD DE,NAMERR ; Print file error
CALL PRTMSG
JP WRMBOOT ; Give up
;.....
;
;
SETSRCDST:
LD C,GETUSR ; Get user #
LD E,0FFH ; Get user flag
CALL BDOS
LD (CURUSR),A ; Save user #
LD HL,DEFFCB2+1 ; Point to 1st destination char.
LD A,' '
CP (HL)
JP Z,UNERASE ; Unerase if no destination user #
LD B,'0'
LD C,(HL)
INC HL
CP (HL)
JP Z,CHGUSR ; Single digit ASCII user # in 'BC'
LD B,C
LD C,(HL)
INC HL
CP (HL)
JP NZ,USRERROR ; Two digit ASCII user # in 'BC' if zero
;
CHGUSR: LD D,0 ; Initial value for high digit
LD A,'0'
CP B
JP Z,CHGUSR1 ; Ok if high digit is '0'
INC A ; A = '1'
CP B
JP NZ,USRERROR ; Error if high digit not '0' or '1'
LD D,10 ; Value for high digit if '1'
;
CHGUSR1:LD A,'0'-1
CP C
JP NC,USRERROR ; Error if low digit < '0'
LD A,'9'
CP C
JP C,USRERROR ; Error if low digit > 9
LD A,C
SBC A,'0' ; Make low digit hex
ADD A,D
CP 16
JP NC,USRERROR ; Error if user # > 15
LD (DSTUSR),A ; Destination user # in hex
LD A,(CURUSR)
LD (SRCUSR),A ; Source user # is current user #
RET
;.....
;
;
UNERASE:LD A,(CURUSR) ; Place file in current user
LD (DSTUSR),A
LD A,0E5H ; 0E5H = erased file "USER #"
LD (SRCUSR),A
RET
;
USRERROR:
LD DE,USRERR
CALL PRTMSG
JP WRMBOOT
;.....
;
;
; Set up local BIOS jump vector
;
SETBIOS:LD BC,LOCDMA ; Get default DMA address
LD (BCREG),BC
LD A,12 ; Set DMA to default
LD (FUNC),A
CALL CALLBIOS
CALL DSKPRM ; Get disk parameters from BDOS
LD A,(DEFFCB) ; Select drive
LD C,A
LD B,0
LD E,B
LD (BCREG),BC ; BIOS select disk function
LD (DEREG),DE
LD A,9 ; 'SELDSK'
LD (FUNC),A
CALL CALLBIOS
LD A,H
OR L ; Check for drive error
JP Z,NODRV ; Go report it
LD E,(HL) ; Get DPH address
INC HL
LD D,(HL)
EX DE,HL
LD (DPHADD),HL ; Save address to DPH
RET
;.....
;
;
DSKPRM: LD A,(DEFFCB)
LD E,A
LD C,14 ; Select disk
CALL BDOS
LD C,GETPARM ; Get address of disk parameters
CALL BDOS
LD E,(HL) ; Get logical SPT
INC HL
LD D,(HL)
LD (SPT),DE
LD DE,6 ; Offset to DRM (# of directory entries)
ADD HL,DE ; Add offset
LD E,(HL) ; Get DRM
INC HL
LD D,(HL)
PUSH DE
PUSH HL
LD DE,7 ; Point to PSH
ADD HL,DE
LD A,(HL) ; Get it
LD (PSH),A ; Save it
POP HL
POP DE
EX DE,HL
INC HL ; Add 1 for total directory entries
LD A,(PSH)
CP 3 ; 1024 byte sectors
CALL Z,PSH1024
LD A,(PSH)
CP 2 ; 512 byte sectors
CALL Z,PSH512
LD A,(PSH)
CP 1 ; 256 byte sectors
CALL Z,PSH256
LD A,(PSH)
OR A ; 128 byte sectors
CALL Z,PSH128
LD A,L ; Save # of directory sectors
LD (DIRSEC),A
LD HL,(SPT) ; Logical sectors per track
LD A,(PSH)
CP 3 ; 1024 byte sectors
CALL Z,DIV8
LD A,(PSH)
CP 2 ; 512 byte sectors
CALL Z,DIV4
LD A,(PSH)
CP 1 ; 256 byte sectors
CALL Z,DIV2
LD A,L ; PHSPT = SPT for 128 byte sectors
LD (PHSPT),A ; Physical sectors per track
LD HL,5 ; Add offset to # of reserved tracks
ADD HL,DE
LD E,(HL) ; Get number of reserved tracks
INC HL
LD D,(HL)
LD (RESTKS),DE ; Save reserved tracks for later
RET
;.....
;
;
ONLY30: LD DE,ERR30 ; Print message for CP/M Plus only
CALL PRTMSG
JP WRMBOOT
;.....
;
;
GETDIR: LD A,(DIRSEC) ; Get # of directory sectors
OR A
RET Z ; Return if none
CALL PHSECTRK ; Compute cur. physical sector and track
LD BC,(RESTKS) ; Get number of reserved tracks in 'BC'
LD H,0 ; Get physical track number in 'HL'
LD A,(PHTRK)
LD L,A
ADD HL,BC ; Directory track in 'HL'
LD (BCREG),HL ; Set track to directory
LD A,10 ; 'SETTRK'
LD (FUNC),A
CALL CALLBIOS
LD A,(PHSECT) ; Get current physical sector
LD C,A
CALL TRNSEC ; Translate sector if necessary
LD B,0
LD (BCREG),BC ; Point to current sector
LD A,11 ; 'SETSEC'
LD (FUNC),A
CALL CALLBIOS
LD A,13 ; Read sector of directory
LD (FUNC),A
CALL CALLBIOS
AND 1
XOR 1
RET
;.....
;
;
CKENT: XOR A ; Zero flag
LD (RECFLG),A
LD A,(DVD) ; Get number of dir. entries per sector
LD B,A
LD HL,LOCDMA
;
CKNXT: LD A,(SRCUSR)
LD D,A ; Source user # in 'D'
LD A,(HL) ; Get byte
CP D ; Check for source user #
JP NZ,GETNXT ; Nope, skip
PUSH HL
CALL CKFIL ; Yes check for recovery
POP HL
;
RECENT: JP NZ,GETNXT
LD A,(DSTUSR)
LD (HL),A ; Recover/change the entry
LD A,0FH ; Set recovered flag
LD (RECFLG),A
LD A,(NOREC) ; Increment number of records found
INC A
LD (NOREC),A
;
GETNXT: LD DE,32 ; Advance to next entry
ADD HL,DE
DEC B ; Decrement counter
JP NZ,CKNXT
LD A,(RECFLG) ; Check for recovered/changed entry
OR A
JP Z,LOOP ; Nope, continue loop
;
;
; Write sector back to disk if file rec/chg
;
CALL PHSECTRK ; Compute cur. physical sector and track
LD BC,(RESTKS) ; Get number of reserved tracks in 'BC'
LD H,0 ; Get physical track number in 'HL'
LD A,(PHTRK)
LD L,A
ADD HL,BC ; Directory track in 'HL'
LD (BCREG),HL ; Set track to directory
LD A,10 ; 'SETTRK'
LD (FUNC),A
CALL CALLBIOS
LD A,(PHSECT) ; Get current physical sector
LD C,A
CALL TRNSEC ; Translate sector
LD B,0
LD (BCREG),BC ; Point to current sector
LD A,11 ; 'SETSEC'
LD (FUNC),A
CALL CALLBIOS
LD BC,1 ; None deferred write
LD (BCREG),BC
LD A,14 ; Write
LD (FUNC),A
CALL CALLBIOS ; Update directory
OR A ; Check for write error
JP NZ,WRTERROR ; Report error
;
LOOP: LD A,(DIRSEC) ; Decrement directory sectors
DEC A
LD (DIRSEC),A
LD A,(SECTOR) ; Increment sector
INC A
LD (SECTOR),A
RET
;.....
;
;
CKFIL: INC HL ; Check deleted entry for recovery
LD DE,DEFFCB+1 ; Point at file to be recovered
EX DE,HL
LD C,11 ; Look at 11 characters
;
CMPFIL: LD A,'?' ; Check to see if spec is ambiguous
CP (HL)
JP Z,NXTCHR
LD A,(DE) ; Get character in name
AND 7FH ; Turn off high bit
CP (HL) ; Are they equal?
RET NZ ; Nope go get another entry
;
NXTCHR: INC DE ; Yes, continue
INC HL
DEC C
JP NZ,CMPFIL
RET
;.....
;
;
PSH1024:LD A,32 ; Set number of dir. entries per sector
LD (DVD),A
JP DIV32
;
PSH512: LD A,16 ; Set number of dir. entries per sector
LD (DVD),A
JP DIV16
;
PSH256: LD A,8 ; Set number of dir. entries per sector
LD (DVD),A
JP DIV8
;
PSH128: LD A,4 ; Set number of dir. entries per sector
LD (DVD),A
JP DIV4
;.....
;
;
; Falls through as many "divide by 2" as needed
;
DIV32: CALL DIV2 ; Divide 'HL' by 32
DIV16: CALL DIV2 ; Divide 'HL' by 32
DIV8: CALL DIV2 ; Divide 'HL' by 32
DIV4: CALL DIV2 ; Divide 'HL' by 32
DIV2: XOR A ; Divide 'HL' by 2 routine
LD A,H ; Get high order byte
RRA ; Shift right for a divide by 2
LD H,A
LD A,L ; Get low order byte
RRA ; Shift right for a divide by 2
LD L,A
RET
;.....
;
;
PHSECTRK:
LD C,0 ; Set 'PHTRK' to 0
LD A,(PHSPT)
LD B,A ; Phys SPT in 'B'
LD A,(SECTOR) ; Logical directory sector
;
CKPHTRK:CP B ; Compute PHSECT = sectors mod PHSPT
JP C,STSECTRK ; And PHTRK = (sectors - PHSECT)/PHSPT
SUB B
INC C
JP CKPHTRK
;...
;
;
STSECTRK:
LD (PHSECT),A
LD A,C
LD (PHTRK),A
RET
;.....
;
;
PRTMSG: LD C,PRINT ; Print string to console
JP BDOS
;.....
;
;
; Print drive error message
;
NODRV: LD DE,DRVERR
CALL PRTMSG
JP WRMBOOT
;.....
;
;
; Print write error message
;
WRTERROR:
LD DE,WRTERR
CALL PRTMSG
JP WRMBOOT
;.....
;
;
TRNSEC: LD HL,(DPHADD) ; Get translate table address
EX DE,HL
LD (BCREG),BC
LD (DEREG),DE
LD A,16 ; 'SECTRAN'
LD (FUNC),A
CALL CALLBIOS
LD C,L
RET
;.....
;
;
CALLBIOS: ; CP/M v3.0 direct BIOS call
LD C,DIRCALL
LD DE,FUN50
CALL BDOS
RET
;.....
;
;
;-----------------------------------------------------------------------
;
; Data area
;
FUN50:
FUNC: DEFB 0
AREG: DEFB 0
BCREG: DEFB 0,0
DEREG: DEFB 0,0
HLREG: DEFB 0,0
;
DPHADD: DEFB 0,0
DIRSEC: DEFB 0
RESTKS: DEFB 0,0
SECTOR: DEFB 0
NOREC: DEFB 0
RECFLG: DEFB 0
PSH: DEFB 0
DVD: DEFB 0
CURUSR: DEFB 0
SPT: DEFB 0,0
PHSPT: DEFB 0
PHSECT: DEFB 0
PHTRK: DEFB 0
SRCUSR: DEFB 0
DSTUSR: DEFB 0
;.....
;
;
; Messages
;
WRTERR: DEFB CR,LF,'Error occurred during disk Write - ABORT','$'
DRVERR: DEFB CR,LF,'Specified an illegal disk drive - ABORT','$'
RECMSG: DEFB CR,LF,'File recovered','$'
CHGMSG: DEFB CR,LF,'File user area changed','$'
NAMERR: DEFB CR,LF,'No File Name specified - ABORT','$'
FILERR: DEFB CR,LF,'File NOT found','$'
USRERR: DEFB CR,LF,'Invalid User Number - ABORT','$'
ERR30: DEFB CR,LF,'+++ UN3 ONLY WORKS FOR CP/M V3.0 OR LATER +++'
DEFB CR,LF,'$'
;.....
;
;
; Buffer area
;
LOCDMA: DEFS 1024 ; Local DMA buffer
;
;
END