home *** CD-ROM | disk | FTP | other *** search
- TITLE 'XDIR - CP/M DIRECTORY DISPLAY PROGRAM'
- ; - XDIR -
- ; BY S J SINGER
- ;MODIFICATIONS
- ; MAY 15, 1980 - ADDED SUPPORT FOR DRIVES A-D
- ; MAY 15, 1980 - CHANGED THE DISPLAY TO 18 LINES
- ; MAY 15, 1980 - FIXED BUG WITH DIR EXTENTS NOT BEING IN
- ; ORDER. IF A LARGER EXTENT CAME BEFORE
- ; EXTENT ZERO, THE PROGRAM WOULD LOOP INFINITELY.
- ; MAY 24, 1980 - CHANGED SO THAT DIR ENTRIES ARE READ VIA
- ; BDOS CALLS (011H AND 012H).
- ; MAY 24, 1980 - CHANGED SO THAT SPACE INFO IS GOTTEN IN
- ; ACCORDANCE WITH CP/M 2.0 AND ABOVE.
- ;
- ; XDIR IS A CPM UTILITY THAT DISPLAYS A DISK DIRECTORY IN A MORE
- ;READABLE FORM. THE DIRECTORY IS READ FROM THE SPECIFIED DISK, SORTED
- ;THEN DISPLAYED IN A 3 COLUMN FORMAT. BOTH THE FILE NAMES AND FILE SIZES
- ;IN 1 K GROUPS ARE DISPLAYED.
- ; THE PRESENT VERSION OF XDIR HAS CERTAIN MINOR LIMITATIONS WHICH
- ;MAY BE EASILY REMOVED IF THEY CAUSE PROBLEMS.
- ;
- ; 1. ONLY 54 FILES ARE DISPLAYED. THIS LIMIT IS SUFFICIENT FOR
- ; ALMOST ALL DISKS AND LEAVES ROOM ON THE SCREEN FOR EDITING.
- ; TO CHANGE THE NO OF LINES DISPLAYED, CHANGE THE LINES VARIABLE
- ; IN THE DATA ALLOCATION SECTION OF THE PROGRAM. FOR EXAMPLE
- ; TO DISPLAY A MAXIMUM OF 54 FILES CHANGE LINES TO 18.
- ;
- ; OCCASIONALLY THE FILE NAMES WILL BE DISPLAYED WITH THE FORMAT
- ;SCRAMBLED OR THE SPACE REMAINING ON THE DISK WILL NOT AGREE WITH THAT REPORTED
- ;BY THE STAT UTILITY. THIS ALMOST ALWAYS MEANS THE DISK DIRECTORY HAS BEEN
- ;MESSED UP SOMEHOW. USUALLY THE PROBLEM CAN BE CORRECTED BY COPYING ALL THE
- ;FILES TO ANOTHER DISK USING PIP.
- ; XDIR WAS ASSEMBLED USING THE NEW CP/M MACRO ASSEMBLER AND USES A LARGE
- ;NUMBER OF MACROS. THESE ARE CONTAINED IN A LIBRARY CALLED MACRO.LIB WHICH
- ;IS REQUIRED IF THE PROGRAM IS TO BE REASSEMBLED.
- ;
- ;
- ; COMMAND FORMAT
- ;
- ; XDIR DISPLAY DIRECTORY OF LOGGED DISK
- ; XDIR A DISPLAY DIRECTORY OF DISK A
- ; XDIR B DISPLAY DIRECTORY OF DISK B
- ; XDIR C DISPLAY DIRECTORY OF DISK C
- ; XDIR D DISPLAY DIRECTORY OF DISK D
- ;
- ;
- ; THE PROGRAM STARTS READING THE CP/M DIRECTORY UNTIL AN EOF OCCURS.
- ;AS IT READS EACH ENTRY, IT MAINTAINS A TABLE OF ALL FILES. THE TABLE CON-
- ;TAINS ONE ENTRY FOR EACH FILE FROM ITS LARGEST EXTENT. WHEN ALL FILES ARE
- ;IN THE TABLE, IT SORTS THEM USING QUICKSORT AND AN AUXILIARY ADDRESS TABLE.
- ;WHEN THE SORT COMPLETES, THE FILE TABLE IS PRINTED IN THE ORDER OF THE AUX
- ;ADDRESS TABLE AND CONTROL IS GIVEN BACK TO CP/M.
-
- ; * * * COMMON EQUATES * * *
- LINES EQU 18 ;LINES PER PAGE OF DISPLAY
- MAXDIR EQU 128 ;MAXIMUM NUMBER OF DIRECTORY ENTRIES
-
- MACLIB MACRO ;INCLUDE MACRO LIBRARY
- PAGE
- ;************************************************
- ;* PROGRAM INITIALIZATION *
- ;************************************************
-
- ORG 100H ;SET PROG START
- LXI H,0
- DAD SP ;GET OLD STACK POINTER
- SHLD OLDSTK ;SAVE IT
- LXI SP,NEWSTK ;LOAD NEW STACK POINTER
- ;
- ; START OF DIRECTORY ROUTINE READ IN GROUPS 0 AND 1 AND STORE
- ; DIRECTORY FILE NAMES NOT FLAGGED E5. IF EXTENT NOT ZERO STORE
- ; OVER PREVIOUS FILE NAME. TABLE OF POINTERS WILL BE BUILT IN PDIR
- ;
- DIR: DISKIO ?DRIVE
- STA NEWDRV
- LDA 81H
- ORA A ;CHECK IF INPUT BUFFER EMPTY
- JZ DDD
- LDA 82H ;CHECK NEW DRIVE (A-D)
- CPI 'A'
- JC DSKERR
- CPI 'D'+1
- JNC DSKERR
- SUI 'A' ;MAKE IT RELATIVE TO ZERO.
- STA NEWDRV ;SAVE IT.
- DDD: PRINT <CR,LF,LF,' DIRECTORY DRIVE - '>
- LDA NEWDRV ;LOGGED DISK
- ADI 'A'
- CHAROUT
- PRINT <CR,LF,LF>
- CALL FIXB ;RESTORE DRIVE.
-
- ; GET THE CURRENT DISK MAX VALUE.
- MVI C,01FH ;GET DPB ADR FROM CP/M.
- CALL 5
- SHLD DPBADR ;SAVE IT.
- LXI D,2 ;GET THE BSH.
- DAD D
- MOV A,M ;SAVE IT.
- STA DSKBSH
- MOV C,A ; AGAIN.
- INX H ;GET THE BLM FOR LATER.
- MOV A,M
- STA DSKBLM ;SAVE IT.
- MOV A,C ;CONVERT BSH TO REL SHIFT.
- SUI 3
- MOV C,A ;SAVE IT.
- INX H ;GET THE DSM.
- INX H
- MOV E,M
- INX H
- MOV D,M
- INX H
- XCHG
- INX H ;MAKE IT RELATIVE TO ONE.
- DCR C ;SHIFT MAX BY (C) TIMES.
- INR C
- JZ $+8
- DAD H
- DCR C
- JMP $-7
- SHLD MAXSTR ;SAVE VALUE.
-
- ; GET DIRECTORY SIZE.
- XCHG ;HL = DPBDRM
- MOV E,M
- INX H
- MOV D,M
- XCHG
- INX H ;MAKE IT RELATIVE TO ONE.
- LXI D,32-1 ;ROUND IT TO EVEN # OF K.
- DAD D
- HALF ;DIVIDE IT BY 32 (# IN 1K).
- HALF ;/4
- HALF ;/8
- HALF ;/16
- HALF ;/32
- SHLD DIRSIZ ;SAVE IT.
-
- ; ADJUST MAX SIZE BY DIRECTORY SIZE.
- LHLD MAXSTR
- DSUB DIRSIZ
- SHLD MAXSTR
-
-
- DIR2: XRA A
- STA COUNT ;COUNT OF DIRECTORY ENTRIES
-
- ; FILL PDIR,PDIR+(2*(MAXDIR+1)) ;ZERO DIR PTR TABLE
- LXI H,PDIR
- LXI D,2*(MAXDIR+1)
- MVI M,0
- INX H
- DCX D
- MOV A,E
- ORA D
- JNZ $-6
-
- LXI H,DIRBUF ;POINTS TO DIRECTORY BUFFER
- SHLD OUTB
- LXI H,PDIR ;POINTER TABLE
- SHLD IPOINT
- LDA NEWDRV
- MOV E,A
- DISKIO LOGIN ;LOG IN NEW DRIVE NO
- DIR4: LXI H,80H ;POINTS TO INPUT BUFFER
- SHLD INB
- MVI C,01AH ;ISSUE SET DMA.
- XCHG
- CALL 5
- MVI C,011H ;ISSUE DIR FIRST GET.
- LXI D,DIRFCB
- CALL 5
- JMP DIR6
-
- ; GET NEXT DIR BUFFER.
- DIR5:
- MVI C,012H
- CALL 5
- CPI 255 ;END OF DIR?
- JZ SORT ;...YES, GO SORT TABLE.
- ADD A ;CONVERT # TO DISP.
- ADD A
- ADD A
- ADD A
- ADD A
- ADI 80H ;ADD IN BUFFER ADDRESS.
- MOV L,A
- MVI H,0
- SHLD INB ;SAVE PTR.
-
- ; SEE IF EOF.
- DIR6: LHLD OUTB ;LOAD DESTINATION POINTER
- XCHG ;PUT IT IN DE
- LHLD INB ;LOAD SOURCE POINTER
- MVI A,0E5H ;FLAG BYTE
- CMP M ;TEST FIRST BYTE
- JNZ DIR8
- INX H
- CMP M ;TEST SECOND BYTE
- JZ SORT ;SORT DIRECTORY
- JMP DIR12A
-
-
- DIR8:
- ; IF ITS THE ZERO ENTRY, ADD IT TO TABLE.
- INX H
- SAVE H,D
-
- ; SCAN TABLE TO SEE IF AN EXTENT EXISTS FOR THE FILE.
- LXI H,0 ;SEARCH FOR SAME NAME AND SWITCH
- SHLD J ;INITIALIZE INDEX
- DIR9: DLOAD PDIR,J
- MOV A,H
- ORA L
- JZ DIR10 ;ERROR TABLE EMPTY
- XCHG
- LHLD INB ;POINTER TO NEW DIR ENTRY
- SAVE D,H
- INX H
- MATCH ,,11 ;COMPARE 11 CHARAACTERS
- RESTORE H,D
- JZ SWITCH ;STORE NEW ENTRY OVER OLD
- INDEX J,2 ;INCR INDEX BY 2
- JMP DIR9
-
- ; REPLACE EXTENT IN TABLE IF ITS GREATER.
- SWITCH:
- CALL CLCSPC ;GET NUMBER OF GROUPS.
- XCHG
- LXI B,11 ;ADD IT TO CNT IN TBL.
- DAD B
- ADD M
- MOV M,A
- JNC $+5
- INX H
- INR M
- JMP DIR12
-
- ; INSERT ENTRY IN TABLE.
- DIR10: RESTORE D,H
- SAVE D,H
- MOVE ,,15 ;MOVE THE DIRECTORY ENTRY
- RESTORE H,D
- LXI H,12 ;MOVE # OF GRPS TO EX.
- DAD D
- CALL CLCSPC ;GET NUMBER OF CPM GROUPS.
- MVI M,0 ;ZERO S1.
- DCX H
- MOV M,A
- LDA COUNT
- INR A
- STA COUNT ;INCR COUNT OF DIRECTORY ENTRIES
- LHLD OUTB
- DSTORE 0,IPOINT ;INDEXED STORE HL
- INDEX OUTB,16
- INDEX IPOINT,2
- JMP DIR12A
-
- ; BUMP INPUT POINTERS AND CHECK FOR END OF BUFFER.
- DIR12:
- RESTORE H
- DIR12A:
- JMP DIR5 ;READ ANOTHER BLOCK FROM DIRECTORY
-
- ; GET NUMBER OF CP/M GROUPS IN THIS EXTENT.
- CLCSPC: SAVE B,D,H
- LHLD INB ;POINT TO EXTENT GROUP #'S.
- LXI D,16
- DAD D
- MVI B,0 ;ZERO COUNT.
- MVI C,16 ;SET FOR MAX # OF GROUPS.
- CLCLP:
- MOV A,M ;GET A GROUP #.
- ORA A ;ALLOCATED?
- JZ $+4 ;...NO.
- INR B ;...YES, BUMP COUNT.
- INX H ;BUMP GROUP PTR.
- DCR C ;DECR COUNT.
- JNZ CLCLP ;LOOP FOR ALL ENTRIES.
- MOV A,B ;GET COUNT.
- RESTORE H,D,B
- RET
-
-
-
- ; THIS ROUTINE PRINTS THE DIRECTORY IN 3 COLUMNS. NO OF LINES
- ; PRINTED IS CONTROLED BY VARIABLE LINES. ALL DIRECTORY NAMES
- ; ARE PRESENT IN TABLE BUT ONLY A MAXIMUM OF 3*LINES WILL BE
- ; PRINTED.
- ;
- DIR14: LXI H,0
- SHLD W ;INITIALIZE ALLOCATION
- SHLD I ;INITIALIZE INDEX
- DIR16: DLOAD PDIR,I ;INDEX LOAD POINTER
- DJZ ENDFIL ;EXIT IF POINTER ZERO
- CALL DIR20 ;CALL PRINT ROUTINE FOR AN ENTRY.
- PRINT ' '
- DLOAD PDIR+LINES*2,I ;POINTER COL 2
- DJZ DIR18 ;NO PRINT IF ZERO
- CALL DIR20 ;PRINT IT
- PRINT ' '
- DLOAD PDIR+LINES*4,I ;POINTER COL 3
- DJZ DIR18
- CALL DIR20 ;CALL PRINT ROUTINE
- DIR18: PRINT CRLF,$
- INDEX I,2 ;INCR INDEX BY 2
- LXI D,LINES*2 ;CHECK INDEX LIMIT
- CPHL
- JZ ENDFIL ;EXIT WHEN INDEX 32
- JMP DIR16 ;PRINT SOME MORE
-
-
- ; *** SUBROUTINE TO PRINT A SINGLE DIRECTORY ENTRY ***
- ;
- ; PRINT THE FILE NAME.
- DIR20: MVI C,11 ;NAME LENGTH
- DIR22: SAVE B,H ;SAVE REGISTERS
- MOV A,M ;GET A CHAR.
- ANI 07FH ;REMOVE POSSIBLE INDICATOR.
- CHAROUT ;PUT IT TO THE CONSOLE.
- RESTORE H,B ;RESTORE THE REGISTERS
- INX H ;INCR NAME POINTER
- DCR C ;DECR CHAR COUNT
- JNZ DIR22 ;LOOP FOR LENGTH OF NAME.
-
- ; CALCULATE AND PRINT THE FILE SIZE.
- DIR24:
- MOV E,M ;DE = # OF ALLOCATED GROUPS
- INX H
- MOV D,M
- XCHG
-
- LDA DSKBSH ;CONVERT CP/M GROUP BACK TO K.
- SUI 3
- JZ $+8
- DAD H
- DCR A
- JNZ $-2
- SAVE H
-
- XCHG ;ADD IT TO CUM TOTAL.
- LHLD W
- DAD D
- SHLD W
-
- PRINT ' '
- POP H
- PUSH H
- LXI D,1000
- CPHL
- JNC DIR30
- PRINT ' '
- POP H
- PUSH H
- LXI D,100
- CPHL
- JNC DIR30
- PRINT ' '
- POP H
- PUSH H
- LXI D,10
- CPHL
- JNC DIR30
- PRINT ' '
- DIR30: POP H
- DECOUT
- PRINT 'K'
- RET
- ;
- ;
- ; THIS ROUTINE RESTORES DRIVE B
- ;
- FIXB: LDA NEWDRV ;CHECK DRIVE NO
- ORA A
- RZ ;RETURN IF DRIVE A
- LDA NEWDRV ;SELECT THE DRIVE.
- MOV E,A
- DISKIO LOGIN
- RET
- ;
- ; THIS IS THE EXIT POINT FROM THE PROGRAM. PRINT NO OF FILES AND
- ; SPACE REMAINING, RELOAD OLD STACK POINTER AND RETURN BACK TO CCP.
- ;
- ENDFIL: PRINT <CR,LF,' '>
- LXI H,0
- LDA COUNT
- MOV L,A
- DECOUT
- PRINT ' FILES '
-
- LHLD MAXSTR ;GET MAX STORAGE SIZE.
- DSUB W ;SUBTRACT IN-USE SIZE.
- DECOUT
- PRINT <'K BYTES REMAINING ON DISK',CR,LF>
- EF1: LHLD OLDSTK
- SPHL ;RELOAD OLD STACK POINTER
- RET ;RETURN TO CCP WITHOUT REBOOT
- ;
- DSKERR: PRINT <CR,LF,'ERROR - SELECT DRIVE A, B, C OR D'>
- JMP EF1 ;EXIT
- ;
- ; THIS SECTION DOES THE ACTUAL SORTING OF THE DIRECTORY. DURING THE
- ; INPUT OF THE DIRECTORY NAMES, A TABLE OF ADDRESS POINTERS PDIR
- ; WAS CONSTRUCTED. THE SORT ROUTINE SORTS THE ADDRESS POINTERS
- ; RATHER THAN THE ACTUAL DIRECTORY.
- ; THIS IS AN IMPLEMENTATION OF C. A. R. HOARE'S QUICKSORT ALGORITHM.
- ; THE ALGORITHM IS VERY FAST AND GENERALLY USEFUL, HOWEVER CAUTION
- ; SHOULD BE USED WITH LARGE FILES. THE ALGORITHM IS RECURSIVE AND
- ; THE STACK SPACE REQUIRED IS PROPORTIONAL TO THE NO OF ITEMS TO BE
- ; SORTED.
- ;
- SORT: LDA COUNT ;NO OF ENTRIES IN DIR
- ORA A
- JZ ENDFIL ;EXIT IF DIRECTORY EMPTY
- DCR A
- LXI H,0 ;ZERO HL
- MOV L,A
- DAD H
- SHLD LAST ;END OF ARRAY
- LXI H,0
- SHLD FIRST ;START OF ARRAY
- LXI H,0FFFFH
- PUSH H ;FLAG FOR STACK EMPTY
- LHLD FIRST
- PUSH H
- LHLD LAST
- PUSH H ;STACK CONTAINS FIRST AND LAST INDICES
- ;
- ; NOW POP STACK AND KEEP CALLING SPLIT RECURSIVELY TILL STACK EMPTY
- ;
- SORT2: POP H
- MOV A,H
- CPI 0FFH
- JZ DIR14 ;GO TO PRINT ROUTINE
- SHLD J
- SHLD LAST
- POP H
- SHLD I
- SHLD FIRST
- CALL SPLIT
- LHLD I
- XCHG
- LHLD FIRST
- CPHL
- JZ SORT4
- PUSH H ;I ON STACK
- DCX D
- DCX D
- PUSH D ;J ON STACK
- SORT4: LHLD J
- XCHG
- LHLD LAST
- CPHL
- JZ SORT8
- INX D
- INX D
- PUSH D ;NEW I ON STACK
- PUSH H ;NEW J ON STACK
- SORT8: JMP SORT2
- ;
- ; SPLIT SUBROUTINE DOES A SINGLE PARTITION ON AN ARRAY OF POINTERS
- ;
- SPLIT: HALF I
- XCHG
- HALF J
- DAD D
- MOV A,L
- ANI 0FEH
- MOV L,A
- SHLD K ;K=I+J/2
- DLOAD PDIR,K
- SHLD W ;W IS POINTER TO PARTITION ELEMENT OF PDIR
- SPLIT2: DLOAD PDIR,I ;GET ITEM FROM LEFT
- XCHG
- LHLD W ;PARTITION ELEMENT
- MATCH ,,11 ;CONPARE KEYS
- JP SPLIT4
- INDEX I,2 ;INCR I
- JMP SPLIT2
- SPLIT4: DLOAD PDIR,J ;GET ITEM FROM RIGHT
- XCHG
- LHLD W ;PARTITION ELEMENT
- XCHG
- MATCH ,,11 ;COMPARE KEYS
- JP SPLIT6
- INDEX J,-2
- JMP SPLIT4 ;LOOP BACK
- SPLIT6: LHLD I
- XCHG
- LHLD J
- CPHL ;COMPARE I AND J
- RZ ;RET IF I = J
- DLOAD PDIR,I ;SWITCH POINTERS
- SAVE H
- DLOAD PDIR,J
- DSTORE PDIR,I
- RESTORE H
- DSTORE PDIR,J
- JMP SPLIT2
- ;
- ; DATA ALLOCATIONS
- ;
- LINES EQU 18 ;LINES PER PAGE ON DISPLAY
- SPACE: DB ' $' ;ASCII SPACE
- CRLF: DB 0DH,0AH,24H ;ASCII CR LF
- I: DW 0 ;PSEUDO INDEX REGISTER
- J: DW 0 ;PSEUDO INDEX REGISTER
- K: DW 0 ;PSEUDO INDEX REGISTER
- FIRST: DW 0 ;START OF ARRAY
- LAST: DW 0 ;END OF ARRAY
- W: DW 0 ;STORAGE FOR PARTITION INDEX
- DIRSIZ: DW 0 ;SIZE OF DIRECTORY IN K
- MAXSTR: DW 0 ;MAXIMUM STORAGE AVAILABLE
- LINE: DW 0 ;LINE NUMBER FOR LISTING
- IPOINT: DW 00 ;VARIABLE BUFFER POINTER
- DRVNO: DB 0 ;STORAGE FOR ORIGINALLY LOGGED DRIVE
- NEWDRV: DB 0 ;STORAGE FOR NEW DRIVE NO
- COUNT: DB 0 ;COUNT OF DIRECTORY ENTRIES
- OLDSTK: DW 0 ;STORAGE FOR OLD STACK POINTER
- ENDSTK: DS 128 ;STORAGE FOR NEW STACK
- NEWSTK: DW 0 ;NEW STACK
- INB: DW 0 ;STORES POINTER TO INPUT BUFFER AREA
- OUTB: DW 0 ;STORES POINTER TO DIRECTORY BUFFER AREA
- DPBADR: DW 0 ;ADDRESS OF DISK'S CP/M DPB
- DSKBSH: DB 0 ;DISK DPBBSH VALUE
- DSKBLM: DB 0 ;DISK DPBBLM VALUE
- DIRFCB: DB '?','????????','???','?',0,0,0
- DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- DB 0,0,0
- PDIR DW 0 ;POINTER TABLE TO DIRECTORY
- DIRBUF: EQU PDIR+(2*MAXDIR) ;START OF AREA USED TO STORE AND SORT DIRECTORY
- END
-