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
/
UNDELETE.LBR
/
UNDELETE.ZZ0
/
UNDELETE.Z80
Wrap
Text File
|
2000-06-30
|
12KB
|
767 lines
BDOS EQU 5
FCB EQU 5CH
DMA EQU 80H
;
CONIN EQU 1
CONOUT EQU 2
PRINTS EQU 9
GETVERSION EQU 12
SELDSK EQU 14
FINDFILE EQU 17
GETDISK EQU 25
GETALV EQU 27
GETDPB EQU 31
GETUSER EQU 32
;
BS EQU 8
TAB EQU 9
;
;
;********************************
;* *
;* START *
;* *
;********************************
;
BEGIN:
JP START
HELLO:
DB TAB,'Smart File Undelete',13,10
DB TAB,' By Guy Cousineau',13,10
DB TAB,' 1989 - 08 - 25',13,10,10,'$'
START:
LD (OLDSP),SP
LD SP,STACK
LD DE,HELLO
LD C,PRINTS
CALL BDOS
;
;Protect from GO since self-modifying code used
;
LD A,(PRET) ;return pointer
LD (BEGIN),A
LD BC,16*3 ;number of vectors
LD DE,BIOSTABLE
LD HL,(1) ;get BIOS start
LDIR
LD BC,DMA
CALL JSETDMA
LD A,(FCB)
OR A
JP NZ,GOTDRV
LD C,GETDISK
CALL BDOS
INC A
GOTDRV:
DEC A
LD E,A
LD C,SELDSK
CALL BDOS
LD DE,BADDRV
JP NZ,EXITM
;
;Check CP/M Version
;May work with CP/M 3.x but disabled here for safety
;change JP NZ,EXITM to JP C,EXITM if you want to test it on CP/M 3.x
;alternately, you can comment out this section of code entirely
;
LD C,GETVERSION
CALL BDOS
AND 0F0H
CP 20H ;is it CP/M 2.x
LD DE,NOT22
JP NZ,EXITM
;
;get disk info
;
LD DE,READM
LD C,PRINTS
CALL BDOS
LD C,GETDPB
CALL BDOS
LD A,(HL)
LD (SECPERTRK),A
LD DE,4
ADD HL,DE
LD A,(HL)
LD (EXTMASK),A
INC HL
LD C,(HL)
INC HL
LD A,(HL) ;high byte of total groups
LD B,A ;BC=disk size
OR A
JR Z,NOTBIG
LD A,1
NOTBIG:
LD (BIGDISK),A ;save 2-byte alv flag
INC HL ;max dir entry
LD E,(HL)
INC HL
LD D,(HL)
INC DE ;adjust count
SRL D
RR E
SRL D
RR E
LD (SECTOGO),DE ;counter
LD DE,5
ADD HL,DE ;system track offset
LD A,(HL)
INC HL
LD H,(HL)
LD L,A
LD (CURTRK),HL ;start reading here
SRL B
RR C
SRL B
RR C
SRL B
RR C ;disk size/8
INC BC ;adjust count
PUSH BC
LD C,GETALV
CALL BDOS
LD DE,ALV
POP BC ;byte count
LDIR ;copy ALV to RAM
LD HL,FILEBUFF
LD (BUFFPOS),HL
XOR A
LD (CURSEC),A
;
;********************************
;* *
;* Read entire directory *
;* make table entry for E5's *
;* *
;********************************
;
LD A,(CURSEC)
READMORE:
LD B,0
LD C,A
CALL JSECTRAN
LD B,H
LD C,L
CALL JSELSEC
LD BC,(CURTRK)
CALL JSELTRK
CALL JREAD
OR A
LD DE,READERR
JP NZ,EXITM
;
;scan for E5
;
LD B,4 ;entries per record
LD HL,DMA
SCANSEC:
LD A,(HL)
CP 0E5H
CALL Z,MAKETABLE
LD DE,20H
ADD HL,DE
DJNZ SCANSEC
LD HL,(SECTOGO)
DEC HL
LD A,H
OR L
JR Z,READDONE
LD (SECTOGO),HL
LD A,(SECPERTRK)
LD B,A
LD A,(CURSEC)
INC A
CP B
JR NZ,SAMETRK
LD HL,(CURTRK)
INC HL
LD (CURTRK),HL
XOR A
SAMETRK:
LD (CURSEC),A
JR READMORE
;
;print status report so far
;
READDONE:
LD DE,DELFILES
LD C,PRINTS
CALL BDOS
CALL SHOWFILES
;
;********************************
;* *
;* Check ALV overlap *
;* *
;********************************
;
LD HL,FILEBUFF
CHECKALV:
PUSH HL
LD DE,20 ;point to ALV
ADD HL,DE
LD B,16
LD A,(BIGDISK)
OR A
JR Z,CHECK1
LD B,8
CHECK1:
LD E,(HL)
LD D,0
LD A,(BIGDISK)
OR A
JR Z,NOT2B
INC HL
LD D,(HL)
NOT2B
LD A,D
OR E
JR Z,NEXTALV ;end of alv for this file
INC HL
PUSH HL ;save current FILE allocation
LD A,E ;get BIT
AND 7
INC A ;may go around 8 times but who cares
LD C,A ;save here for loop
SRL D
RR E
SRL D
RR E
SRL D
RR E ;DE/8=ALV byte to check
LD HL,ALV
ADD HL,DE
LD A,(HL)
PUSH BC
GETBIT: RLCA
DEC C
JR NZ,GETBIT
POP BC ;get bit counter back
EX DE,HL ;DISK ALV byte
POP HL ;FILE alv pointer
RRCA ;test bit
JR C,KILLFILE
RLCA ;start going back
OR 1 ;set alv bit used
SETBIT: RRCA
DEC C
JR NZ,SETBIT
LD (DE),A ;update ALV
DJNZ CHECK1
XOR A ;set to OK
JR NEXTALV
KILLFILE:
LD A,1
NEXTALV:
POP HL
LD (HL),A ;update flag byte
CALL INCREMENT
JR NZ,CHECKALV
;
;Status report
;
LD DE,NOALV
LD C,PRINTS
CALL BDOS
CALL SHOWFILES
;
;********************************
;* *
;* Check if files exist in USER *
;* *
;********************************
;
LD DE,CHECKM
LD C,PRINTS
CALL BDOS
LD HL,FILEBUFF
DUPLICATE:
LD A,(HL)
OR A
JR NZ,NOCHECK ;already killed
LD DE,FCB2
LD B,33
ZEROFILL:
LD (DE),A
INC DE
DJNZ ZEROFILL
PUSH HL ;save buffer pos
LD DE,5
ADD HL,DE ;start of file name
LD BC,11
LD DE,FCB2+1
LDIR
LD DE,FCB2
LD C,FINDFILE
CALL BDOS
INC A ;if A now zero then file not found
POP HL ;buffer pos
NOCHECK:
LD (HL),A ;update flag
CALL INCREMENT
JR NZ,DUPLICATE
;
;status report
;
LD DE,NODUPS
LD C,PRINTS
CALL 5
CALL SHOWFILES
CALL PRESSKEY
;
;********************************
;* *
;* Show files for tagging *
;* *
;********************************
;
LD DE,MENU
LD C,PRINTS
CALL BDOS
LD HL,FILEBUFF
TAGMORE:
PUSH HL
LD A,(HL)
OR A
JR NZ,NSHOW
LD DE,5+11 ;point to extent
ADD HL,DE
LD A,(EXTMASK)
CP (HL)
JR C,NSHOW ;don't show a second extent
LD DE,-11
ADD HL,DE ;point to file name
CALL CRLF
CALL PRINTFILE
LD E,' '
LD C,CONOUT
CALL 5
CALL GETKEY ;does uppercase
CP 'U'
JR NZ,NSHOW
POP HL
LD A,0FFH
LD (HL),A
PUSH HL
CALL CHECKREST ;check to end of directory for others
NSHOW:
POP HL
CALL INCREMENT
JR NZ,TAGMORE
JP UNDELETE
;
CHECKREST:
EX DE,HL ;DE=start of entry
LD HL,19
ADD HL,DE
LD A,(HL)
CP 80H
RET NZ ;if this extent not full then no next
LD HL,5
ADD HL,DE ;point to name
LD A,(HL) ;get first character for compare
LD DE,FCB2
LD BC,11 ;save name
LDIR
;
;set up CPIR from here to end of table
;
EX DE,HL ;de=current position
LD HL,(BUFFPOS)
OR A
SBC HL,DE ;bytes to do
LD B,H
LD C,L
EX DE,HL ;HL=end of this name
COMPARE:
CPIR
RET NZ
EX AF,AF' ;save first character
PUSH HL
EXX
POP HL ;get current position
LD B,10 ;first char already checked
LD DE,FCB2+1 ;start at second char
CHECKSAME:
LD A,(DE)
CP (HL)
JR NZ,NOMATCH
INC DE
INC HL
DJNZ CHECKSAME
LD DE,-16
ADD HL,DE
LD (HL),0FFH ;tag this extent as well
NOMATCH
EXX ;note old HL and DE unchanged
EX AF,AF' ;get first character back
JR COMPARE
;
;********************************
;* *
;* SHOW and CONFIRM *
;* *
;********************************
;
UNDELETE:
INC A
LD DE,DOTHESE
LD C,PRINTS
CALL BDOS
;
;change the status byte check
;
LD A,(UNDELETE)
LD (INCAPATCH),A
CALL SHOWFILES
LD DE,YESNO
LD C,PRINTS
CALL BDOS
RETRY:
LD E,BS
LD C,CONOUT
CALL BDOS
CALL GETKEY
CP 'U'
JP NZ,RETRY
;
;********************************
;* *
;* FINALLY we're ready *
;* *
;********************************
;
LD E,255
LD C,GETUSER
CALL BDOS
LD (USER),A
LD DE,UNDELMSG
LD C,PRINTS
CALL 5
LD HL,FILEBUFF
UNDELMORE:
LD A,(HL)
INC A
JR NZ,NO_UNDEL
PUSH HL
INC HL
LD C,(HL)
INC HL
LD B,(HL) ;TRACK
INC HL
LD A,(HL) ;SECTOR & OFFSET
PUSH AF
CALL JSELTRK
POP AF
PUSH AF
AND 3FH ;remove sector offset
LD B,0
LD C,A
CALL JSECTRAN
LD B,H
LD C,L
CALL JSELSEC
CALL JREAD
OR A
LD DE,READERR
JP NZ,EXITM
POP AF ;sector offset
RLCA ;from top 2 bits
RLCA
AND 3
LD B,A ;dir entries to skip
LD HL,DMA
LD DE,20H
JR Z,GOTOFFSET
GETOFFSET:
ADD HL,DE
DJNZ GETOFFSET
GOTOFFSET:
LD A,(USER)
LD (HL),A
INC HL
CALL PRINTFILE ;echo file name
CALL CRLF
LD C,1
CALL JWRITE
OR A
LD DE,WRTERR
JP NZ,EXITM
POP HL
NO_UNDEL:
CALL INCREMENT
JR NZ,UNDELMORE
;
;Must exit with WARM BOOT to reset directory
;
JP 0
;
;EXITS
;
EXITM:
LD C,PRINTS
CALL BDOS
EXIT:
LD SP,(OLDSP)
PRET:
RET
;
;********************************
;* *
;* SUBROUTINES *
;* *
;********************************
;
;********************************
;* *
; Make table entry *
;* *
;********************************
;
MAKETABLE:
INC HL
LD A,(HL)
CP 0E5H ;if E5 E5 then not a file
DEC HL
RET Z
PUSH BC
PUSH DE
PUSH HL
LD DE,(BUFFPOS)
XOR A
LD (DE),A
INC DE
LD A,(CURTRK)
LD (DE),A
INC DE
LD A,(CURTRK+1)
LD (DE),A
INC DE
LD A,4 ;entries/sector
SUB B ;Entry number
RRCA
RRCA ;get in top 2 bits
AND 0F8H
LD B,A
LD A,(CURSEC)
OR B
LD (DE),A ;save sector and offset
INC DE
LD BC,32 ;move in entire file name
LDIR
LD (BUFFPOS),DE
POP HL
POP DE
POP BC
RET
;
;********************************
;* *
;*Show files with matching flag *
;* *
;********************************
;
SHOWFILES:
LD DE,FILEBUFF
LD HL,(BUFFPOS)
OR A
SBC HL,DE
EX DE,HL
LD DE,NOFILES
JP Z,EXITM
XOR A
LD (GOTAFILE),A
SHOWMORE:
PUSH HL
LD A,(HL)
INCAPATCH:
OR A
JR NZ,NOSHOW
LD DE,5+11 ;point to extent
ADD HL,DE
LD A,(EXTMASK)
CP (HL)
JR C,NOSHOW ;don't show a second extent
LD DE,-11
ADD HL,DE ;point to file name
LD A,(GOTAFILE)
LD B,A
INC A
LD (GOTAFILE),A
LD A,3
AND B
CALL Z,CRLF
CALL PRINTFILE
LD C,CONOUT
LD E,TAB
CALL BDOS
NOSHOW:
POP HL
CALL INCREMENT
JR NZ,SHOWMORE
LD DE,NOFILES
LD A,(GOTAFILE)
OR A
JP Z,EXITM
RET
;
;********************************
;* *
;* increment table address *
;* *
;********************************
;
INCREMENT:
LD DE,BUFFLEN
ADD HL,DE
EX DE,HL
LD HL,(BUFFPOS)
OR A
SBC HL,DE
EX DE,HL
RET
;
;********************************
;* *
;* CHARACTER FUNCTIONS *
;* *
;********************************
;
CRLF:
PUSH BC
PUSH DE
PUSH HL
LD DE,CRLFMES
LD C,PRINTS
CALL BDOS
POP HL
POP DE
POP BC
RET
;
;Print file name in (HL)
;
PRINTFILE:
LD B,8
LD C,CONOUT
CALL SHOWB
PUSH HL
PUSH BC
LD E,'.'
CALL BDOS
POP BC
POP HL
LD B,3
LD C,CONOUT
SHOWB:
LD A,(HL)
AND 7FH
CP ' '
LD E,A
PUSH BC
PUSH HL
CALL NC,BDOS
POP HL
POP BC
INC HL
DJNZ SHOWB
RET
;
;Ask for keypress to continue
;
PRESSKEY:
LD DE,PRESSM
LD C,PRINTS
CALL BDOS
GETKEY:
LD C,CONIN
CALL BDOS
AND 5FH
CP 3
LD DE,ABORT
JP Z,EXITM
RET
;
;********************************
;* *
;* BIOS VECTOR MAP *
;* *
;********************************
;
BIOSTABLE:
DB 0,0,0 ;WARM BOOT
DB 0,0,0 ;CONSTA
DB 0,0,0 ;CONIN
DB 0,0,0 ;CONOUT
DB 0,0,0 ;LSTOUT
DB 0,0,0 ;PUNOUT
DB 0,0,0 ;READER
DB 0,0,0 ;HOME
DB 0,0,0 ;SELECT DISK
JSELTRK: DB 0,0,0 ;SELECT TRACK
JSELSEC: DB 0,0,0 ;SELECT SECTOR
JSETDMA: DB 0,0,0 ;SELECT DMA
JREAD: DB 0,0,0 ;READ
JWRITE: DB 0,0,0 ;WRITE
DB 0,0,0 ;LIST STATUS
JSECTRAN: DB 0,0,0 ;SECTOR TRANSALTE
;
;********************************
;* *
;* MESSAGES *
;* *
;********************************
;
NOT22 DB 'Not CP/M 2.x$'
BADDRV DB 'Invalid Drive$'
READERR DB 'Drive Read Error$'
WRTERR DB 'Drive Write Error$'
READM DB 13,10,'Reading Directory$'
NOFILES DB 13,10,7,'No Recoverable Files$'
DELFILES DB TAB,'-->',TAB,'Deleted files',13,10,'$'
NOALV: DB 13,10,10,'Files without allocation overlap',13,10,'$'
CHECKM: DB 13,10,10,'Checking for Duplicates$'
NODUPS: DB 13,10,'Files that don''t exist in this user'
CRLFMES DB 13,10,'$'
PRESSM DB 13,10,10,'Press a Key to Continue$'
MENU DB 13,10,10,'Press "U" to undelete'
DB 13,10,'Any other key skips'13,10,7,'$'
DOTHESE DB 13,10,10,'These files will be UNdeleted',13,10,'$'
YESNO DB 13,10,10,'Press "U" to undelete'
DB 13,10,'OR ^C to Abort',13,10,10,' $'
UNDELMSG DB 13,'RECOVERING...',13,10,10,'$'
ABORT: DB 13,10,10,7,'ABORT',13,10,'$'
;
;********************************
;* *
;* DATA *
;* *
;********************************
;
SECPERTRK DS 1
SECTOGO DS 2
CURTRK DS 2
CURSEC DS 1
BIGDISK DS 1
EXTMASK DS 1
GOTAFILE DS 1 ;got a deleted file flag
USER: DS 1
OLDSP DS 30
STACK:
FCB2: DS 33
ALV: DS 2048 ;copy ALV here to work on
;
;UN-ERASABLE FILE BUFFER
;FORMAT 00 01 02 03 04..19 20..35
; FLAG TRACK SEC NAME,EXT,ETC ALLOCATIONS
;FLAG IS 00 FOR GOOD
; FF FOR TAGGED
; ?? FOR NO GOOD (FILE EXISTS OR ALV OVERLAP)
;
BUFFLEN EQU 36
BUFFPOS DS 2
FILEBUFF:
END