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
/
CLEANDIR.MAC
< prev
next >
Wrap
Text File
|
2000-06-30
|
15KB
|
857 lines
;
; Program: CLEANDIR
; Derivation: SAP 3.8 (see following history for authors)
; Derivation By: Richard Conn
; Version: 1.1
; Date: 28 November 1984
; Previous Versions: 1.0 (20 June 84)
;
; bug fix ;841201 Peter T Lyman
; Version 1.1P
;
; Search for ';841201' to locate the code
;
; CLEANDIR can and does wipe out the operating system
; (also known as a crash) whenever the maximum size of
; the directory (DRM) exceeds the available memory....
;
; Maybe that is a good feature, since you at least don't
; hurt the disk...
;
; However on my hard disk I have two platters with
; DRM equal to 2048.... In this case CLEANDIR crashes...
;
; The fix that I have added (I did this with an early version
; of SAP) gives you a choice.... If DRM is greater than
; the space available betwwen BUF and BDOS, you are given
; a choice with proceeding if the actual number of directory
; entries is less than or equal to the space available....
; If not you ABORT.....
;
; The down side risk of this modification is that if you
; proceed ("Y") when the actual number of files exceeds
; the space available, you lose all the directories entries
; which don't fit in the available space....
;
; With out the fix the system crashes and you cannot clean the
; directory... With the fix you can clean the directory, but
; you can lose files if you don't pay attention....
;
vers equ 11
z3env equ 0f400h
;
; SYSLIB and Z3LIB References
;
ext z3init,z3log
ext eprint,cout
ext codend
ext phlfdc ;841201
;
; 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 Environment
; v3.8 SORT AND PACK CP/M DISK DIRECTORY - 10/16/83
;
; THIS PROGRAM READS THE DISK DIRECTORY TRACKS, SORTS THEM ALPHABETICALLY
; THEN REPLACES THEM ON THE DISK. ALL UNUSED OR ERASED AREAS ON THE DIR-
; ECTORY TRACK ARE REFORMATTED WITH CONTINUOUS 'E5' CHARACTERS. (THIS
; ERASES PREVIOUS FILE NAMES WHICH HAVE BEEN DEACTIVATED.) SORTING THE
; DIRECTORY IN THIS MANNER OFFERS MANY ADVANTAGES. SOME OF THEM ARE:
;
; 1) ALLOWS 'DIR' TO SHOW AN ALPHABETIZED LISTING
; 2) ELIMINATES POTENTIAL PROBLEMS WITH "UNERASE" PROGRAMS
; 3) SPEEDS UP ACCESS VIA 'SD' AND OTHER SPECIAL PROGRAMS
; 4) ASSISTS ON WORKING DIRECTLY ON THE DISK WITH 'DUU', ETC.
; 5) REMOVES FILES FROM THE DISK SOMEBODY ELSE COULD RECOVER
;
; - Notes by Irv Hoff W6FFC
;
; 1977 Written by L. E. Hughes. Modified extensively since by Bruce
; Ratoff, Keith Petersen, James Prest, Ron Fowler, Frank Gaude,
; Irv Hoff and likely others.
;
; 10/16/83 Now using a Shell-Metzner sort which speeds the sorting time
; considerably, especially on large directories. (SFK)
;
; 07/27/83 Shows an error flag for MP/M and CP/M+ both. Rewrites dir-
; tory even if previously sorted, to insure erased programs at
; v3.7 end of directory are properly cleared.
; - Irv Hoff
;
TRUE EQU 0FFH
FALSE EQU 0
;
BDOS EQU 5
CR EQU 0DH
DPBLEN EQU 15 ;SIZE OF CP/M2 DISK PARAMETER BLOCK
FCB EQU 5CH
FCB2 EQU 6CH
GETDSK EQU 25 ;BDOS "GET DISK #" FUNCTION
LF EQU 0AH
SELDRV EQU 14 ;SELECT DRIVE
;.....
;
;
; OBTAIN BIOS VECTORS
;
VECTRS:
JMP GETVEC
;
DS 53 ;ROOM FOR JUMP VECTORS
;
WBOOT EQU VECTRS+3 ;DO NOT CHANGE THESE EQUATES
CSTS EQU VECTRS+6
CI EQU VECTRS+9
CO EQU VECTRS+12
LO EQU VECTRS+15
PO EQU VECTRS+18
RI EQU VECTRS+21
HOME EQU VECTRS+24
SELDSK EQU VECTRS+27
SETTRK EQU VECTRS+30
SETSEC EQU VECTRS+33
SETDMA EQU VECTRS+36
READ EQU VECTRS+39
WRITE EQU VECTRS+42
LSTS EQU VECTRS+45 ;ONLY IN CP/M2
SECTRN EQU VECTRS+48 ;ONLY IN CP/M2
;
; GET BIOS VECTORS
;
GETVEC:
LXI D,WBOOT
LHLD 1
MVI B,53
CALL MOVE
;
; PROGRAM STARTS HERE
;
LXI H,0
DAD SP ;GET ADDRESS OF CP/M STACK
SHLD STACK ;STORE IT SO WE CAN GO BACK TO IT
CALL CODEND ;DETERMINE FREE SPACE
LXI D,80H ;ALLOW 80H BYTES FOR STACK
SHLD BUF ;SET BUFFER ADDRESS
SPHL ;SET TOP OF STACK
lda bdos+2 ;fetch bdos page ;841201
dcr a ; less one ;
lhld buf ;fetch buf pntr ;
sub h ;available space for dir ;
mvi h,0 ; ;
mov l,a ;number of pages available ;
dad h ;x2->number of sectors ;
dad h ;x2 ;
dad h ;x2->number of directory ;
; entries which will fit ;
shld maxdir ;save for later ;
XRA A ;SET NO REVERSE OF USER AREAS
STA REVERSE
CALL EPRINT ;PRINT MSG:
DB 'CLEANDIR, Version '
DB (vers/10)+'0','.',(vers mod 10)+'0','P' ;841201
DB 0
LDA FCB+1 ;CHECK FOR HELP REQUEST
CPI '/' ;ANY OPTION MEANS HELP
JZ HELP
CPI 'D' ;SELECT DESCENDING ORDER?
JZ DESC
LDA FCB2+1 ;CHECK FOR OPTION CHAR
CPI 'D' ;DESCENDING ORDER OF USER AREAS?
JNZ SAP
DESC:
MVI A,0FFH ;ENABLE REVERSE
STA REVERSE
JMP SAP
;
; PRINT HELP MESSAGE
;
HELP:
CALL EPRINT
DB CR,LF,'Syntax:'
DB CR,LF,' CLEANDIR dir: o'
DB CR,LF,'Options:'
DB CR,LF,' D - sort in Descending Order (users and files)'
DB CR,LF,'Note:'
DB CR,LF,' Only disk ref is used in dir: form'
DB 0
JMP EXIT1
;
; MAIN PROGRAM ROUTINE
;
SAP:
CALL SETUP
call ckdrsz ;check available memory space ;841201
CALL RDDIR
CALL CLEAN
CALL SORT
CALL PACK
CALL WRDIR
CALL EPRINT
DB 'Done',0
JMP EXIT
ckdrsz: lhld drm ;fetch max dir size ;841201
xchg ; ;
lhld maxdir ;fetch memory available for dir ;
call hlmde ;subtract ;
rnc ;return if room ;
call eprint ;else... ;
db lf,lf,lf,lf,lf,lf ;
db cr,lf,'Your maximum directory size is ',0 ;
lhld drm ;print max dir size ;
inx h ; ;
call phlfdc ; ;
call eprint ; ;
db ' directory entries.',0 ;
call eprint ; ;
db cr,lf,'your memory can only handle ',0 ;
lhld maxdir ;print space available ;
call phlfdc ; ;
call eprint ; ;
db ' directory entries.' ;
db cr,lf,lf,'IF.....your directory DOES NOT exceed ',0;
lhld maxdir ; ;
call phlfdc ; ;
call eprint ; ;
db ' directory entries,' ;
db cr,lf,' (Directory entries NOT Files)';
db cr,lf,' you may enter "Y" to proceed,' ;
db cr,lf,lf,'ELSE...any other key ABORTS.' ;
db cr,lf,lf,lf,lf,lf,lf,lf,lf,'..............> ',7,0;
ck1: mvi c,6 ;get input ;
mvi e,-1 ; ;
call bdos ; ;
cpi 0 ; ;
jz ck1 ; ;
ani 5fh ; ;
cpi 'Y' ; ;
jnz exit1 ; ;
lhld maxdir ; ;
shld drm ; ;
ret ; ;
; ;
hlmde: mov a,h ; ;
cmp d ; ;
rnz ; ;
mov a,l ; ;
cmp e ; ;
ret ; ;
;
; SUBROUTINES
;
;
CLEAN:
LXI H,0 ;I = 0
;
CLNLOP:
SHLD I
CALL INDEX ;HL = BUF + 16 * I
MOV A,M ;JUMP IF THIS IS A DELETED FILE
CPI 0E5H
JZ FILLE5
LXI D,12
DAD D ;HL = HL + 12
MOV A,M ;CHECK EXTENT FIELD
ORA A
JNZ CLBUMP ;SKIP IF NOT EXTENT ZERO
INX H ;POINT TO RECORD COUNT FIELD
INX H
MOV A,M ;GET S2 BYTE (EXTENDED RC)
ANI 0FH ; FOR CPM2, 0 FOR CPM1
MOV E,A
INX H
MOV A,M ;CHECK RECORD COUNT FIELD
ORA E
JNZ CLBUMP ;JUMP IF NON-ZERO
LHLD I ;CLEAR ALL 32 BYTES OF
CALL INDEX ; DIRECTORY ENTRY TO E5
INX H
MOV A,M ;GET FIRST CHAR OF FILENAME
DCX H ; WARD CHRISTENSONS CAT PGMS
CPI '-' ; HAVE DISKNAME OF ZERO LENGTH
JZ CLBUMP ; THAT START WITH '-', DON'T DELETE
CPI ' ' ; DISCAT USES DISKNAME OF ZERO LENGTH
JZ CLBUMP ; THAT STARTS WITH ' ', DON'T DELETE
;
FILLE5:
MVI C,32 ;NUMBER OF BYTES TO CLEAR
;
FILLOP:
MVI M,0E5H ;MAKE IT ALL E5'S
INX H
DCR C
JNZ FILLOP
;
CLBUMP:
LHLD DRM ;GET COUNT OF FILENAMES
INX H
XCHG
LHLD I ;OUR CURRENT COUNT
INX H
PUSH H
CALL SUBDE ;SUBTRACT
POP H
JC CLNLOP ;LOOP TILL ALL CLEANED
RET
;
DODIR:
STA WRFLAG
LHLD SYSTRK
CALL DOTRAK ;SET THE TRACK
LXI H,0
SHLD SECTOR
LHLD DRM ;NUMBER OF DIR ENTRIES
INX H ;RELATIVE TO 1
CALL ROTRHL ;DIVIDE BY 4
CALL ROTRHL ; TO GET SECTOR COUNT
SHLD DIRCNT
LHLD BUF
SHLD ADDR ;FOR DMA ADDRESS
;
DIRLOP:
LHLD SECTOR ;GET SECTORS PER TRACK
INX H
XCHG
LHLD SPT ;CURRENT SECTOR
CALL SUBDE ; SECTOR - SPT
XCHG
JNC NOTROV
;
; TRACK OVERFLOW, BUMP TO NEXT
;
LHLD TRACK
INX H
CALL DOTRAK
LXI H,1 ;REWIND SECTOR NUMBER
;
NOTROV:
CALL DOSEC ;SET CURRENT SECTOR
LHLD ADDR
MOV B,H ;SET UP DMA ADDRESS
MOV C,L
CALL SETDMA
LDA WRFLAG ;TIME TO FIGURE OUT
ORA A ; IF WE ARE READING
JNZ DWRT ; OR WRITING
;
;
; READ
;
CALL READ
ORA A ;TEST FLAGS ON READ
JNZ RERROR ;NZ=ERROR
JMP MORE ;GOOD READ, GO DO MORE
;
; TRACK AND SECTOR UPDATE ROUTINES
;
DOTRAK:
SHLD TRACK
MOV B,H
MOV C,L
CALL SETTRK
RET
DOSEC:
SHLD SECTOR
MOV B,H
MOV C,L
LHLD SECTBL
XCHG
DCX B
CALL SECTRN
MOV B,H
MOV C,L
CALL SETSEC
RET
;
; WRITE
;
DWRT:
MVI C,1 ;FOR CPM/2 DEBLOCKING BIOS'S
CALL WRITE
ORA A ;TEST FLAGS ON WRITE
JNZ WERROR ;NZ=BAD DIRECTORY WRITE
JMP MORE
;
; Exit Program
;
EXIT:
LDA NOBOOT ;SEE IF BOOT IS NEEDED
ORA A
JNZ EXIT1 ;FLAG IS SET IF ALREADY ALPHABETIZED
JMP 0000H ;A REWRITTEN DIRECTORY NEEDS A WARM BOOT
;
EXIT1:
LHLD STACK ;GET ADDRESS OF ORIGINAL CP/M STACK
SPHL ;RESET STACK ADDRESS
RET
;
INDEX:
DAD H
DAD H
DAD H
DAD H
DAD H
XCHG
LHLD BUF ;GET ADDRESS OF BUF
XCHG
DAD D
RET
;
; GOOD READ OR WRITE
;
MORE:
LHLD ADDR ;BUMP DMA ADRS FOR NEXT PASS
LXI D,80H
DAD D
SHLD ADDR
LHLD DIRCNT ;COUNTDOWN ENTRIES
DCX H
SHLD DIRCNT
MOV A,H ;TEST FOR ZERO LEFT
ORA L
JNZ DIRLOP ;LOOP TILL ZERO
;
;
; DIRECTORY I/O DONE, RESET DMA ADDRESS
;
LXI B,80H
CALL SETDMA
RET
;
; MOVE UTILITY SUBROUTINE
;
MOVE:
MOV A,M
STAX D
INX H
INX D
DCR B
JNZ MOVE
RET
;
; PACK DIRECTORY
;
PACK:
LXI H,0 ;I = 0
;
PACK1:
SHLD I
CALL INDEX ;HL = BUF + 16 * I
LXI D,9
DAD D ;HL = HL + 9
MOV A,M ;JUMP IF FILETYPE NOT 'X$$'
SUI '0' ; WHERE 0.LE.X.LE.9
JC PACK2
CPI 10
JNC PACK2
STA J
INX H
MOV A,M
CPI '$'
JNZ PACK2
INX H
MOV A,M
CPI '$'
JNZ PACK2
INX H ;SET EXTENT NUMBER TO X
LDA J
MOV M,A
DCX H ;SET FILETYPE TO '$$$'
MVI M,'$'
DCX H
MVI M,'$'
DCX H
MVI M,'$'
;
PACK2:
LHLD I ;I = I + 1
INX H
XCHG
LHLD DRM
INX H
XCHG
PUSH H
CALL SUBDE
POP H ;LOOP UNTIL I > DRM
JC PACK1
RET
;
; READ AND WRITE DIRECTORY ROUTINES
;
RDDIR:
CALL EPRINT
DB ' --> Reading, ',0
XRA A
STA NOBOOT ;ZERO THE FLAG
JMP DODIR ;ZERO THE WRITE FLAG FOR NOW
;
; COME HERE IF WE GET A READ ERROR
;
RERROR:
CALL EPRINT ;PRINT:
DB ' READ ERROR - No Change Made',0
JMP EXIT
;
; DIVIDE HL BY 2
;
ROTRHL:
ORA A ;CLEAR CARRY
MOV A,H
RAR
MOV H,A
MOV A,L
RAR
MOV L,A
RET
;
; SETUP FOR SELECTING DRIVE AND LOADING DISK PARM BLOCK
;
SETUP:
LXI D,FCB
CALL Z3LOG ;LOG INTO DISK SPECIFIED BY USER
MVI C,GETDSK ;OTHERWISE GET CURRENT DEFAULT DRIVE
CALL BDOS ;SO QUERY 'BDOS' FOR DRIVE
MOV C,A ;PREP FOR OBTAINING DPB
CALL EPRINT
DB CR,LF,' Disk ',0
MOV A,C ;GET DISK NUMBER
ADI 'A' ;CONVERT TO ASCII
CALL COUT
CALL SELDSK
;
; GET CP/M 2.2 DPB DATA
;
MOV E,M
INX H
MOV D,M
INX H
XCHG
SHLD SECTBL
XCHG
LXI D,8 ;OFFSET TO DPB WITHIN HEADER
DAD D ;RETURNED BY SELDSK IN CPM2
MOV A,M ;GET ADRS OF DPB
INX H
MOV H,M
MOV L,A
LXI D,DPB ;POINT TO DEST: OUR DPB
MVI B,DPBLEN
CALL MOVE
RET
;
; SORT THE DIRECTORY
;
SORT:
CALL EPRINT
DB 'Sorting (',0
LDA REVERSE ;INDICATE ASC OR DSC
ORA A ;0=ASC
JZ SORTASC
CALL EPRINT
DB 'Descending',0
JMP SORTDO
SORTASC:
CALL EPRINT
DB 'Ascending',0
;
; SHELL-METZNER SORT
;
SORTDO:
CALL EPRINT
DB ' Order), ',0
LHLD I
SHLD SNUMRECW
LHLD BUF
SHLD SSTADR
PUSH H ; AND SAVE IT
LXI H,32
SHLD SRECLEN
PUSH H ; AND SAVE IT
;
; NOW DIVIDE # OF FIELDS BY 2
;
DIVIDE:
LHLD SNUMRECW ;GET VALUE
CALL ROTRHL
SHLD SNUMRECW ;SAVE RESULT
MOV A,L ;IF SNUMRECW<>0
ORA H ; THEN
JNZ NOTDONE ; NOT DONE
;
; ALL FIELDS SORTED
;
POP B ;CLEAN UP STACK
POP D
RET
;
NOTDONE:
XCHG
LHLD I
MOV A,L
SUB E
MOV L,A
MOV A,H
SBB D
MOV H,A
SHLD SRECLEN
LXI H,1
SHLD SSORTV1
SHLD SSTADR
DCR L
POP B
PUSH B
NDONE1:
DAD D
DCX B
MOV A,B
ORA C
JNZ NDONE1
SHLD SSORTV2
XCHG
POP B
POP H
PUSH H
PUSH B
NDONE2:
SHLD SSORTV4
SHLD SSORTV3
XCHG
DAD D
XCHG
COMPARE:
POP B
PUSH B
COMPAR1:
LDAX D
ANI 7FH
PUSH B
MOV C,A
MOV A,M
ANI 7FH
MOV B,A
MOV A,C
SUB B
POP B
JNZ NOTEQU
INX H
INX D
DCX B
MOV A,B
ORA C
JNZ COMPAR1
JMP NOSWITCH
;
; THE CONDITION AT NOTEQU: HAS TO
; BE CHANGED FOR DESCENDING SORT -- IF REVERSE=0, JNC TO NOSWITCH, ELSE
; JC TO NOSWITCH
;
NOTEQU:
PUSH PSW ;SAVE CONDITION
LDAX D ;GET (DE)
CPI 0E5H ;IF ERASED, SELECT ASCENDING
JZ ASCENDING
MOV A,M ;GET (HL)
CPI 0E5H ;IF ERASED, SELECT ASCENDING
JZ ASCENDING
LDA REVERSE ;DESCENDING SORT?
ORA A ;0=NO
JZ ASCENDING
POP PSW ;GET CONDITION FOR DESCENDING SORT
JC NOSWITCH
JMP SWITCH
ASCENDING:
POP PSW ;GET CONDITION FOR ASCENDING SORT
JNC NOSWITCH
SWITCH:
PUSH B
MOV B,M
LDAX D
MOV M,A
MOV A,B
STAX D
INX H
INX D
POP B
DCX B
MOV A,B
ORA C
JNZ SWITCH
LHLD SNUMRECW
MOV A,H
CMA
MOV D,A
MOV A,L
CMA
MOV E,A
LHLD SSORTV1
DAD D
JNC NOSWITCH
INX H
SHLD SSORTV1
LHLD SSORTV3
XCHG
LHLD SSORTV2
MOV A,E
SUB L
MOV L,A
MOV A,D
SBB H
MOV H,A
SHLD SSORTV3
JMP COMPARE
;
NOSWITCH:
LHLD SSTADR
INX H
SHLD SSTADR
SHLD SSORTV1
XCHG
LHLD SRECLEN
MOV A,L
SUB E
MOV A,H
SBB D
JC DIVIDE
LHLD SSORTV4
POP D
PUSH D
DAD D
XCHG
LHLD SSORTV2
XCHG
JMP NDONE2
;
; UTILITY SUBTRACTION SUBROUTINE...
; HL=HL-DE
;
SUBDE:
MOV A,L
SUB E
MOV L,A
MOV A,H
SBB D
MOV H,A
RET
;.....
;
;
WRDIR:
CALL EPRINT
DB 'Writing, ',0
MVI A,1
JMP DODIR
;
; COME HERE IF WE GET A WRITE ERROR
;
WERROR:
CALL EPRINT ;PRINT:
DB ' WRITE ERROR - Directory Left in UNKNOWN Condition',0
JMP EXIT
;
; DATA AREA
;
ADDR:
DS 2
BUF:
DS 2
DIRCNT:
DS 2
I:
DS 2
J:
DS 2
MAPPTR:
DS 2
maxdir:
ds 2 ;841201
NOBOOT:
DS 1
NOSWAP:
DS 1
REVERSE:
DS 1
SECTBL:
DS 2
SECTOR:
DS 2
TRACK:
DS 2
WRFLAG:
DS 1
SRECLEN:
DS 2
SSTADR:
DS 2
SSORTV1:
DS 2
SSORTV2:
DS 2
SSORTV3:
DS 2
SSORTV4:
DS 2
SNUMRECW:
DS 2
;
; DISK PARAMETER BLOCK:
;
DPB:
SPT:
DS 2
BSH:
DS 1
BLM:
DS 1
EXM:
DS 1
DSM:
DS 2
DRM:
DS 2
AL0:
DS 1
AL1:
DS 1
CKS:
DS 2
SYSTRK:
DS 2
;
STACK:
DS 2 ;SPACE FOR OLD STACK ADDRESS
;
END
;