;LDIR.Z80 by Trevor Marshall.....Stolen from SD-50.ASM ; v1.0 7/23/83 ;Created to give a library module for many purposes..including cataloging ;Send any fixes to Thousand Oaks Tech RBBS (805) 492 5472 ; FALSE EQU 0 TRUE EQU NOT FALSE ;******************************** ;* * ;* USER OPTION SPECIFICATIONS * ;* * ;******************************** ; NPL EQU 4 ;# of names per line (max of 3 for 64x16) ;(max of 4 for 80x24) ; BDOS equates CPM EQU 5 BDOS EQU 5 FCB EQU 5CH ;FCB1 RDCHR EQU 1 ;Read char from console WRCHR EQU 2 ;Write char to console CONST EQU 11 ;Check cons stat RESET EQU 13 ;Reset disk system SELDSK EQU 14 ;Select disk OPEN EQU 15 ;0FFH=not found CLOSE EQU 16 ; " " SEARCH EQU 17 ; " " NEXT EQU 18 ; " " READ EQU 20 ;not 0 = EOF WRITE EQU 21 ;not 0 = disk full MAKE EQU 22 ;0FFH = directory full CURDSK EQU 25 ;Get currently logged disk name SETDMA EQU 26 ;Set current DMA GALLOC EQU 27 ;Get address of allocation vector CURDPB EQU 31 ;Get current disk parameters CURUSR EQU 32 ;Get currently logged user number (2.x only) ; START: LD HL,0 LD (LBTOTL),HL LD (LMTOTL),HL ;On entry the filenames are in FCB1...make them .LBR LD HL,FCB+9 LD (HL),'L' INC HL LD (HL),'B' INC HL LD (HL),'R' ; LD DE,80H ;set def dir bfr LD C,SETDMA CALL CPM ; LD DE,FCB ;Now ask for matching directory entries LD C,SEARCH ;look for the first CALL CPM INC A JR NZ,SOME.THERE LD HL,NOT.FOUND ;else quit LD B,22 CALL TYPEIT JP EXIT SOME.THERE: ;calculate filename address DEC A ;inced above RLC A ;A*2 RLC A RLC A RLC A ;A*16 RLC A ;A*32 ADD 80H ;now pointing at name LD D,0 LD E,A ;get it to DE INC DE ;point at the name ;See if it is the 0 extent, if not skip this name LD HL,11 ;point at extent ADD HL,DE LD A,(HL) ;get it OR A JR NZ,GET.NEXT XOR A LD (LNCNT),A CALL LBRTST ;Else print the details ;Done one file, now look for more GET.NEXT: LD DE,80H ;first reset the DMA to 80h LD C,SETDMA CALL CPM ; LD C,NEXT LD DE,FCB CALL BDOS INC A JR NZ,SOME.THERE ;else exit EXIT: CALL LBEXIT ;after printing the summaries ERROR.EXIT: JP 0 NOT.FOUND: DB '++ Library not found ++',0dh,0ah ;************** UTILITY SUBROUTINES ************************* ;* Print HL in decimal with leading zero suppression DECPRT: SUB A ;Clear leading zero flag LD (LZFLG),A LD DE,-1000 ;Print 1000's digit CALL DIGIT LD DE,-100 ;Etc. CALL DIGIT LD DE,-10 CALL DIGIT LD A,'0' ;Get 1's digit ADD L JP TYPE DIGIT: LD B,'0' ;Start off with ASCII 0 DIGLP: PUSH HL ;Save current remainder ADD HL,DE ;Subtract JP NC,DIGEX ;Quit on overflow POP AF ;Throw away remainder INC B ;Bump digit JP DIGLP ;Loop back DIGEX: POP HL ;Restore pointer LD A,B CP '0' ;Zero digit? JP NZ,DIGNZ ;No, type it LD A,(LZFLG) ;Leading zero? OR A LD A,'0' JP NZ,TYPE ;Print digit LD A,(SUPSPC) ;Get space suppression flag OR A ;See if printing file totals RET Z ;Yes, don't give leading spaces JP SPACE ;Leading zero...print space DIGNZ: LD (LZFLG),A ;Set leading zero flag so next zero prints JP TYPE ;And print digit ; ;-------------- CRLF: LD A,0DH ;Send CR CALL TYPE LD A,0AH ;Send LF JP TYPE ;Exit to caller from TYPE ;---------- FPAD: CALL TYPE ;Print it, fall into space SPACE: LD A,' ' ;Fall through to TYPE ;* Output character in A to console, and optionally to printer and/or ;* the output file. TYPE: PUSH BC PUSH DE PUSH HL LD C,2 LD E,A CALL CPM POP HL POP DE POP BC RET ;* Print a string at HL of length B TYPEIT: LD A,(HL) CALL TYPE INC HL DEC B JP NZ,TYPEIT RET ;* Print string terminated with last byte high on console. PRINT: LD A,(DE) PUSH AF AND 7FH CALL TYPE POP AF OR A RET M INC DE JP PRINT ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; SUBROUTINES to read library file directory ; ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ;Compare routine COMPR: PUSH HL ;Save table addr LD E,(HL) ;Load low order INC HL LD D,(HL) ;Load high order INC HL LD C,(HL) INC HL LD B,(HL) ; BC,DE now point to entries to be compared for L characters COMP: EX DE,HL LD E,A ;Get count CMPLP: LD A,(HL) AND 7FH LD D,A LD A,(BC) AND 7FH CP D INC HL INC BC JP NZ,NOTEQL ;Quit on mismatch DEC E ;Or end of count JP NZ,CMPLP NOTEQL: POP HL RET ;Cond code tells all, Z=match ; ENTRYL ;Entry here from below, on multiple file looping LD HL,(LCOUNT) LD A,H ;Is this the last file? OR L RET Z ;if so return to mainline code DEC HL ;Dock file count LD (LCOUNT),HL PUSH BC LD HL,(NEXTL) LD A,11 CALL COMPR ;Does this entry match next one? POP BC JP NZ,LBRTST ;No, print it INC HL INC HL ;Skip since highest extent comes last in list LD (NEXTL),HL JP ENTRYL ;Loop back for next lowest extent ; ; Exit Library member printing ; LBEXIT LD HL,(LMTOTL) LD A,H OR L RET Z PUSH HL ;Save Member count XOR A ;Get a zero to... LD (SUPSPC),A ;Suppress leading spaces in totals CALL CRLF CALL CRLF LD DE,CONTM ;Print "There are " CALL PRINT POP HL ;GET TOTAL MEMBER COUNT BACK CALL DECPRT LD DE,MFILES ;PRINT "Members in " CALL PRINT LD HL,(LBTOTL) CALL DECPRT LD DE,LIBR CALL PRINT ; LD DE,LLENMSG CALL PRINT ;Print " with " LD HL,(L2LENLOC) ;GET TOTAL LENGTH OF .LBR (IN SECTORS) ***** PUSH HL XOR A LD (SUPSPC),A ;SUPRESS LEADING SPACES ;Now have the # of sectors in HL..will cahnge it to kBytes LD A,L ;save the old LSByte RR H RR L ;/2 OR A RR H RR L ;/4 OR A RR H RR L ;/8 now in k AND A,00000111B ;do we have a remainder? JR Z,PUT.IT3 INC HL ;Remainder -> INC HL (Also handles < 1k ) PUT.IT3: CALL DECPRT LD HL,0 LD (LLENLOC),HL ;ZERO OLD COUNT ***** LD (L2LENLOC),HL POP HL LD DE,LLENMSG2 CALL PRINT ;Print " sectors total." RET ; ;* Valid library..dump it out ; on entry DE points to FCB+1 (start of the name) LBRTST: PUSH DE LD HL,MNPL LD A,(LNCNT) CP (HL) CALL NZ,CRLF CALL CRLF LD HL,LFMSEP ;say 'Library file members for:' LD B,31 CALL TYPEIT POP HL ;get ptr to start of name PUSH HL ;save it again LD B,8 ;File name length CALL TYPEIT LD A,'.' ;Period after FN CALL TYPE LD B,3 ;Display 3 characters of filetype CALL TYPEIT CALL CRLF POP HL ;get name again ; ; Saves the library file name into LBRFCB ; first set the drive # LD A,(FCB) ;from FCB1 LD DE,LBRFCB ;TO LD (DE),A INC DE LD B,11 ;name+extent CALL MOVE ;DO THE MOVE from (HL) to (DE) EX DE,HL LD B,25 ;then zero rest of FCB CLMFCB LD (HL),0 INC HL DEC B JP NZ,CLMFCB CALL SETLDMA ;set DMA to lib bffr LD DE,LBRFCB ;POINT TO FILE LD C,OPEN ;GET FUNCTION CALL CPM ;OPEN IT LD C,READ LD DE,LBRFCB CALL CPM ; CALL SETFOP LD HL,LBBUF LD A,(HL) OR A JP Z,CKLDIR ;check directory present and type it BADLBR LD HL,NLBRF ;say 'NOT a library file' LD B,25 CALL TYPEIT LMLEXI CALL LBCLOSE ;close the file PUSH DE PUSH HL LD HL,MNPL LD A,(LNCNT) CP (HL) CALL NZ,CRLF LD DE,ILFMSG CALL PRINT ;PRINT "This library contains " LD HL,(LLENLOC) PUSH HL XOR A LD (SUPSPC),A ;SUPRESS LEADING SPACES ;Now have the # of sectors in HL..will cahnge it to kBytes LD A,L ;save LSByte RR H RR L ;/2 OR A RR H RR L ;/4 OR A RR H RR L ;/8 now in k AND A,00000111B ;do we have a remainder? JR Z,PUT.IT2 INC HL ;Also handles <1k PUT.IT2: CALL DECPRT POP DE LD HL,(L2LENLOC) ADD HL,DE LD (L2LENLOC),HL LD HL,0 LD (LLENLOC),HL LD DE,ILFMS2 CALL PRINT ;PRINT "kbytes total." POP HL POP DE LD A,0FFH LD (SUPSPC),A ;PUT BACK LEADING SPACES JP ENTRYL NLBRF DEFB '++Not a LIBRARY file.++',13,10 ; ; Close the library file ; LBCLOSE LD DE,LBRFCB LD C,CLOSE CALL CPM RET ; ; SETLDMA - Set the Library file DMA adderss ; SETLDMA LD DE,LBBUF LD C,SETDMA CALL CPM RET ; ; CKLDIR - check to see if there indeed is a LBR file ; directory and barf if not! ; CKLDIR: LD B,11 ;len of file name LD A,' ' ;space INC HL CKDLP: CP (HL) JP NZ,BADLBR DEC B INC HL JP NZ,CKDLP ; ; The first entry in the LBR directory is indeed blank. ; Now see if the directory size is >0 ; LD E,(HL) ;file starting location low INC HL ;must be zero here LD A,(HL) ;file starting location high OR E ;must be zero here also JP NZ,BADLBR INC HL LD E,(HL) ;get library size low INC HL ;point to library size high LD D,(HL) ;get library size high LD A,D OR E ;library must have some size JP Z,BADLBR DEC DE EX DE,HL LD (SLFILE),HL LD HL,(LBTOTL) INC HL LD (LBTOTL),HL LD A,(MNPL) LD (LNCNT),A ;Reset names per line counter LD B,3 LD HL,17 ADD HL,DE LD A,(MNPL) LD (LNCNT),A ;Reset names per line counter JP LMTEST LFMLOP LD HL,(SLFILE) ;GET LD A,L OR H JP Z,LMLEXI DEC HL LD (SLFILE),HL CALL SETLDMA LD C,READ LD DE,LBRFCB CALL CPM ; CALL SETFOP LD B,4 ;GET FILE COUNT PER SECTOR LD HL,LBBUF ;GET BUFFER STARTING ADDRESS LMTEST LD A,(HL) ;Get member open flag OR A ;TEST FOR OPEN JP Z,PRMNAM LMTESA LD DE,32 ;Member not open get offset ADD HL,DE ;to next and add it in. DEC B ;is buffer empty ? JP NZ,LMTEST ;No so test next entry JP LFMLOP ;Yes get next buffer... PRMNAM PUSH HL ;Print member NAME and SIZE PUSH BC LD HL,LNCNT LD A,(MNPL) CP (HL) JP NZ,PRMNA1 ; IF NPL <= 3 LD A,3 ;If printing less than 4 wide CP (HL) JP C,PRMNA1 LD A,(LBRFCB) ;.. precede new line with drive name ADD 'A'-1 CALL TYPE LD A,':' ;Tag header with a colon and a space CALL FPAD ;..and exit back to ENTRY ENDIF ; PRMNA1 POP BC POP HL PUSH HL PUSH BC INC HL LD B,8 ;File name length CALL TYPEIT LD A,'.' ;Period after FN CALL TYPE LD B,3 ;Display 3 characters of filetype CALL TYPEIT INC HL INC HL LD E,(HL) INC HL LD D,(HL) EX DE,HL ;If report size enabled, output the size of the individual file. PUSH DE PUSH HL PUSH HL LD HL,(LLENLOC) PUSH HL POP DE POP HL ADD HL,DE LD (LLENLOC),HL POP HL POP DE ;Now have the # of sectors in HL..will cahnge it to kBytes XOR A LD A,L ;save LSByte RR H RR L ;/2 OR A RR H RR L ;/4 OR A RR H RR L ;/8 now in k AND A,00000111B ;do we have a remainder? JR Z,PUT.IT ;if not then print it INC HL ;Also handles <1k PUT.IT: CALL DECPRT ;..go print it LD A,'k' ;..and follow with k CALL TYPE LD A,',' CALL TYPE ;* At least one more file to output - can we put it on the current line? LD HL,(LMTOTL) INC HL LD (LMTOTL),HL LD A,(LNCNT) DEC A LD (LNCNT),A PUSH AF CALL NZ,SPACE ;If room left, output the space character POP AF POP BC POP HL JP NZ,LMTESA ;.. and go output another file ;*Current line full, start a new one. LD A,(MNPL) LD (LNCNT),A ;Reset names per line counter CALL CRLF ;Space down to next line JP LMTESA ; ; Move characters from 'HL' to 'DE' length in 'B' ; MOVE: LD A,(HL) ;GET A CHAR LD (DE),A ;STORE IT INC HL ;TO NEXT "FROM" INC DE ;TO NEXT "TO" DEC B ;MORE? JP NZ,MOVE ; YES, LOOP RET ; NO, RETURN ; ; ;* Initialized data area LFMSEP db ' Library file members for : ' LBRTYP db 'LBR' CONTM DEFB ' There are',' '+80H MFILES DEFB ' Member Files in',' '+80H LIBR DEFB ' Library(s',')'+80H LLENMSG DEFB ' totalling',' '+80H LLENMSG2 DEFB ' kBytes','.'+80H ILFMSG DEFB ' This library contains',' '+80H ILFMS2 DEFB ' kBytes','.'+80H ;* Uninitialized data area LZFLG DEFS 1 ;0 when printing leading zeros SUPSPC DEFS 1 ;Leading space flag for decimal routine ; LLENLOC DEFW 0 ;RUNNING TOTAL OF LBR LENGTH (SECS) ***** L2LENLOC DEFW 0 ;"" LMTOTL DEFW 0 LBTOTL DEFW 0 LNCNT DEFB 0 LCOUNT DEFW 0 NEXTL DEFW 0 SLFILE DEFW 0 LBRFCB: DEFS 36 LBBUF DEFS 80H MNPL: DW NPL ;entries per line ; END