home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug060.arc
/
CPM#005.LBR
/
U3.ASM
< prev
next >
Wrap
Assembly Source File
|
1979-12-31
|
13KB
|
539 lines
; U3 - CP/M PLUS UTILITY FOR RECOVERING ERASED FILES AND FOR
; CHANGING THE USER AREA OF A FILE. 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 recoverers all erased files on
; drive d: (or the default if d: is not specified) matching
; afn.aft and places them is 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.
; Versions 1.01 and 1.02 of U3 were prepared by R. Saeks from
; Gale Wolfenbarger's code for version 1.00. Comments regarding
; these revisions may be passed to the author by leaving a
; message on either the
;
; Mesilla Valley RCP/M | (505)-524-6920
; or the
; Lost Dutchman's Gold Mine RCP/M | (602)-848-6708
; HISTORY
;12/24/84 REVISED CODE TO PERMIT U3 TO BE USED TO EITHER
;Ver. 1.02 RECOVER AN ERASED FILE OR CHANGE THE USER AREA
; OF A FILE. ADDED AMBIGUOUS FILE SPECIFICATIONS
; REVISED CODE TO WORK ON DISKS WITH
; MORE THAN ONE DIRECTORY TRACK. MOVED CPM 3.0
; VERSION CHECK CODE TO BEGINNING OF CODE AND
; CORRECTED ERROR TEST IN NODEF. - R. SAEKS
;06/16/84 REVISED TO WORK WITH 1024 BYTE SECTORS AND TO PLACE
;Ver. 1.01 RECOVERED FILES IN CURRENTLY LOGGED USER AREA.
; - R. SAEKS
;12/29/83 FIRST PASS AT DISASSEMBLY OF UNERASE.COM AND MODIFICATIONS
;Ver. 1.00 TO MAKE IT COMPATIBLE WITH CP/M PLUS
; I ALSO DID A SELECT DISK IN DSKPRM SO THAT IF YOU TRY TO
; RECOVER A FILE FROM A DISK THAT IS A DIFFERENT FORMAT FROM
; THE ONE THAT YOU ARE CURRENTLY LOGGED ON TO, ITS GETS THE
; RIGHT DPH. AT THE SAME TIME I 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 ;CPM 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 CPM 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
; I USED MACROS FROM Z80.LIB TO IMPLEMENT SOME Z80 COMMANDS
; BECAUSE MAC.COM AND Z80.LIB COME WITH CP/M PLUS.
; IF YOU ARE USING ASM.COM OR NOT USING A Z80 PROCESSOR
; YOU WILL HAVE TO USE EQUATES OR INSERT INLINE CODE FOR THE
; Z80 MACROS - gw
MACLIB Z80
ORG 100H
JMP START
DB 'U3 ver 1.02'
DB 'FOR CPM 3.0'
DB '12/29/83 - gw'
DB 'Rev 06/16/84, 12/24/84 - rs'
ORG 200H
START:
LXI SP,START
CALL SETUP
CALL RDDIR
CALL FINISH
JMP WRMBOOT
SETUP:
CALL CKVERS ;CHECK FOR CPM 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
RZ ;END OR READ ERROR
CALL CKENT ;CHECK ENTRIES FOR FILE
JMP RDDIR
FINISH:
MVI C,DRESET ;RESET DISK SYSTEM
CALL BDOS
LDA NOREC ;GET NUMBER of DIR FOUND
ORA A
JZ NOTFND ;NON FOUND
LDA SRCUSR
CPI 0E5H
JZ RECOVMSG
LXI D,CHGMSG
JMP PRINTMSG
RECOVMSG:
LXI D,RECMSG
PRINTMSG:
CALL PRTMSG ;PRINT SUCCESS MESSAGE
RET
NOTFND:
LXI D,FILERR
CALL PRTMSG
RET
CKVERS:
MVI C,GETVER ;GET CPM VERSION #
CALL BDOS
CPI 30H ;IS IT 3.0 OR GREATER
JC ONLY30 ;THIS VERSION FOR CPM 3.0 AND LATER
RET
CKNAME:
LDA DEFFCB ;GET DRIVE FOR FILE
ORA A ;USE DEFAULT?
JNZ NODEF ;NO CONVERT TO FCB FORMAT
MVI C,GETCUR ;GET CURRENT DISK
CALL BDOS
INR A ;SET UP FOR DECREMENT
NODEF:
DCR A ;CONVERT TO FCB FORMAT
STA DEFFCB ;SAVE IT
LDA DEFFCB+1 ;CHECK FOR NO FILE
CPI ' '+1
RNC ;RETURN IF OK
LXI D,NAMERR ;PRINT FILE ERROR
CALL PRTMSG
JMP WRMBOOT ;GIVE UP
SETSRCDST:
MVI C,GETUSR ;GET USER #
MVI E,0FFH ;GET USER FLAG
CALL BDOS
STA CURUSR ;SAVE USER #
LXI H,DEFFCB2+1 ;POINT TO 1ST DESTINATION CHAR.
MVI A,' '
CMP M
JZ UNERASE ;UNERASE IF NO DEST. USER #
MVI B,'0'
MOV C,M
INX H
CMP M
JZ CHGUSR ;SINGLE DIGIT ASCII USER # IN BC
MOV B,C
MOV C,M
INX H
CMP M
JNZ USRERROR ;TWO DIGIT ASCII USER # IN BC IF ZERO
CHGUSR:
MVI D,0 ;INITIAL VALUE FOR HIGH DIGIT
MVI A,'0'
CMP B
JZ CHGUSR1 ;OK IF HIGH DIGIT IS '0'
INR A ;A = '1'
CMP B
JNZ USRERROR ;ERROR IF HIGH DIGIT NOT '0' OR '1'
MVI D,10 ;VALUE FOR HIGH DIGIT IF '1'
CHGUSR1:
MVI A,'0'-1
CMP C
JNC USRERROR ;ERROR IF LOW DIGIT < '0'
MVI A,'9'
CMP C
JC USRERROR ;ERROR IF LOW DIGIT > 9
MOV A,C
SBI '0' ;MAKE LOW DIGIT HEX
ADD D
CPI 16
JNC USRERROR ;ERROR IF USER # > 15
STA DSTUSR ;DEST. USER # IN HEX
LDA CURUSR
STA SRCUSR ;SOURCE USER # IS CURRENT USER #
RET
UNERASE:
LDA CURUSR ;PLACE FILE IN CURRENT USER
STA DSTUSR
MVI A,0E5H ;E5H = ERASED FILE "USER #"
STA SRCUSR
RET
USRERROR:
LXI D,USRERR
CALL PRTMSG
JMP WRMBOOT
SETBIOS: ;SET UP LOCAL BIOS JUMP VECTOR
LXI B,LOCDMA ;GET DEFAULT DMA ADDRESS
SBCD BCREG
MVI A,12 ;SET DMA TO DEFAULT
STA FUNC
CALL CALLBIOS
CALL DSKPRM ;GET DISK PARAMETERS FROM BDOS
LDA DEFFCB ;SELECT DRIVE
MOV C,A
MVI B,0
MOV E,B
SBCD BCREG ;BIOS SELDSK FUNCTION
SDED DEREG
MVI A,9 ;SELDSK
STA FUNC
CALL CALLBIOS
MOV A,H
ORA L ;CHECK FOR DRIVE ERROR
JZ NODRV ;GO REPORT IT
MOV E,M ;GET DPH ADDRESS
INX H
MOV D,M
XCHG
SHLD DPHADD ;SAVE ADDRESS TO DPH
RET
DSKPRM:
LDA DEFFCB
MOV E,A
MVI C,14 ;SELECT DISK
CALL BDOS
MVI C,GETPARM ;GET ADDRESS OF DISK PARMS
CALL BDOS
MOV E,M ;GET LOGICAL SPT
INX H
MOV D,M
SDED SPT
LXI D,6 ;OFFSET TO DRM (# OF DIRECTORY ENTRIES)
DAD D ;ADD OFFSET
MOV E,M ;GET DRM
INX H
MOV D,M
PUSH D
PUSH H
LXI D,7 ;POINT TO PSH
DAD D
MOV A,M ;GET IT
STA PSH ;SAVE IT
POP H
POP D
XCHG
INX H ;ADD 1 FOR TOTAL DIRECTORY ENTRIES
LDA PSH
CPI 3 ;1024 BYTE SECTORS
CZ PSH1024
LDA PSH
CPI 2 ;512 BYTE SECTORS
CZ PSH512
LDA PSH
CPI 1 ;256 BYTE SECTORS
CZ PSH256
LDA PSH
ORA A ;128 BYTE SECTORS
CZ PSH128
MOV A,L ;SAVE # OF DIRECTORY SECTORS
STA DIRSECTS
LHLD SPT ;LOGICAL SECTORS PER TRACK
LDA PSH
CPI 3 ;1024 BYTE SECTORS
CZ DIV8
LDA PSH
CPI 2 ;512 BYTE SECTORS
CZ DIV4
LDA PSH
CPI 1 ;256 BYTE SECTORS
CZ DIV2
MOV A,L ;PHSPT = SPT FOR 128 BYTE SECTORS
STA PHSPT ;PHYSICAL SECTORS PER TRACK
LXI H,5 ;ADD OFFSET TO NUMBER OF RESERVED TRACKS
DAD D
MOV E,M ;GET NUMBER OF RESERVED TRACKS
INX H
MOV D,M
SDED RESTKS ;SAVE RESERVED TRACKS FOR LATER
RET
ONLY30:
LXI D,ERR30 ;PRINT MESSAGE FOR CPM PLUS ONLY
CALL PRTMSG
JMP WRMBOOT
GETDIR:
LDA DIRSECTS ;GET # OF DIRECTORY SECTORS
ORA A
RZ ;RETURN IF NONE
CALL PHSECTRK ;COMPUTE CURRENT PHYSICAL SECTOR AND TRACK
LBCD RESTKS ;GET NUMBER OF RESERVED TRACKS IN BC
MVI H,0 ;GET PHYSICAL TRACK NUMBER IN HL
LDA PHTRK
MOV L,A
DAD B ;DIRECTORY TRACK IN HL
SHLD BCREG ;SET TRACK TO DIRECTORY
MVI A,10 ;SETTRK
STA FUNC
CALL CALLBIOS
LDA PHSECT ;GET CURRENT PHYSICAL SECTOR
MOV C,A
CALL TRNSEC ;TRANSLATE SECTOR IF NECESSARY
MVI B,0
SBCD BCREG ;POINT TO CURRENT SECTOR
MVI A,11 ;SETSEC
STA FUNC
CALL CALLBIOS
MVI A,13 ;READ SECTOR OF DIRECTORY
STA FUNC
CALL CALLBIOS
ANI 1
XRI 1
RET
CKENT:
XRA A ;ZERO FLAG
STA RECFLG
LDA DVD ;GET NUMBER OF DIRECTORY ENTRIES PER SECTOR
MOV B,A
LXI H,LOCDMA
CKNXT:
LDA SRCUSR
MOV D,A ;SOURCE USER # IN D
MOV A,M ;GET BYTE
CMP D ;CHECK FOR SOURCE USER #
JNZ GETNXT ;NOPE SKIP
PUSH H
CALL CKFIL ;YES CHECK FOR RECOVERY
POP H
RECENT:
JNZ GETNXT
LDA DSTUSR
MOV M,A ;RECOVER/CHANGE THE ENTRY
MVI A,0FH ;SET RECOVERED FLAG
STA RECFLG
LDA NOREC ;INCREMENT NUMBER OF RECORDS FOUND
INR A
STA NOREC
GETNXT:
LXI D,32 ;ADVANCE TO NEXT ENTRY
DAD D
DCR B ;DECREMENT COUNTER
JNZ CKNXT
LDA RECFLG ;CHECK FOR RECOVERED/CHANGED ENTRY
ORA A
JZ LOOP ;NOPE CONTINUE LOOP
;WRITE SECTOR BACK TO DISK IF FILE REC/CHG
CALL PHSECTRK ;COMPUTE CURRENT PHYSICAL SECTOR AND TRACK
LBCD RESTKS ;GET NUMBER OF RESERVED TRACKS IN BC
MVI H,0 ;GET PHYSICAL TRACK NUMBER IN HL
LDA PHTRK
MOV L,A
DAD B ;DIRECTORY TRACK IN HL
SHLD BCREG ;SET TRACK TO DIRECTORY
MVI A,10 ;SETTRK
STA FUNC
CALL CALLBIOS
LDA PHSECT ;GET CURRENT PHYSICAL SECTOR
MOV C,A
CALL TRNSEC ;TRANSLATE SECTOR
MVI B,0
SBCD BCREG ;POINT TO CURRENT SECTOR
MVI A,11 ;SETSEC
STA FUNC
CALL CALLBIOS
LXI B,1 ;NONE DEFERRED WRITE
SBCD BCREG
MVI A,14 ;WRITE
STA FUNC
CALL CALLBIOS ;UPDATE DIRECTORY
ORA A ;CHECK FOR WRITE ERROR
JNZ WRTERROR ;REPORT ERROR
LOOP:
LDA DIRSECTS ;DECREMENT DIRECTORY SECTORS
DCR A
STA DIRSECTS
LDA SECTOR ;INCREMENT SECTOR
INR A
STA SECTOR
RET
CKFIL:
INX H ;CHECK DELETED ENTRY FOR RECOVERY
LXI D,DEFFCB+1 ;POINT AT FILE TO BE RECOVERED
XCHG
MVI C,11 ;LOOK AT 11 CHARACTERS
CMPFIL:
MVI A,'?' ;CHECK TO SEE IF SPEC IS AMBIGUOUS
CMP M
JZ NXTCHR
LDAX D ;GET CHARACTER IN NAME
ANI 7FH ;TURN OFF HIGH BIT
CMP M ;ARE THEY EQUAL?
RNZ ;NOPE GO GET ANOTHER ENTRY
NXTCHR:
INX D ;YES, CONTINUE
INX H
DCR C
JNZ CMPFIL
RET
PSH1024:
MVI A,32 ;SET NUMBER OF DIRECTORY ENTRIES PER SECTOR
STA DVD
JMP DIV32
PSH512:
MVI A,16 ;SET NUMBER OF DIRECTORY ENTRIES PER SECTOR
STA DVD
JMP DIV16
PSH256:
MVI A,8 ;SET NUMBER OF DIRECTORY ENTRIES PER SECTOR
STA DVD
JMP DIV8
PSH128:
MVI A,4 ;SET NUMBER OF DIRECTORY ENTRIES PER SECTOR
STA DVD
JMP DIV4
DIV32: ;DIVIDE HL BY 32
CALL DIV2
DIV16: ;DIVIDE HL BY 32
CALL DIV2
DIV8: ;DIVIDE HL BY 32
CALL DIV2
DIV4: ;DIVIDE HL BY 32
CALL DIV2
DIV2: ;DIVIDE HL BY 2 ROUTINE
XRA A ;CLEAR CARRY
MOV A,H ;GET HIGH ORDER BYTE
RAR ;SHIFT RIGHT FOR A DIVIDE BY 2
MOV H,A
MOV A,L ;GET LOW ORDER BYTE
RAR ;SHIFT RIGHT FOR A DIVIDE BY 2
MOV L,A
RET
PHSECTRK:
MVI C,0 ;SET PHTRK TO 0
LDA PHSPT
MOV B,A ;PHYS SPT IN B
LDA SECTOR ;LOGICAL DIRECTORY SECTOR
CKPHTRK:
CMP B ;COMPUTE PHSECT = SECTORS MOD PHSPT
JC STSECTRK ;AND PHTRK = (SECTORS - PHSECT)/PHSPT
SUB B
INR C
JMP CKPHTRK
STSECTRK:
STA PHSECT
MOV A,C
STA PHTRK
RET
PRTMSG:
MVI C,PRINT ;PRINT STRING TO CONSOLE
JMP BDOS
NODRV: ;PRINT DRIVE ERROR MESSAGE
LXI D,DRVERR
CALL PRTMSG
JMP WRMBOOT
WRTERROR: ;PRINT WRITE ERROR MESSAGE
LXI D,WRTERR
CALL PRTMSG
JMP WRMBOOT
TRNSEC:
LHLD DPHADD ;GET TRANSLATE TABLE ADDRESS
XCHG
SBCD BCREG
SDED DEREG
MVI A,16 ;SECTRAN
STA FUNC
CALL CALLBIOS
MOV C,L
RET
CALLBIOS: ;CPM 3.0 DIRECT BIOS CALL
MVI C,DIRCALL
LXI D,FUN50
CALL BDOS
RET
FUN50:
FUNC: DS 1
AREG: DS 1
BCREG: DS 2
DEREG: DS 2
HLREG: DS 2
DPHADD:
DS 2
DIRSECTS:
DS 1
RESTKS: DS 2
SECTOR: DB 0
NOREC: DB 0
RECFLG: DB 0
PSH: DS 1
DVD: DB 0
CURUSR: DS 1
SPT: DS 2
PHSPT: DS 1
PHSECT: DS 1
PHTRK: DS 1
SRCUSR: DS 1
DSTUSR: DS 1
WRTERR:
DB CR,LF,'Error occurred during disk Write - ABORT$'
DRVERR:
DB CR,LF,'Specified an illegal disk drive - ABORT$'
RECMSG:
DB CR,LF,'File recovered.$'
CHGMSG:
DB CR,LF,'File user area changed.$'
NAMERR:
DB CR,LF,'No File Name specified - ABORT$'
FILERR:
DB CR,LF,'File NOT found$'
USRERR:
DB CR,LF,'Invalid User Number - ABORT$'
ERR30:
DB CR,LF,'THIS VERSION OF U3 ONLY WORKS'
DB CR,LF,'FOR CPM 3.0 OR LATER',CR,LF,'$'
LOCDMA:
DS 1024 ;LOCAL DMA BUFFER
END