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
/
SIMTEL
/
CPMUG
/
CPMUG040.ARK
/
DI.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
14KB
|
595 lines
; - D -
; BY S J SINGER
;
; D 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 D 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.
; 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.
; D 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.
; THE STANDARD VERSION OF 'D' IS CONFIGURED FOR A DISPLAY SCREEN OF
;24 BY 80 CHARACTERS. A CONDITIONAL ASSEMBLY SWITCH IS INCLUDED TO CONFIGURE
;THE DISPLAY FOR A 16 BY 64 SIZE SCREEN WITH A SMALLER MAXIMUM NUMBER OF
;FILES. SET THE SWITCH TO TRUE FOR SMALLER SCREENS.
; VDM EQU 0FFH
;
;
;
; COMMAND FORMAT
;
; D DISPLAY DIRECTORY OF LOGGED DISK
; D A: DISPLAY DIRECTORY OF DISK A
; D B: DISPLAY DIRECTORY OF DISK B
; D C: DISPLAY DIRECTORY OF C
; D D: DISPLAY DIRECTORY OF D
;
;
VDM: EQU 0H ;CONDITIONAL ASSEMBLY SWITCH SET TRUE IF
; 16 BY 64 SCREEN
;
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
; GROUP NO IN G, TRT NO RETURNED TO TRACK, SEC TO BSEC AND ESEC
;
GRPTS: LDA DENCODE ;CHECK DENSITY
CPI 0DDH ;DOUBLE?
JZ GRPTSD
JMP GRPTSS ;ELSE SINGLE DENSITY
;
GRPTSD: MVI A,2
STA TRACK ;DIRECTORY IS ON TRACK 2
LDA S ;SECTOR NO
INR A ;INCR BY 1
MOV B,A ;TO B
LDA G ;GROUP NO
ADD A
ADD A
ADD A
ADD A ;SHIFT LEFT 4 BITS
ADD B ;ADD IN GROUP NO
STA BSEC
STA ESEC
RET
;
GRPTSS: 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 DIR2
LXI H,82H ;POINT TO INPUT BUFFER
CALL GETDRV
JNC DSKERR ;ERROR OF NO DRIVE FOUND
STA NEWDRV ;STORE DRIVE CODE
DIR2: XRA A
STA S ;SECTOR COUNT
STA G ;GROUP 0 = DIRECTORY
STA COUNT ;COUNT OF DIRECTORY ENTRIES
LXI H,PDIR ;ZERO DIRECTORY POINTER TABLE
MVI B,0
XRA A
DIR3: MOV M,A ;STORE A ZERO
INX H
DCR B
JNZ DIR3 ;LOOP FOR 256 ITERATIONS
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
CALL GETDEN
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
IF VDM
PRINT ' '
ELSE
PRINT ' '
ENDIF
LDA COUNT
CPI 58
JM DIR17A
DLOAD PDIR+LINES*2+6,I ;POINTER COL 2
JMP DIR17B
DIR17A: DLOAD PDIR+LINES*2,I ;POINTER COL 2
DIR17B: DJZ DIR18 ;NO PRINT IF ZERO
CALL DIR20 ;PRINT IT
IF VDM
PRINT ' '
ELSE
PRINT ' '
ENDIF
LDA COUNT
CPI 58
JM DIR17C
DLOAD PDIR+LINES*4+12,I
JMP DIR17D
DIR17C: DLOAD PDIR+LINES*4,I ;POINTER COL 3
DIR17D: DJZ DIR18
CALL DIR20 ;CALL PRINT ROUTINE
DIR18: INDEX I,2 ;INCR INDEX BY 2
LXI D,LINES*2 ;CHECK INDEX LIMIT
LDA COUNT
CPI 58
JM DIR19
LXI D,LINES*2+6
DIR19: CPHL
JZ ENDFIL ;EXIT WHEN INDEX 32
PRINT CRLF,$
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
XRA A ;CLEAR CARRY
MOV A,M ;GET RECORD COUNT
RRC
RRC
RRC ;SHIFT RIGHT 3 (DIVIDE BY 8)
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: LDA DENCODE ;CHECK DENSITY CODE
CPI 0DDH ;DOUBLE DENSITY
JNZ DIR26A ;SINGLE DENSITY
INX H
MOV A,L
ANI 0FEH
MOV L,A ;ROUND UP ONE BIT (2K GROUPS)
DIR26A: MOV A,L
ADD B
MOV L,A
PUSH H
LXI D,10
CPHL
JM DIR28
POP H
PUSH H
LXI D,100
CPHL
JM DIR27
PRINT ' '
JMP DIR30
DIR27: PRINT ' '
JMP DIR30
DIR28: PRINT ' '
DIR30: POP H
PUSH H
XCHG
LHLD W
DAD D
SHLD W
POP H
DECOUT
PRINT 'K'
RET
;
;
; GET DENSITY CODE FROM TRACK ZERO SECTOR 1 BYTE 128
;
GETDEN: 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
LDA 0FFH
CPI 0DDH ;DOUBLE DENSITY CODE
JZ GDEN1
LDA 0FEH ;TRY NEXT TO LAST BYTE ALSO
CPI 0DDH
RNZ
GDEN1: STA DENCODE
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: LDA COUNT
CPI 58
JP END0
PRINT CRLF,$
IF VDM
END0: PRINT <CR,LF,' '>
ELSE
END0: PRINT <CR,LF,' '>
ENDIF
LXI H,0
LDA COUNT
MOV L,A
DECOUT
PRINT ' FILES '
LHLD W
MOV A,L ;CHECK FOR ZERO
ORA H
JZ END1
XRA A
SUB L
MOV L,A ;MOVE IT BACK
MVI A,00H
SBB H
MOV H,A ;TWOS COMPLIMENT IN HL
END1: LDA DENCODE ;CHECK DENSITY
CPI 0DDH
LXI D,478 ;DOUBLE DENSITY SPACE
JZ END2
LXI D,241 ;SINGLE DENSITY SPACE
END2: DAD D ;SUBTRACT FROM TOTAL
DECOUT
PRINT <'K BYTES REMAINING ON DISK '>
LDA NEWDRV ;DRIVE NUMBER
CALL PRNDRV ;PRINT DRIVE NAME
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 ;CHECK FOR EXTENDED PRINT
CPI 58
JP SORT1
IF NOT VDM
PRINT <CR,LF,LF,' DIRECTORY DRIVE - '>
LDA NEWDRV ;LOGGED DISK
CALL PRNDRV ;PRINT DRIVE NAME (A - C)
PRINT CRLF2,$ ;PRINT CR AND LF
ENDIF
SORT1: 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
;
;
; GETDRV SEARCH COMMAND STRING FOR DRIVE NAME AND RETURN CODE
; A:=0 B:=1 C:=2 D:=3 CARRY SET IF DRIVE PRESENT
; GETDRV IS CALLED WITH HL POINTING TO STARTING POSITION FOR SEARCH
;
GETDRV: SAVE ;SAVE REGS
LXI D,DSKNAME ;POINT TO NAME TABLE
MVI C,0 ;DRIVE NUMBER
GD1: SAVE
MVI B,40H ;STRING LENGTH
MVI C,2 ;SUBSTRING LENGTH
INSTR
RESTORE
JC GD3 ;FOUND NAME ON CARRY
MOV A,C ;DRIVE NO TO A
CPI 3 ;CHECK LIMIT
JZ GD3
INR C ;INCR DRIVE NO
INX D
INX D ;POINT TO NEXT NAME
JMP GD1 ;LOOP FOR 4 DRIVES
GD3: MOV A,C ;DRIVE NO TO A
RESTORE
RET
;
DSKNAME:DB 'A:' ;TABLE OF DISK NAMES
DB 'B:'
DB 'C:'
DB 'D:'
;
; PRNDRV PRINT DRIVE NAME CORRESPONDING TO CODE IN A REG
; 0=A 1=B 2=C 3=D >3 ERROR
;
PRNDRV: SAVE
CPI 4 ;CHECK RANGE
JP PRDR3 ;ERROR IF > 3
ADI 'A' ;CALC LETTER TO PRINT
CHAROUT ;PRINT IT
PRDR1: RESTORE
RET
PRDR3: PRINT <CR,LF,'ERROR - DRIVE NUMBER GREATER THAN 3',CR,LF>
JMP PRDR1
;
;
; DATA ALLOCATIONS
;
IF VDM
LINES EQU 13
ELSE
LINES EQU 19 ;LINES PER PAGE ON DISPLAY
ENDIF
FCB EQU 5CH ;FILE CONTROL BLOCK
SPACE: DB ' $' ;ASCII SPACE
CRLF: DB 0DH,0AH,24H ;ASCII CR LF
CRLF2: DB 0DH,0AH,0AH,'$' ;ASCII CR LF 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
INBUF: DS 10 ;USED AS CONSOLE INPUT BUFFER
LASTIN: DB 0 ;LAST CONSOLE INPUT CHAR
INFLAG: DB 0 ;FLAG, RET FOR MORE CONSOLE INPUT
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 NO FOR VALIDATE
SNUM: DB 0 ;SECTOR NO FOR VALIDATE
VALFLG: DB 0 ;VALIDATION ERROR FLAG
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
INB: DW 0 ;STORES POINTER TO INPUT BUFFER AREA
OUTB: DW 0 ;STORES POINTER TO DIRECTORY BUFFER AREA
DENCODE:DB 0 ;DENSITY CODE DD=DOUBLE 4D=QUAD
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
ENDSTK: DS 100 ;STORAGE FOR NEW STACK
NEWSTK: DS 0 ;NEW STACK
PDIR DS 256 ;POINTER TABLE TO DIRECTORY (128 ENTRIES MAX)
DIRBUF: EQU PDIR+258 ;START OF AREA USED TO STORE AND SORT DIRECTORY
END