home *** CD-ROM | disk | FTP | other *** search
- ; SAP v44 -- Sort & Pack directory 07/25/85
- ;
- ASEG ; needed for M80, ignore error if using MAC
- ;
- ; THIS PROGRAM READS THE DISK DIRECTORY TRACKS, SORTS THEM ALPHABETICALLY
- ; THEN REPLACES THEM ON THE DISK. ALL UNUSED OR ERASED AREAS ON THE DI-
- ; RECTORY 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 'DU', ETC.
- ; 5) REMOVES FILES FROM THE DISK SOMEBODY ELSE COULD RECOVER
- ; 6) OPTIONALLY ERASES ALL FILES OF ZERO LENGTH (EXCEPT THOSE
- ; STARTING WITH '-' FOR CATALOG USE WITH MAST.CAT)
- ;
- ; - Notes by Irv Hoff W6FFC
- ;
- ;=======================================================================
- ;
- ; 07/25/85 Added some pushes and pops so that the switch routine will
- ; v44 swap the entire contents of the two directory entries.
- ; Previously it only swapped the part after it found a difference
- ; which sometimes resulted in flag bits moving from one file
- ; to another. - Bob Clyne
- ;
- ; 03/20/85 Inserted my name where it belonged under the v42 release
- ; v43 notice, added conditional assembly option for verbose mode
- ; which will, if selected, permit the program to assemble in
- ; under 1k. Added conditional assembly option for CP/M-only
- ; mode which suppresses check for MP/M and CP/M+.
- ; - Dennis Quinn
- ;
- ; 03/06/85 Removed "trash directory" feature to make program more user-
- ; v42 friendly, made "delete zero-length files" an assembly-time
- ; option, as there are more programs than MCAT which make use
- ; of zero-length files. - Dennis Quinn (added in v43)
- ;
- ; 02/28/85 Minor cleanup, made compatible with all assemblers.
- ; v41 - Irv Hoff
- ;
- ; 09/17/84 Added 'Previously sorted' statement that was included in v37
- ; v40 but got dropped from v38 when the Shell-Metnzer sort was put
- ; in. It still rewrites the directory even if previously
- ; sorted, to insure erased programs at end of directory are
- ; properly cleared. - Irv Hoff
- ;
- ; 07/27/84 Corrected sorting of last directory entry.
- ; v39 - WOD
- ;
- ; 10/16/83 Now using a Shell-Metzner sort which speeds the sorting time
- ; v38 considerably, especially on large directories.
- ; - Sigi Kluger
- ;
- ; 07/27/83 Shows an error flag for MP/M and CP/M+ both. Rewrites the
- ; v37 directory even if previously sorted, to insure erased pro-
- ; grams at end of directory are properly cleared.
- ; - Irv Hoff
- ;
- ; 1977 Written by L. E. Hughes. Modified extensively since by Bruce
- ; Ratoff, Keith Petersen, James Prest, Ron Fowler, Frank Gaude,
- ; Sigi Kluger, Irv Hoff and likely others.
- ;
- ;=======================================================================
- ;
- NO EQU 0
- YES EQU NOT NO
- ;
- ;=======================================================================
- ;
- ; User-customizable options:
- ;
- VERBOSE EQU YES ; Set this to YES to force full-length messages
- ; as in SAP40), NO to minimize message length.
-
- ONLY22 EQU NO ; Set this to YES if SAP will be running ONLY
- ; under CP/M v2.2. If not sure, set to NO.
-
- ONLY14 EQU NO ; Set this to YES if SAP will be running ONLY
- ; under CP/M v1.4. If not sure, set to NO.
-
- CPMONLY EQU NO ; Set this to YES if SAP will be running ONLY
- ; under CP/M, either v1.4 or 2.2 If possi-
- ; bility exists that SAP might be executed
- ; under MP/M or CP/M+, set to NO.
-
- DELZRO EQU NO ; Set this to YES to cause SAP to delete all
- ; zero-length files not beginning with "-" (as
- ; in SAP40). If no files are to be deleted
- ; solely on the basis of file size, set to NO.
-
- ;
- ; End of user-selected options
- ;=======================================================================
- ;
- ;
- UNSPECI EQU NOT (ONLY22 OR ONLY14)
- ;
- IF ONLY22 AND ONLY14
- ERROR 'You must set EITHER only22 or only14 to YES, not both'
- ENDIF
- ;
- BDOS EQU 0005H
- CR EQU 0DH
- DPBLEN EQU 15 ; Size of CP/M 2.2 disk parameter block
- FCB EQU 5CH
- GETDSK EQU 25 ; BDOS "get disk #" function
- LF EQU 0AH
- SELDRV EQU 14 ; Select drive
- VERNO EQU 12 ; Provides CP/M version number
- ;
- ;
- ORG 100H
- ;
- ;
- ; Obtain BIOS vectors
- ;
- GETVEC: LXI D,WBOOT
- LHLD 0001H
- MVI B,53
- CALL MOVE
- ;
- START: LXI SP,STACK ; Use our own stack
- CALL ILPRT
- ;
- IF VERBOSE
- DB CR,LF,'SORT AND PACK DIRECTORY v'
- ENDIF ; VERBOSE
- ;
- IF NOT VERBOSE
- DB 'SAP v'
- ENDIF ; NOT VERBOSE
- ;
- DB '44 07/25/85'
- DB CR,LF,0
- ;
- IF UNSPECI
- MVI C,VERNO ; Check for CP/M ver 2.2
- CALL BDOS
- ENDIF ; UNSPECI
- ;
- IF UNSPECI AND (NOT CPMONLY)
- DCR H ; H=1 for MPM
- JZ MPMYES ; Exit if MPM, we can't use it
- MOV A,L ; HL = 0022H if CP/M ver 2.2
- CPI 30H ; Check for MPM or CP/M 3.0
- JNC MPMYES ; Exit if CP/M 3.0, we can't user it
- ENDIF ; UNSPECI AND (NOT CPMONLY)
- ;
- IF UNSPECI
- STA VERFLG ; Store the version
- ENDIF
- ;
- ;
- ;=======================================================================
- ;
- ; Main program routine
- ;
- SAP: CALL SETUP
- CALL RDDIR
- CALL CLEAN
- CALL SORT
- CALL PACK
- CALL WRDIR
- CALL ILPRT
- ;
- IF VERBOSE
- DB 'Done'
- ENDIF
- ;
- DB CR,LF,0
- JMP EXIT
- ;
- ;
- ;=======================================================================
- ; 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 FILL$E5
- ;
- IF DELZRO
- LXI D,12
- DAD D ; HL = HL + 12
- MOV A,M ; Check extent field
- ORA A
- JNZ CLBUMP ; Skip if not extent 0
- INX H ; Point to record count field
- INX H
- MOV A,M ; Get S2 byte (extended RC)
- ANI 0FH ; For CP/M 2.2, 0 for CP/M 1.4
- 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 character of filename
- DCX H ; MAST.CAT catalog programs
- CPI '-' ; Have diskname of zero length
- JZ CLBUMP ; That start with '-', do not delete
- ENDIF ; DELZRO
- ;
- IF NOT DELZRO
- JMP CLBUMP ; Don't delete this file
- ENDIF ; NOT DELZRO
- ;
- 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
- ;
- IF ONLY14 OR UNSPECI
- ;
- ;
- ; CP/M 1.4 routine
- ;
- CPM14: LHLD BDOS+1
- MVI L,0
- MVI A,(JMP)
- STA RECTRN
- PUSH H
- LXI D,15 ; RECTRAN offset from BDOS in CP/M 1.4
- DAD D
- SHLD RECTRN+1
- POP H
- LXI D,3AH ; Offset from BDOS to 1.4 DPB
- DAD D
- MVI D,0
- MOV E,M
- INX H
- XCHG
- SHLD SPT
- XCHG
- MOV E,M
- INX H
- XCHG
- SHLD DRM
- XCHG
- MOV A,M
- INX H
- STA BSH
- MOV A,M
- INX H
- STA BLM
- MOV E,M
- INX H
- XCHG
- SHLD DSM
- XCHG
- MOV E,M
- INX H
- XCHG
- SHLD AL0
- XCHG
- MOV E,M
- XCHG
- SHLD SYSTRK
- RET
- ENDIF
- ;
- ;
- ; CP/M 2.2 routine
- ;
- IF ONLY22 OR UNSPECI
- CPM22: MOV E,M
- INX H
- MOV D,M
- INX H
- XCHG
- SHLD RECTBL
- XCHG
- LXI D,8 ; Offset to DPB within header
- DAD D ; Returned by seldsk in CP/M 2.2
- MOV A,M ; Get adrress of DPB
- INX H
- MOV H,M
- MOV L,A
- LXI D,DPB ; Point to destestination: our DPB
- MVI B,DPBLEN
- CALL MOVE
- RET
- ENDIF ; ONLY22 OR UNSPECI
- ;
- DODIR: STA WRFLAG
- LHLD SYSTRK
- CALL DOTRAK ; Set the track
- LXI H,0
- SHLD RECORD
- LHLD DRM ; Number of directory entries
- INX H ; Relative to 1
- CALL ROTRHL ; Divide by 4
- CALL ROTRHL ; To get record count
- SHLD DIRCNT
- LXI H,BUF
- SHLD ADDR ; For DMA address
- ;
- DIRLOP: LHLD RECORD ; Get records per track
- INX H
- XCHG
- LHLD SPT ; Current record
- CALL SUBDE ; Record - SPT
- XCHG
- JNC NOTROV
- ;
- ;
- ; Track overflow, bump to next
- ;
- LHLD TRACK
- INX H
- CALL DOTRAK
- LXI H,1 ; Rewind record number
- ;
- NOTROV: CALL DOREC ; Set current record
- 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 record update routines
- ;
- DOTRAK: SHLD TRACK
- MOV B,H
- MOV C,L
- CALL SETTRK
- RET
- ;
- DOREC: SHLD RECORD
- MOV B,H
- MOV C,L
- LHLD RECTBL
- XCHG
- DCX B
- CALL RECTRN
- MOV B,H
- MOV C,L
- ;
- IF UNSPECI
- LDA VERFLG
- ORA A
- RZ
- CALL SETREC
- RET
- ENDIF ; UNSPECI
- ;
- IF ONLY14
- RET
- ENDIF ; ONLY14
- ;
- IF ONLY22
- CALL SETREC
- RET
- ENDIF ; ONLY22
- ;
- ;
- ; Write
- ;
- DWRT: MVI C,1 ; For CP/M 2.2 deblocking BIOS's
- CALL WRITE
- ORA A ; Test flags on write
- JNZ WERROR ; NZ=bad directory write
- JMP MORE
- ;
- EXIT: JMP 0000H ; Go warm reboot
- ;
- ;
- ; Print a string: Address is on top of stack
- ;
- ILPRT: XTHL ; Get address from stack
- MOV A,M ; Get character
- INX H ; Point to next address
- XTHL ; Restore to stack
- ORA A ; Are we done?
- RZ ; Yes, return past string
- PUSH H ; In case CBIOS clobbers it
- MOV C,A ; Character to 'C' for CP/M
- CALL CO ; Print character
- POP H
- JMP ILPRT ; Continue
- ;
- INDEX: DAD H
- DAD H
- DAD H
- DAD H
- DAD H
- LXI D,BUF
- DAD D
- RET
- ;
- ;
- ; Good read or write
- ;
- MORE: LHLD ADDR ; Bump DMA address 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: 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'
- 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 ILPRT
- ;
- IF VERBOSE
- DB CR,LF,'---> Reading, ',0
- ENDIF ; VERBOSE
- ;
- IF NOT VERBOSE
- DB CR,LF,'Rd, ',0
- ENDIF ; NOT VERBOSE
- ;
- JMP DODIR ; Zero the write flag for now
- ;
- ;
- ; 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: LDA FCB
- DCR A
- JP SETUP1 ; Exit if disk drive mentioned
- MVI C,GETDSK ; Otherwise get current default drive
- CALL BDOS ; So query 'BDOS' for drive
-
- SETUP1: MOV C,A
- CALL SELDSK
- ;
- IF UNSPECI
- LDA VERFLG ; If CPL/M 1.4
- ORA A
- JZ CPM14 ; If 1.4, then do it the 1.4 way
- JMP CPM22 ; Must be 2.2 then since not MP/M
- ENDIF ; UNSPECI
- ;
- IF ONLY14
- JMP CPM14
- ENDIF ; ONLY14
- ;
- IF ONLY22
- JMP CPM22
- ENDIF ; ONLY22
- ;
- ;
- ; Sort the directory
- ;
- SORT: XRA A
- STA NOSWAP ; Zero the flag in case already sorted
- CALL ILPRT
- ;
- IF VERBOSE
- DB 'Sorting, ',0
- ENDIF ; VERBOSE
- ;
- IF NOT VERBOSE
- DB 'Srt, ',0
- ENDIF ; NOT VERBOSE
- ;
- ;
- ; Shell-Metzner sort
- ;
- LHLD I
- INX H
- SHLD SNUMRECW
- LXI H,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
- ;
- ;
- ; Not done yet
- ;
- NOTDONE:XCHG
- LHLD I
- INX H
- 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
- PUSH D ;Save addresses of the beginning of these
- PUSH H ;..2 directory entries.
- ;
- COMPAR1:LDAX D
- ANI 7FH
- PUSH B
- PUSH PSW
- MOV A,M
- ANI 7FH
- MOV B,A
- POP PSW
- 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
- ;
- NOTEQU: JNC NOSWITCH
- MVI A,1
- STA NOSWAP
- POP H ;Get back the addresses of the beginning of
- POP D ;..these 2 directory entries
- POP B ;..and the number of bytes.
- PUSH B ;Leave this on the stack.
- ;
- 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 NOSW1
- 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:
- POP H ;Clean up the stack.
- POP H ;..and again.
- NOSW1: 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: LDA NOSWAP
- ORA A
- JNZ WRDIR1
- CALL ILPRT
- ;
- IF VERBOSE
- DB '(Previously sorted) - ',0
- ENDIF ; VERBOSE
- ;
- IF NOT VERBOSE
- DB '(Prv std) ',0
- ENDIF ; NOT VERBOSE
-
- WRDIR1: CALL ILPRT
- ;
- IF VERBOSE
- DB 'Writing, ',0
- ENDIF ; VERBOSE
- ;
- IF NOT VERBOSE
- DB 'Wrt',0
- ENDIF ; NOT VERBOSE
- ;
- WRDIR2: MVI A,1
- JMP DODIR
- ;
- ;
- ; Come here if we get a read error
- ;
- RERROR: CALL ILPRT
- ;
- IF VERBOSE
- DB '++ READ ERROR - NO CHANGE made'
- ENDIF ; VERBOSE
- ;
- IF NOT VERBOSE
- DB '+ Rd err +'
- ENDIF ; NOT VERBOSE
- ;
- DB CR,LF,0
- JMP EXIT
- ;
- ;
- ; Come here if we get a write error
- ;
- WERROR: CALL ILPRT
- ;
- IF VERBOSE
- DB '++ WRITE ERROR - '
- DB 'directory left in UNKNOWN condition'
- ENDIF ; VERBOSE
- ;
- IF NOT VERBOSE
- DB '+ Wrt err +'
- ENDIF ; NOT VERBOSE
- ;
- DB CR,LF,0
- JMP EXIT
- ;
- ;
- ; M/PM OR CP/M 3.0 not allowed with this program
- ;
- IF UNSPECI AND (NOT CPMONLY)
- MPMYES: CALL ILPRT
- DB CR,LF,'SAP not useable with MP/M or CP/M 3.0',0
- JMP EXIT
- ENDIF ; UNSPECI AND (NOT CPMONLY)
- ;
- ;
- ; Data area
- ;
- ADDR: DS 2
- DIRCNT: DS 2
- I: DS 2
- J: DS 2
- MAPPTR: DS 2
- NOSWAP: DS 1
- RECTBL: DS 2
- RECORD: DS 2
- TRACK: DS 2
- VERFLG: DS 1
- 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
- ;
- VECTRS: 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
- SETREC EQU VECTRS+33
- SETDMA EQU VECTRS+36
- READ EQU VECTRS+39
- WRITE EQU VECTRS+42
- LSTS EQU VECTRS+45 ; Only in CP/M 2.2
- RECTRN EQU VECTRS+48 ; Only in CP/M 2.2
-
- DS 32 ; Minimum stack depth
- EVEN EQU ($+255)/256*256 ; Start buffer on even page, which also
- ; Increase stack area greatly
- ORG EVEN
- STACK EQU $-2
- BUF: DS 0
- ;
- END