; DIRF.MAC (Z80 VERSION) ver 1.3 ; by Keith Petersen, W8SDZ ; (revised 12/19/80) ; ; DIRECTORY FUNCTION FOR CP/M 1.4 OR 2.x PROGRAMS ; ;--->NOTE: Assemble with Microsoft M80 assembler ; ;This file contains routines which can be included in any ;CP/M program to allow listing the directory. No sorting ;is done because that would require use of more memory above ;the program. These routines use the 80h default buffer for ;all operations so if you have data there be sure to move it ;before running this directory function. Assume all registers ;destroyed when calling 'DIRF'. ; ;This module may be assembled as a stand-alone program for ;testing. L80 link command for testing: L80 DIRF,DIRF,/N/E ;Execute program from CP/M, not L80. It will return to the ;CCP after finishing. ; .Z80 ;Z80 SWITCH FOR ASSEMBLER ENTRY DIRF ;DEFINE DIRF AS PUBLIC ; NPL EQU 4 ;NUMBER OF NAMES PER LINE TAB EQU 9 ;HORIZONTAL TAB CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED ; ;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 FSRCHF EQU 17 ;0FFH=NOT FOUND FSRCHN EQU 18 ; " " CURDSK EQU 25 ;GET CURRENT DISK NAME BDOS EQU 5 FCB EQU 5CH ; ;First, we preserve old stack pointer and set a new one ;because some functions take more stack space than may ;be available in the calling program. DIRF: LD HL,0 ADD HL,SP ;GET OLD STACK POINTER LD (STACK),HL ;SAVE FOR LATER LD SP,STACK ;SET NEW STACK POINTER ; ;Check FCB for drive request LD A,(FCB) ;GET DRIVE NAME FROM FCB OR A ;ANY REQUESTED? (0=NO) JR NZ,GOTDRV ;NOT ZERO MEANS WE HAVE NAME ; ;Get drive name LD C,CURDSK ;GET CURRENT DRIVE NAME CALL BDOS INC A ;MAKE 'A' RELATIVE TO 1 NOT 0 ; ;Print signon message and drive name GOTDRV: ADD A,40H ;MAKE IT ASCII LD (DNAME),A ;SAVE IT IN MESSAGE LD DE,MSG ;POINT TO MESSAGE LD C,PRINT ;PRINT IT CALL BDOS ; ;Make FCB all '?' to match any file LD HL,FCB+1 LD B,11 ;FN+FT COUNT ; QLOOP: LD (HL),'?' ;STORE '?' IN FCB INC HL DEC B JR NZ,QLOOP ; ;Initialize number of names per line counter LD A,NPL ;NR. NAMES PER LINE LD (NNAMS),A ;INIT COUNTER ; ;Look up the FCB in the directory LD C,FSRCHF ;GET 'SEARCH FIRST' FNC LD DE,FCB CALL BDOS ;READ FIRST INC A ;WERE THERE ANY? JR NZ,SOME ;GOT SOME CALL ERXIT DEFB '++NO FILE$' ; ;Read more directory entries MORDIR: LD C,FSRCHN ;SEARCH NEXT LD DE,FCB CALL BDOS ;READ DIR ENTRY INC A ;CHECK FOR END (0FFH) JP Z,EXIT ;NO MORE - EXIT ; ;Point to directory entry SOME: DEC A ;UNDO PREV 'INC A' AND 3 ;MAKE MODULUS 4 ADD A,A ;MULTIPLY... ADD A,A ;..BY 32 BECAUSE ADD A,A ;..EACH DIRECTORY ADD A,A ;..ENTRY IS 32 ADD A,A ;..BYTES LONG LD HL,81H ;POINT TO BUFFER (SKIP TO FN/FT) ADD A,L ;POINT TO ENTRY LD L,A ;SAVE - HL NOW = ENTRY ADRS ; ;Check for console break PUSH HL ;SAVE NAME POINTER LD C,CONST ;CK STATUS OF KBD CALL BDOS POP HL ;RESTORE NAME POINTER OR A ;ANY KEY PRESSED? JP NZ,ABORT ;YES, ABORT ; ;Print an entry LD B,8 ;FILE NAME LENGTH CALL TYPEIT ;TYPE FILENAME LD A,'.' ;PERIOD AFTER FN CALL TYPE LD B,3 ;GET THE FILETYPE CALL TYPEIT LD HL,NNAMS ;POINT TO NAMES COUNTER DEC (HL) ;ONE LESS ON THIS LINE PUSH AF CALL NZ,FENCE ;NO CR-LF NEEDED, DO FENCE POP AF CALL Z,CRLF ;CR-LF NEEDED JP MORDIR ; ;Print two spaces, fence character, then two more spaces FENCE: CALL TWOSPC LD A,':' ;FENCE CHARACTER CALL TYPE ; ;Print two spaces TWOSPC: CALL SPACE ; ;Print one space SPACE: LD A,' ' ; ;Type char in A register TYPE: PUSH BC PUSH DE PUSH HL LD E,A ;CHAR TO E FOR CP/M LD C,WRCHR ;WRITE CHAR TO CONSOLE FUNC CALL BDOS POP HL POP DE POP BC RET ; ;Type (B) characters from memory (HL) TYPEIT: LD A,(HL) AND 7FH ;REMOVE CP/M 2.x ATTRIBUTES CALL TYPE INC HL DEC B JR NZ,TYPEIT RET ; ;CR-LF routine. HL=NNAMS upon entry CRLF: LD A,CR ;CR CALL TYPE LD A,LF ;LF CALL TYPE LD (HL),NPL ;NUMBER OF NAMES PER LINE RET ; ;Error exit ERXIT: POP DE ;GET MSG LD C,PRINT JR CALLB ;PRINT MSG, EXIT ; ;Abort - read char entered to clear it from CP/M buffer ABORT: LD C,RDCHR ;DELETE THE CHAR ; ;Fall into CALLB ; CALLB: CALL BDOS ; ;Fall into EXIT ; ;Exit - All done, return to caller EXIT: LD HL,(STACK) ;GET OLD STACK LD SP,HL ;MOVE TO STACK RET ;...AND RETURN ; MSG: DEFB TAB,TAB,' Directory for drive ' DNAME: DEFB 'X:',CR,LF,'$' ; ;Temporary storage area ; NNAMS: DEFS 1 ;NAMES PER LINE COUNTER DEFS 40 ;ROOM FOR STACK STACK: DEFS 2 ;OLD STACK STORED HERE ; ;END OF DIRECTORY MODULE ; ;Temporary end statement used only for testing DIRF module. ;Remove before including module in other programs. END DIRF