home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpmug
/
cpmug047.ark
/
DIRS9_8.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
8KB
|
368 lines
;
; DIRS.ASM
; revised 9/08/80
;
; SORTED DIRECTORY PROGRAM
; by Keith Petersen, W8SDZ
;
;DISPLAY FORMAT IS SAME AS CP/M 2.x DIR, EXCEPT IS SORTED
;ALPHABETICALLY. SUGGESTED AS A REPLACEMENT FOR THE "DIR"
;COMMAND IN CP/M-2. PRESENT VERSION ALLOWS MAX. OF 256 NAMES.
;
;PRINTS A 4-WIDE DIRECTORY, SORTED ALPHABETICALLY.
;COMPATIBLE WITH CP/M 1.4 AND 2.x. IGNORES "SYS" FILES.
;
;BASED ON 'FMAP' BY WARD CHRISTENSEN.
;
;DIRS FILENAME.FILETYPE or just DIRS
;
;ALLOWS '*' OR '?' TYPE SPECIFICATIONS
;DRIVE NAME BY ALSO BE SPECIFIED
;
; 09/07/80 - Modified to assemble with RMAC and externalized
; page 0 for use with MP/M. (Must be linked
; with PG0EQU.ASM)
; Also modified to allow (via conditional assembly)
; 'S' option to display system files.
; (by Bruce R. Ratoff)
; 09/08/80 - CHKUSR conditional assembly added to force match of
; current user number, as required in MP/M to
; prevent user 0 files from showing up in all
; areas. Also used in CP/M 2.2 systems containing
; BDOSPAT. (BRR)
;
;
FALSE EQU 0 ;DEFINE LOGICAL FALSE
TRUE EQU NOT FALSE ;DEFINE LOGICAL TRUE
;
ALTCPM EQU FALSE ;PUT TRUE HERE FOR H8 OR TRS-80
RMAC EQU FALSE ;PUT TRUE HERE FOR ASSEMBLY BY RMAC
SOPT EQU FALSE ;PUT TRUE TO ALLOW 'DIR *.* S' FORM
CHKUSR EQU FALSE ;PUT TRUE IF USER # MATCH REQUIRED
;
IF ALTCPM
BASE EQU 4200H
TPA EQU 4300H
ENDIF
IF RMAC
EXTRN BASE,FCB,BDOS ;MAKE BASE EXTERNAL
ENDIF
IF (NOT ALTCPM) AND (NOT RMAC)
BASE EQU $ ;WILL DEFAULT TO 0 (OR 100H WITH MAC +R OPTION)
TPA EQU 100H
ENDIF
;
IF NOT RMAC
FCB EQU BASE+5CH
BDOS EQU BASE+5
ENDIF
;
NPL EQU 4 ;NUMBER OF NAMES PER LINE
DELIM EQU ':' ;FENCE (DELIMITER) CHARACTER
;
IF NOT RMAC
ORG TPA
ENDIF
;
;SAVE THE STACK
START LXI H,0
DAD SP ;H=STACK
SHLD STACK ;SAVE IT
LXI SP,STACK ;GET NEW STACK
;
IF SOPT
LDA FCB+17 ;SAVE S OPTION FLAG
STA SOPFLG ;(BLANK OR LETTER S)
ENDIF
;
IF CHKUSR
MVI E,0FFH
MVI C,CURUSR ;INTERROGATE USER NUMBER
CALL BDOS
STA USERNO
ENDIF
;
LXI H,FCB
MOV A,M ;GET DRIVE NAME
ORA A ;ANY SPECIFIED?
JNZ START2 ;YES SKIP NEXT ROUTINE
MVI C,CURDSK
CALL BDOS ;GET CURRENT DISK NR
INR A ;MAKE A:=1
;
START2 ADI 'A'-1 ;MAKE IT PRINTABLE
STA DRNAM ;SAVE FOR LATER
LXI H,FCB+1 ;POINT TO NAME
MOV A,M ;ANY SPECIFIED?
CPI ' '
JNZ GOTFCB
;NO FCB - MAKE FCB ALL '?'
MVI B,11 ;FN+FT COUNT
QLOOP MVI M,'?' ;STORE '?' IN FCB
INX H
DCR B
JNZ QLOOP
;LOOK UP THE FCB IN THE DIRECTORY
GOTFCB MVI C,FSRCHF ;GET 'SEARCH FIRST' FNC
LXI D,FCB
CALL BDOS ;READ FIRST
INR A ;WERE THERE ANY?
JNZ SOME ;GOT SOME
CALL ERXIT
DB 'NO FILE$'
;
;READ MORE DIRECTORY ENTRIES
MOREDIR MVI C,FSRCHN ;SEARCH NEXT
LXI D,FCB
CALL BDOS ;READ DIR ENTRY
INR A ;CHECK FOR END (0FFH)
JZ SPRINT ;NO MORE - SORT & PRINT
;POINT TO DIRECTORY ENTRY
SOME DCR A ;UNDO PREV 'INR A'
ANI 3 ;MAKE MODULUS 4
ADD A ;MULTIPLY...
ADD A ;..BY 32 BECAUSE
ADD A ;..EACH DIRECTORY
ADD A ;..ENTRY IS 32
ADD A ;..BYTES LONG
LXI H,BASE+81H ;POINT TO BUFFER
;(SKIP TO FN/FT)
ADD L ;POINT TO ENTRY
ADI 9 ;POINT TO SYS BYTE
MOV L,A ;SAVE (CAN'T CARRY TO H)
;
IF SOPT
LDA SOPFLG ;DID USER REQUEST SYS FILES?
CPI 'S'
JZ SYSFOK
ENDIF
;
MOV A,M ;GET SYS BYTE
ANI 80H ;CHECK BIT 7
JNZ MOREDIR ;SKIP THAT FILE
SYSFOK MOV A,L ;GO BACK NOW
SUI 9 ;BACK TO FT/FN START
MOV L,A ;HL POINTS TO ENTRY NOW
;
IF CHKUSR
DCX H ;POINT TO USER BYTE IN FCB
LDA USERNO ;GET CURRENT USER
CMP M
JNZ MOREDIR ;IGNORE IF DIFFERENT
INX H
ENDIF
;
;MOVE ENTRY TO TABLE
XCHG ;ENTRY TO DE
LHLD NEXTT ;NEXT TABLE ENTRY TO HL
MVI B,11 ;ENTRY LENGTH
TMOVE LDAX D ;GET ENTRY CHAR
ANI 7FH ;REMOVE ATTRIBUTES
MOV M,A ;STORE IN TABLE
INX D
INX H
DCR B ;MORE?
JNZ TMOVE
SHLD NEXTT ;SAVE UPDATED TABLE ADDR
LDA COUNT ;GET PREV COUNT
INR A
STA COUNT
JMP MOREDIR
;
;SORT AND PRINT
SPRINT LDA COUNT ;GET FILE NAME COUNT
ORA A ;ANY FOUND?
JZ EXIT ;NO, EXIT
;INIT THE ORDER TABLE
LXI H,ORDER
LXI D,TABLE
LXI B,11 ;ENTRY LENGTH
BLDORD MOV M,E ;SAVE LO ORD ADDR
INX H
MOV M,D ;SAVE HI ORD ADDR
INX H
XCHG ;TABLE ADDR TO HL
DAD B ;POINT TO NEXT ENTRY
XCHG
DCR A ;MORE?
JNZ BLDORD ;..YES
LDA COUNT ;GET COUNT
STA SCOUNT ;SAVE AS # TO SORT
DCR A ;ONLY 1 ENTRY?
JZ DONE ;..YES, SO SKIP SORT
SORT XRA A ;GET A ZERO
STA SWITCH ;SHOW NONE SWITCHED
LDA SCOUNT ;GET COUNT
DCR A ;USE 1 LESS
STA TEMP ;SAVE # TO COMPARE
STA SCOUNT ;SAVE HIGHEST ENTRY
JZ DONE ;EXIT IF NO MORE
LXI H,ORDER ;POINT TO ORDER TABLE
SORTLP CALL COMPR ;COMPARE 2 ENTRIES
CM SWAP ;SWAP IF NOT IN ORDER
INX H ;BUMP ORDER
INX H ;..TABLE POINTER
LDA TEMP ;GET COUNT
DCR A
STA TEMP
JNZ SORTLP ;CONTINUE
;ONE PASS OF SORT DONE
LDA SWITCH ;ANY SWAPS DONE?
ORA A
JNZ SORT
;SORT IS ALL DONE - PRINT ENTRIES
DONE LXI H,ORDER
SHLD NEXTT
;
;PRINT AN ENTRY
CALL DRPRNT ;PRINT DRIVE NAME
MVI C,NPL ;NR. OF NAMES PER LINE
ENTRY: PUSH B
MVI C,CONST ;CK STATUS OF KB
CALL BDOS ;ANY KEY PRESSED?
POP B
ORA A
JNZ ABORT ;YES, ABORT
CALL FENCE ;PRINT FENCE CHAR AND SPACE
LHLD NEXTT ;GET ORDER TABLE POINTER
MOV E,M ;GET LO ADDR
INX H
MOV D,M ;GET HI ADDR
INX H
SHLD NEXTT ;SAVE UPDATED TABLE POINTER
XCHG ;TABLE ENTRY TO HL
MVI B,8 ;FILE NAME LENGTH
CALL TYPEIT ;TYPE FILENAME
CALL PERIOD ;PERIOD AFTER FN
MVI B,3 ;GET THE FILETYPE
CALL TYPEIT
CALL SPACE ;SPACE OVER ONE
;SEE IF MORE ENTRIES
LDA COUNT
DCR A
JZ EXIT
STA COUNT
DCR C ;ONE LESS ON THIS LINE
CZ CRLF ;PRINT CR-LF AND DRIVE NAME
JMP ENTRY
;
PERIOD MVI A,'.'
JMP TYPE
;
DRPRNT LDA DRNAM ;GET SAVED DRIVE NAME
JMP TYPE ;PRINT IT
;
FENCE MVI A,DELIM ;FENCE CHARACTER
CALL TYPE ;PRINT IT, FALL INTO SPACE
;
SPACE MVI A,' '
;
;TYPE CHAR IN A
TYPE PUSH B
PUSH D
PUSH H
MOV E,A
MVI C,WRCHR
CALL BDOS
POP H
POP D
POP B
RET
;
TYPEIT MOV A,M
CALL TYPE
INX H
DCR B
JNZ TYPEIT
RET
;
CRLF MVI A,13 ;PRINT
CALL TYPE
MVI A,10 ;LF
CALL TYPE
CALL DRPRNT
MVI C,NPL ;NUMBER OF NAMES PER LINE
RET
;
;COMPARE ROUTINE FOR SORT
COMPR PUSH H ;SAVE TABLE ADDR
MOV E,M ;LOAD LO
INX H
MOV D,M ;LOAD HI
INX H
MOV C,M
INX H
MOV B,M
;BC, DE NOW POINT TO ENTRIES TO BE COMPARED
XCHG
CMPLP LDAX B
CMP M
INX H
INX B
JZ CMPLP
POP H
RET ;COND CODE TELLS ALL
;
;SWAP ENTRIES IN THE ORDER TABLE
SWAP MVI A,1
STA SWITCH ;SHOW A SWAP WAS MADE
MOV C,M
INX H
PUSH H ;SAVE TABLE ADDR+1
MOV B,M
INX H
MOV E,M
MOV M,C
INX H
MOV D,M
MOV M,B
POP H
MOV M,D
DCX H ;BACK POINTER TO CORRECT LOC'N
MOV M,E
RET
;
;ERROR EXIT
ERXIT POP D ;GET MSG
MVI C,PRINT
JMP CALLB ;PRINT MSG, EXIT
;
;ABORT - READ CHAR ENTERED
ABORT MVI C,RDCHR
CALLB CALL BDOS ;DELETE THE CHAR
;
;FALL INTO EXIT
;EXIT - ALL DONE , RESTORE STACK
EXIT LHLD STACK ;GET OLD STACK
SPHL ;MOVE TO STACK
RET ;..AND RETURN
;
NEXTT DW TABLE ;NEXT TABLE ENTRY
COUNT DB 0 ;ENTRY COUNT
SCOUNT DB 0 ;# TO SORT
SWITCH DB 0 ;SWAP SWITCH FOR SORT
BUFAD DW BASE+80H ;OUTPUT ADDR
ORDER DS 512 ;ORDER TABLE (ROOM FOR 256 NAMES)
DS 60 ;STACK AREA
STACK DS 2 ;SAVE OLD STACK HERE
SOPFLG DS 1 ;SET TO 'S' TO ALLOW SYS FILES TO PRINT
USERNO DS 1 ;CONTAINS CURRENT USER NUMBER
DRNAM DS 1 ;SAVE DRIVE NAME HERE
TEMP DS 1 ;SAVE DIR ENTRY
TABLE EQU $ ;READ ENTRIES IN HERE
;
; BDOS EQUATES
;
RDCHR EQU 1 ;READ CHAR FROM CONSOLE
WRCHR EQU 2 ;WRITE CHR TO CONSOLE
PRINT EQU 9 ;PRINT CONSOLE BUFF
CONST EQU 11 ;CHECK CONS STAT
FOPEN EQU 15 ;0FFH=NOT FOUND
FCLOSE EQU 16 ; " "
FSRCHF EQU 17 ; " "
FSRCHN EQU 18 ; " "
CURDSK EQU 25 ;GET CURRENTLY LOGGED DISK NAME
CURUSR EQU 32 ;GET CURRENTLY LOGGED USER NUMBER (2.X ONLY)
;
END