home *** CD-ROM | disk | FTP | other *** search
- ; - XDIR -
- ; BY S J SINGER
- ;
- ; 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 48 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.
- ; 2. THE PRESENT VERSION READS GROUPS 0 AND 1 DIRECTLY FOR SPEED.
- ; IF A DISK IS SET UP FOR MORE THAN 64 FILES OR THE BLOCK FORMAT
- ; IS CHANGED THE READ ROUTINE WILL HAVE TO BE MODIFIED.
- ;
- ; 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
- ;
- ;
- MACLIB MACRO ;INCLUDE MACRO LIBRARY
- 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
- JMP DIR
- ;
- ; GRPTS CONVERT CPM GROUP AND SECTOR NUMBER TO TRK AND SEC
- ;
- GRPTS: MVI H,0 ;ZERO H
- LDA G ;GROUP NO
- MOV L,A ;TO L
- MOV D,H ;ZERO D
- DAD H
- DAD H
- DAD H ;SHIFT LEFT 3
- LDA S ;GET SECTOR NO
- MOV E,A ;TO DE
- DAD D ;HL HAS G*8+S
- LXI D,-26 ;DIVISOR
- MVI A,1 ;CONTAINS DIVIDEND
- DIV: DAD D ;SUB 26
- INR A
- JC DIV ;LOOP TILL MINUS
- LXI D,TABLE+26 ;INDEX INTO TABLE
- DAD D
- STA TRACK ;STORE TRACK NO
- MOV A,M ;GET SECTOR NO
- STA BSEC ;SAVE IN BEGINNING SECTOR
- STA ESEC ;SAVE IN END SECTOR TOO
- RET
- ;
- ; 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
- CPI 'A'
- JNZ DX1
- XRA A
- STA NEWDRV ;SELECT DRIVE A
- JMP DDD
- DX1: CPI 'B'
- JNZ DSKERR
- MVI A,1
- STA NEWDRV
- DDD: PRINT <CR,LF,LF,' DIRECTORY DRIVE - '>
- LDA NEWDRV ;LOGGED DISK
- ORA A
- JNZ BDIR
- PRINT <'A',CR,LF,LF>
- JMP DIR2
- BDIR: PRINT <'B',CR,LF,LF>
- CALL FIXB ;RESTORE DRIVE B
- DIR2: XRA A
- STA S ;SECTOR COUNT
- STA G ;GROUP 0 = DIRECTORY
- STA COUNT ;COUNT OF DIRECTORY ENTRIES
- FILL PDIR,PDIR+130 ;ZERO DIRECTORY POINTER TABLE
- 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
- CALL GRPTS ;COMPUTE TRACK AND SECTOR NO FROM G AND S
- SETSEC BSEC ;SET SECTOR
- SETTRK TRACK ;SET TRACK
- CALLBIOS DREAD ;READ DIRECT
- 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 DIR12
- DIR8: INX H
- SAVE H,D
- LXI D,11 ;EXTENSION OFFSET
- DAD D
- MOV A,M
- ORA A
- JZ DIR10 ;IF EXTENT ZERO CONTINUE
- LXI H,0 ;ELSE, 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
- SWITCH: INX H
- MOVE ,,15 ;OVERWRITE OLD ENTRY
- RESTORE H
- JMP DIR12
- DIR10: RESTORE D,H
- MOVE ,,15 ;MOVE THE DIRECTORY ENTRY
- 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
- DIR12: INDEX INB,32 ;INCR POINTERS
- LXI D,100H
- CPHL ;LIMIT OF 4 ENTRIES
- JNZ DIR6
- LDA S
- INR A
- STA S ;INCR DIRECTORY SECTOR COUNT
- JMP DIR4 ;READ ANOTHER BLOCK FROM DIRECTORY
- ;
- ; 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
- 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
- ;
- DIR20: MVI C,11 ;NAME LENGTH
- DIR22: SAVE B,H ;SAVE REGISTERS
- MVI C,2
- MOV E,M ;CHAR TO BE PRINTER
- CALL 5 ;CALL BDOS
- RESTORE H,B ;RESTORE THE REGISTERS
- INX H ;INCR NAME POINTER
- DCR C ;DECR CHAR COUNT
- JZ DIR24 ;PRINT SIZE
- JMP DIR22 ;LOOP TILL COUNT 0
- DIR24: MOV A,M ;EXTENSION TO A
- ADD A
- ADD A
- ADD A
- ADD A ;MULTIPLY BY 16
- MOV B,A ;SAVE IN B
- INX H
- INX H
- INX H ;ADD 3
- MOV A,M ;GET RECORD COUNT
- RRC
- RRC
- RRC ;SHIFT RIGHT 3
- PUSH PSW
- ANI 1FH ;EXTRACT
- LXI H,0
- MOV L,A ;NO TO HL TO PRINT
- POP PSW
- ANI 0E0H ;EXTRACT
- JZ DIR26
- INX H
- DIR26: MOV A,L
- ADD B
- MOV L,A
- SAVE H
- LXI D,10
- CPHL
- JM DIR28
- PRINT ' '
- JMP DIR30
- DIR28: PRINT ' '
- DIR30: POP H
- PUSH H
- XCHG
- LHLD W
- DAD D
- SHLD W
- 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 DRIVE B
- MOV E,A
- DISKIO LOGIN
- XRA A
- STA TNUM ;SELECT TRACK ZERO
- INR A ;SELECT SECTOR 1
- STA SNUM
- SETSEC SNUM
- SETTRK TNUM
- CALLBIOS DHOME ;HOME DRIVES
- CALLBIOS DREAD ;READ TRACK ZERO DIRECT
- 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 W
- MOV A,L
- CMA
- INR A ;NEGATE
- ADI 240
- MOV L,A
- 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 OR B'>
- 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 16 ;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
- 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
- TRACK: DB 0 ;SELECTED TRACK
- BSEC: DB 0 ;SELECTED BEGINNING SECTOR
- ESEC: DB 0 ;SELECTED ENDING SECTOR
- TNUM: DB 0 ;TRACK NUMBER
- SNUM: DB 0 ;SECTOR NUMBER
- G: DB 0 ;CPM GROUP NO
- S: DB 0 ;SECTOR NO WITHIN GROUP G
- COUNT: DB 0 ;COUNT OF DIRECTORY ENTRIES
- OLDSTK: DW 0 ;STORAGE FOR OLD STACK POINTER
- ENDSTK: DS 60 ;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
- TABLE: DB 01H ;SECTOR LOOK UP TABLE
- DB 07H
- DB 0DH
- DB 13H
- DB 19H
- DB 05H
- DB 0BH
- DB 11H
- DB 17H
- DB 03H
- DB 09H
- DB 0FH
- DB 15H
- DB 02H
- DB 08H
- DB 0EH
- DB 14H
- DB 1AH
- DB 06H
- DB 0CH
- DB 12H
- DB 18H
- DB 04H
- DB 0AH
- DB 10H
- DB 16H
- PDIR DW 0 ;POINTER TABLE TO DIRECTORY (64 ENTRIES MAX)
- DIRBUF: EQU PDIR+130 ;START OF AREA USED TO STORE AND SORT DIRECTORY
- END
-