; SAPP v52 SORT AND PACK CP/M DISK DIRECTORY -- 07/01/85 ; ; v52 07-01-85 (DJM P*PS) ; 1. Fixed unbalanced stack in dodate which caused ; eratic exit behaviour in some circumstances ; 2. Minor tidy up of some comments and exit ; ; v51 02-23-85 ; 1. Preserved original attributes of '!!!TIME&.DAT' file ; ; v50 11/13/84 ; 1. Added support for DateStamper time-and-date file, if ; present on disk. The datestamp entries are ; rewritten in the new directory order, with updated ; checksums. ; 2. New, faster sort routine swaps pointers rather than ; directory entries. ; 3. Directory writes speeded up by flushing only the final ; sector. ; 4. Zero-length files are erased only if confirmed by user. ; 5. Prompt for drive if no command line. ; 6. Erase temporary files of form 'filename.$$$' ; 7. Removed the 'PACK' routine. ; As written, it converted 'filename.n$$' extent=0 files ; to 'filename.$$$' extent=n-'0'. ; If the intent was to erase temporary files it should ; be done BEFORE sorting, as v 5.0 now does. ; 8. Note: not tested on cp/m 1.4 ; ; Bridger Mitchell (Plu*Perfect Systems) ; ;----------------------------------------------------------------------- ; ; 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 (horizontal) ; 2) eliminates potential problems with "UNERASE" programs ; 3) speeds 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) erases all files of zero length (except those starting ; with '-' for catalog use with MAST.CAT) ; ; - notes by Irv Hoff W6FFC ; ;======================================================================= ; ; 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. (SFK) ; ; 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. ; ;======================================================================= ; ; VERS EQU 52 ; ; BDOS EQU 0005H ; ; ; BDOS functions ; VERNO EQU 12 ; Provides CP/M version number RESET EQU 13 ; Bdos reset drives fn SELDRV EQU 14 ; Select drive fn OPEN EQU 15 CLOSE EQU 16 USERFN EQU 32 ; BDOS user function ATTFN EQU 30 GETDSK EQU 25 ; BDOS "get disk #" function DMAFN EQU 26 READFN EQU 20 WRITFN EQU 21 ; FCB EQU 5CH TBUFF EQU 80H ; BS EQU 08H CR EQU 0DH LF EQU 0AH JMP EQU 0C3H ; ; DPBLEN EQU 15 ; Size of CP/M 2.2 disk parameter block ; ; ORG 100H ; ; START: LXI SP,STACK ; Use our own stack LXI D,WBOOT ; Get bios vector LHLD 0001H MVI B,16*3 ; DJM 7/1/85 CALL MOVE CALL ILPRT DB CR,LF,'SAP v ' DB VERS/10 +'0',(VERS MOD 10) +'0' ; VERDAT: DB ' 07/01/85',CR,LF,LF DB 'Sort and Pack Directory -- ' DB 'with DateStamper(TM) support.',CR,LF,0 MVI C,VERNO ; Check for CP/M ver 2.2 CALL BDOS MOV A,H ; H=1 for MPM ORA A JNZ MPMYES ; Exit if MPM, we can't use it MOV A,L ; HL = 0022H if CP/M ver 2.2 CPI 22H+1 ; Check for MPM or CP/M 3.0 JNC MPMYES ; Exit if CP/M 3.0, we can't use it STA VERFLG ; ; ;----------------------------------------------------------------------- ; ; MAIN PROGRAM ; ;----------------------------------------------------------------------- ; SAP: CALL SETUP CALL TSTWRT CALL RDDIR CALL CLEAN CALL SORT CALL WRDIR ; Write directory and DateStamper file CALL ILPRT DB '... Done.',CR,LF,0 ; EXIT: LDA O$DISK ; Restore login status MOV E,A MVI C,SELDRV ; Sets bios drive too CALL BDOS LDA O$USER MOV E,A ; S8: MVI C,USERFN CALL BDOS RST 0 ; Warm boot - required after ; Change in directory checksum ; ;----------------------------------------------------------------------- ; ; INITIALIZATION ; ;----------------------------------------------------------------------- ; ; Setup for selecting drive and loading disk parm block ; SETUP: XRA A STA CLEANFLG MVI C,USERFN ; Save original drive & user number MVI E,0FFH CALL BDOS STA O$USER MVI C,GETDSK CALL BDOS STA O$DISK STA CURDSK LDA FCB ORA A JNZ SETUP1 ; ; ; Prompt for drive before proceeding ; REASK: CALL ILPRT DB CR,LF,'Which drive ?',BS,0 CALL CI CPI 'C'-'@' ; Abort on ^C bailout JZ 0 ANI 5FH PUSH PSW CALL AOUT POP PSW ; STUP0: SUI 'A'-1 ; SETUP1: DCR A STA CURDSK CPI 0 JC BADDRV CPI 16 JC LOGIT ; BADDRV: MVI C,7 CALL AOUT JMP REASK ;..... ; ; LOGIT: MOV E,A ; Login designated drive thru BDOS MVI C,SELDRV CALL BDOS MVI E,0 ; Set user 0 MVI C,USERFN CALL BDOS LDA CURDSK ; BIOS call to get DPH to HL MOV C,A CALL SELDSK LDA VERFLG ; If CP/M 1.4 ORA A JZ DO14 ; If 1.4, then do it the 1.4 way CALL CPM22 JMP SETUP2 ;..... ; ; DO14: CALL CPM14 ; SETUP2: LHLD DRM ; Number of directory entries INX H ; Relative to 1 SHLD SCOUNT PUSH H DAD H ; Allocate 2*#dir entries LXI D,ORDER ; For pointer words DAD D SHLD BUFBASE POP H PUSH H CALL ROTRHL ; Divide by 4 CALL ROTRHL ; To get record count SHLD DIRLEN CALL ROTRHL ; And by 8 for time&date SHLD TDCNT ; ; ; ; Check for sufficient memory-- ; POP H ; # entries *32 DAD H DAD H DAD H DAD H DAD H XCHG LHLD BUFBASE ; + BUFBASE DAD D XCHG LHLD 6 ; - available TPA CALL SUBDE RNC CALL ILPRT DB CR,LF,7,'Insufficient memory!',0 JMP EXIT ;..... ; ; CPM22: MOV E,M ; CP/M 2.2 routine 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 JMP MOVE ;..... ; ; ; 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 ; ; ; Read & write 1st directory record to ensure writable disk ; TSTWRT: MVI C,RESET CALL BDOS CALL SETCUR LHLD SYSTRK CALL DOTRAK LXI H,1 CALL DOREC LXI H,TBUFF MOV B,H MOV C,L CALL SETDMA CALL READ ORA A JNZ RTERR MVI C,1 ; Directory write forces flush CALL WRITE ORA A JNZ WTERR CALL CKTD ; See if special DateStamper file is on disk RET ;..... ; ; WTERR: CALL ILPRT DB CR,LF,7,'Can''t write disk -- ' DB 'check write-protect tab',0 RET ;..... ; ; RTERR: CALL ILPRT DB CR,LF,7,'Can''t read disk',0 RET ; ;----------------------------------------------------------------------- ; ; READ & WRITE DIRECTORY ; ;----------------------------------------------------------------------- ; ; Write directory ; WRDIR: LDA NOSWAP ORA A JNZ WRDIR1 CALL ILPRT DB '(Previously sorted) ',0 LDA CLEANFLG ; If in sorted order ORA A ; And no erasures RZ ; We're all done ; WRDIR1: CALL ILPRT DB CR,LF,' ---> Writing, ',0 ; WRDIR2: CALL DMA80 ; Set default dma LHLD DIRLEN SHLD DIRCNT LXI H,ORDER ; Set initial pointer SHLD PTR MVI A,1 ; Flag write operation CALL DODIR CALL DODATE ; Then update the DateStamper file RET ;..... ; ; ; Read directory ; RDDIR: CALL ILPRT DB CR,LF,'---> Reading, ',0 LHLD DIRLEN SHLD DIRCNT LHLD BUFBASE SHLD ADDR ; For read DMA address LXI H,ORDER SHLD PTR MVI A,0 ; Readflg ; DODIR: STA WRFLAG LHLD SYSTRK CALL DOTRAK ; Set the track LXI H,0 SHLD RECORD ; DLOOP: 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 LDA WRFLAG ; Time to figure out ORA A ; If we are reading JNZ DWRT ; Or writing ; ; ; Reading ; LHLD ADDR MOV B,H ; Set up DMA address MOV C,L CALL SETDMA CALL READ ORA A ; Test flags on read JNZ RERROR ; NZ=error LHLD ADDR MVI B,4 ; Install ptrs for 4 entries in this rec. XCHG LHLD PTR ; PLP: MOV M,E INX H MOV M,D INX H PUSH H LXI H,32 DAD D XCHG POP H DCR B JNZ PLP SHLD PTR XCHG SHLD ADDR ; New dma ; ; ; Common r/w code ; MORE: LHLD DIRCNT ; Countdown entries DCX H SHLD DIRCNT MOV A,H ; Test for zero left ORA L JNZ DLOOP ; Loop till zero ; ; ; Directory I/O done, reset DMA address ; DMA80: LXI B,TBUFF JMP SETDMA ;..... ; ; ; Write-directory code ; DWRT: MVI B,4 LXI D,TBUFF ; DWRT1: PUSH B ; Copy 4 sorted entries to buffer CALL NXTENT CALL MOVE32 POP B DCR B JNZ DWRT1 MVI C,0 ; Write allocated... LHLD DIRCNT DCX H MOV A,H ORA L JNZ DWRT3 ; Unless it's the last record MVI C,1 ; Which must be flushed ; DWRT3: CALL WRITE ORA A JNZ WERROR JMP MORE ;..... ; ; ; Return HL = pointer to next sorted entry ; NXTENT: PUSH D LHLD PTR MOV E,M INX H MOV D,M INX H SHLD PTR XCHG POP D RET ;..... ; ; ; Track and record update routines ; DOTRAK: SHLD TRACK MOV B,H MOV C,L JMP SETTRK ;..... ; ; DOREC: SHLD RECORD MOV B,H MOV C,L LHLD RECTBL XCHG DCX B CALL RECTRN MOV B,H MOV C,L LDA VERFLG ORA A RZ JMP SETREC ;..... ; ; ;----------------------------------------------------------------------- ; ; CLEAN OUT ERASED ENTRIES ; Also any zero-length files, if affirmed by user. ; Preserve '-' zero-length (catalog) filenames. ; ;----------------------------------------------------------------------- ; CLEAN: LXI H,0 ; I = 0 ; CLNLOP: SHLD I CALL INDEX ; HL = BUF + 32 * I MOV A,M ; Jump if this is a deleted file CPI 0E5H JZ FILLE5 MOV B,H ; Save index in BC MOV C,L LXI D,9 ; If filetype is '$$$' DAD D MVI A,'$' CMP M JNZ CLN1 INX H CMP M JNZ CLN1 INX H CMP M JZ FILLE5 ; Erase it ; CLN1: LXI H,12 DAD B 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 ; Keep any files beginning with '-' CALL INDEX 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 PUSH H ; For other 0-length files... CALL ILPRT ; Ask for confirmation before erasing DB CR,LF,'Erase zero-length file: ',0 LDA CURDSK ADI 'A' CALL AOUT POP H PUSH H ; +1 MOV A,M CPI 10 JC ONES PUSH PSW ADI '0'-10 CALL AOUT POP PSW ; SULP: SUI 10 JP SULP ADI 10 ; ONES: ADI '0' CALL AOUT MVI A,':' CALL AOUT POP H PUSH H ; +1 INX H CALL FNFT CALL ILPRT DB ' ?',BS,0 CALL CI CPI 'Y' POP H ; +0 JZ YESANS CPI 'y' JZ YESANS MVI A,'N' CALL AOUT JMP CLBUMP ;..... ; ; YESANS: CALL AOUT ; FILLE5: LHLD I ; Recompute entry address CALL INDEX MVI C,32 ; Number of bytes to clear MVI A,0E5H ; FILLE6: CMP M JNZ FILLE7 INX H DCR C JNZ FILLE6 JMP CLBUMP ; Already clean ;..... ; ; FILLE7: STA CLEANFLG ; FILLOP: MOV M,A ; 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 ;..... ; ; ; Type 'FILENAME.TYP' at (HL) ; FNFT: MVI B,8 CALL TYPEFN MVI A,'.' CALL AOUT MVI B,3 ; TYPEFN: PUSH B MOV A,M CALL AOUT INX H POP B DCR B JNZ TYPEFN RET ;..... ; ; AOUT: PUSH B PUSH H MOV C,A CALL CO POP H POP B RET ;..... ; ; ; Print a string: Address is on top of stack, preserves BC ; 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 CALL AOUT ; Preserves hl,bc JMP ILPRT ; Continue ;..... ; ; INDEX: DAD H ; *32 DAD H DAD H DAD H DAD H XCHG LHLD BUFBASE DAD D RET ;..... ; ; MOVE16: MVI B,16 JMP MOVE ; MOVE32: MVI B,32 ; ; ; Move (B) bytes from (HL) to (DE) ; MOVE: MOV A,M STAX D INX H INX D DCR B JNZ MOVE RET ;..... ; ; ;----------------------------------------------------------------------- ; ; Sort the directory ; ;----------------------------------------------------------------------- ; SORT: XRA A STA NOSWAP ; Zero the flag in case already sorted CALL ILPRT DB CR,LF,' ---> Sorting, ',0 ; ; ; This sort routine is adapted from SOFTWARE TOOLS by Kernigan and ; Plaugher. Routine extracted from SD. ; LHLD SCOUNT ; Number of entries LDA TDFLAG ORA A JZ L0 DCX H ; Skip past TIME&DAT entry SHLD SCOUNT ; L0: ORA A ; Clear carry MOV A,H ; GAP=GAP/2 RAR MOV H,A MOV A,L RAR MOV L,A ORA H ; Is it zero? RZ ; Then none left MOV A,L ; Make gap odd ORI 1 MOV L,A SHLD GAP INX H ; I=GAP+1 ; L2: SHLD I XCHG LHLD GAP MOV A,E ; J=I-GAP SUB L MOV L,A MOV A,D SBB H MOV H,A ; L3: SHLD J XCHG LHLD GAP ; JG=J+GAP DAD D SHLD JG CALL COMPARE ; Compare (J) and (JG) ; L3A: JP L5 ; If A(J)<=A(JG) LHLD J XCHG LHLD JG CALL SWAP ; Exchange A(J) and A(JG) LHLD J ; J=J-GAP XCHG LHLD GAP MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A JM L5 ; If J>0 GOTO L3 ORA L ; Check for zero JNZ L3 ; * shortened ; L5: LHLD SCOUNT ; For later XCHG LHLD I ; I=I+1 INX H MOV A,E ; If I<=N GOTO L2 SUB L MOV A,D SBB H JP L2 LHLD GAP JMP L0 ;..... ; ; ; Returns SIGNED comparison ; COMPARE:CALL GETBAS DAD H ; *2 DAD B ; +base XCHG ; 1st pointer to DE DAD H DAD B XCHG ; 2nd to HL MOV C,M ; Fetch 1st to BC INX H MOV B,M XCHG ; Fetch 2nd to HL MOV E,M INX H MOV D,M XCHG ; ; ; Should be 1+11+ext - sort by userno,NAME,TYPE,extent ; MVI E,13 ; COMPBH: MOV A,M ; 7-bit signed compare of (BC), (HL) ANI 7FH MOV D,A LDAX B ANI 7FH CMP D INX B INX H RNZ DCR E JNZ COMPBH RET ;..... ; ; Swap entries in the order table ; SWAP: MVI A,0FFH STA NOSWAP CALL GETBAS DAD H ; *2 DAD B ; + base XCHG DAD H ; *2 DAD B ; + base MOV C,M LDAX D XCHG MOV M,C STAX D INX H INX D MOV C,M LDAX D XCHG MOV M,C STAX D RET ;..... ; ; GETBAS: LXI B,ORDER-2 ; If TIME&DAT file LDA TDFLAG ORA A RZ INX B ; Start at 2nd entry INX B RET ;..... ; ; ;----------------------------------------------------------------------- ; ; DATESTAMPER SUPPORT CODE ; ; 1. checks for presence of DateStamper(TM) file ; 2. re-writes time and date entries in sorted order ; corresponding to the new directory order. ; ;----------------------------------------------------------------------- ; ; Check 1st directory entry for "TIME&.DAT" file ; CKTD: LXI H,TDNAM0 ; User # 0 too MVI B,12 PUSH H PUSH B LXI D,TDFCB ; Initialize userno,name in fcb now CALL MOVE XRA A MVI B,36-12 ; ZLP: STAX D INX D DCR B JNZ ZLP POP B POP H LXI D,TBUFF ; See if it's the time&dat file CALL MATCH7 ; JNZ NOTD MVI A,0FFH JMP SETTD ; NOTD: XRA A ; SETTD: STA TDFLAG ; Set flag if special file present RET ;..... ; ; ; Rewrite the TIME&DAT file in sorted order ; 1. read the file to (bufbase) ; 2. use ptrs to index to each 16-byte entry ; 3. write new records ; DODATE: LDA TDFLAG ORA A RZ ; No TIME&DAT file MVI C,RESET ; Directory has been changed CALL BDOS ; Force new checksum in bdos CALL SETCUR ; ; ; 1. open file to get all attributes ; 2. reset R/O bit ; LXI D,TDFCB PUSH D MVI C,OPEN CALL BDOS INR A POP D JZ TDOERR LXI H,TDFCB+9 ; Set file r/w MOV A,M ANI 7FH MOV M,A MVI C,ATTFN CALL BDOS ; DOD1: MVI B,0 ; Record counter LHLD BUFBASE ; TDRLP: XCHG PUSH D PUSH B MVI C,DMAFN CALL BDOS LXI D,TDFCB MVI C,READFN CALL BDOS ORA A POP B POP D JNZ RDDONE INR B LXI H,80H DAD D JMP TDRLP ;..... ; ; RDDONE: LHLD BUFBASE ; ; Check the checksum for all records ; CKLP: PUSH B CALL CKSUM CMP M INX H POP B JZ SOK CALL ILPRT DB CR,LF,'Checksum error in original "!!!TIME&.DAT" file' DB ' -- proceeding',0 ; SOK: DCR B JNZ CKLP ; ; ; Initialize for writing ; XRA A STA TDFCB+12 ; Extent STA TDFCB+32 ; Currec CALL DMA80 LXI H,ORDER ; Initialize ptr SHLD PTR LHLD TDCNT ; WTLP1: PUSH H ; ; ; Copy 8 time&date entries to TBUFF ; LXI D,TBUFF MVI B,8 ; WTLP2: PUSH B ; +1 PUSH D ; +2 LHLD PTR ; Get ptr to next entry MOV E,M INX H MOV D,M INX H SHLD PTR ; Save next ptr ; ; ; DateStamper entries are 16 bytes ; LHLD BUFBASE ; Get: BUFBASE + [(PTR)-BUFBASE]/2 PUSH H XCHG CALL SUBDE ; (PTR)-BUFBASE CALL ROTRHL ; /2 POP D ; + BUFBASE DAD D ; POP D ; Move it to TBUFF CALL MOVE16 ; De points to next slot in TBUFF POP B ; +0 DCR B JNZ WTLP2 LXI H,TBUFF ; Update the record's checksum byte CALL CKSUM MOV M,A LXI D,TDFCB ; Write the record MVI C,WRITFN ; DBUG: CALL BDOS ORA A POP H JNZ TDWERR DCX H ; Count down MOV A,H ORA L JNZ WTLP1 LXI D,TDFCB ; Close TIME&DAT file PUSH D MVI C,CLOSE CALL BDOS POP D INR A JZ TDCERR LXI H,TDFCB+9 ; Return file to R/O status MOV A,M ORI 80H MOV M,A MVI C,ATTFN JMP BDOS ;..... ; ; Check-sum 1st 127 bytes at (HL) ; CKSUM: MVI B,127 XRA A ; CKSU1: ADD M INX H DCR B JNZ CKSU1 RET ;..... ; ; TDNAM0: DB 0,'!!!TIME&DAT' ; TDOERR: CALL ILPRT DB CR,LF,7,'Can''t open',0 ; FNERR: CALL ILPRT DB ' "!!!TIME&.DAT" file!',CR,LF,0 RET ;..... ; ; TDWERR: CALL ILPRT DB CR,LF,7,'Write error',0 JMP FNERR ;..... ; ; TDCERR: CALL ILPRT DB CR,LF,7,'Close error',0 JMP FNERR ;..... ; ; ;----------------------------------------------------------------------- ; ; MISCELLANEOUS SUPPORT ROUTINES ; ;----------------------------------------------------------------------- ; SETCUR: LDA CURDSK MOV E,A ; Put drive back MVI C,SELDRV JMP BDOS ;..... ; ; ; Compare B bytes at DE and HL - (W/O attributes ) ; MATCH7: LDAX D XRA M ANI 7FH ; Ignore attributes RNZ INX H INX D DCR B JNZ MATCH7 RET ;..... ; ; ; Utility subtraction subroutine...HL = HL-DE ; SUBDE: MOV A,L SUB E MOV L,A MOV A,H SBB D MOV H,A RET ;..... ; ; ; Divide HL by 2 ; ROTRHL: ORA A ; Clear carry MOV A,H RAR MOV H,A MOV A,L RAR MOV L,A RET ;..... ; ; ; Come here if we get a read error ; RERROR: CALL ILPRT DB '++ READ ERROR - NO CHANGE made' DB CR,LF,0 JMP EXIT ;..... ; ; ; Come here if we get a write error ; WERROR: CALL ILPRT DB '++ WRITE ERROR - ' DB 'directory left in UNKNOWN condition',CR,LF,0 JMP EXIT ;..... ; ; ; M/PM OR CP/M 3.0 not allowed with this program ; MPMYES: CALL ILPRT DB CR,LF,'SAP ' DB VERS/10 +'0','.',(VERS MOD 10) +'0' DB ' not useable with M/PM or CP/M 3.0',0 JMP EXIT ;..... ; ; ; Data area ; ADDR: DS 2 DIRLEN: DS 2 DIRCNT: DS 2 I: DS 2 J: DS 2 GAP: DS 2 JG: DS 2 RECTBL: DS 2 RECORD: DS 2 TRACK: DS 2 TDCNT: DS 2 NOSWAP: DS 1 VERFLG: DS 1 WRFLAG: DS 1 TDFLAG: DS 1 CLEANFLG: DS 1 ; ; ; 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 CURDSK: DS 1 O$DISK: DS 1 O$USER: DS 1 BUFBASE:DS 2 PTR: DS 2 SCOUNT: DS 2 ; TDFCB: DS 36 ; DateStamper file control block ;..... ; ; VECTRS: DS 17*3 ; 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 ; can increase stack area greatly ; ORG EVEN ; STACK EQU $-2 ; ORDER: DS 0 ; ; END