; Ward Christenson's FMAP from CP/M UG Vol 8 ; Modified by Trevor Marshall ; Uni W A ; Dept Elec Eng ; to reflect his modifications on the ; CACHE T7 disk ; and to allow compatibility with CDOS ; (up to 512 entries) ; ORG 100H ; JMP START ;SKIP PROGRAM ID CALL START ID: DB 'CDOS 2.35 FMAP Sept 80',0DH,0AH,'$' ;SORTED DIRECTORY MAP PROGRAM ;WITH OPTION OF WRITING FILE OF NAMES ; ;FMAP FN.FT OR JUST MAP ;FMAP FN.FT F TO WRITE A FILE ;ALLOWS '*' OR '?' TYPE SPECIFICATIONS FCB EQU 5CH ;SYSTEM FCB ;SAVE THE STACK START POP D MVI C,9 CALL BDOS LXI H,0 DAD SP ;H=STACK SHLD STACK ;SAVE IT LXI SP,STACK ;GET NEW STACK ;SAVE FILE WRITE REQUEST CHAR LDA FCB+17 STA FILESW ;NO FCB SPECIFIED? LXI H,FCB+1 MOV A,M 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 ;Mod #2 GOTFCB MVI A,'?' STA 68H ;LOOK UP THE FCB IN THE DIRECTORY MVI C,FSRCHF ;GET 'SEARCH FIRST' FNC LXI D,FCB CALL BDOS ;READ FIRST INR A ;WERE THERE ANY? STA TEMP ;SAVE JNZ PRTTL1 ;GOT SOME - PRT TITLE, CONT LXI D,NONMSG CALL WRCON JMP EXIT NONMSG DB '*** No Entries Found ***$' ; Mod #3 PRTTL1 LDA FILESW CPI 'Q' JZ JMP1 CPI 'D' JZ JMP1 CPI 'M' JZ JMP1 ;PRINT TITLE PRTTL LXI D,TTL CALL WRCON CALL CR JMP1: LDA TEMP ;RELOAD EXTENT JMP SOME TTL DB 'FILENAME TYP EX RC -----EXTENT-----$' ;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,81H ;POINT TO BUFFER ;(SKIP TO FN/FT) ADD L ;POINT TO ENTRY MOV L,A ;SAVE (CAN'T CARRY TO H) ;MOVE ENTRY TO TABLE XCHG ;ENTRY TO DE LHLD NEXTT ;NEXT TABLE ENTRY TO HL MVI B,31 ;ENTRY LENGTH TMOVE LDAX D ;GET ENTRY CHAR 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 ;INIT THE ORDER TABLE LXI H,ORDER LXI D,TABLE LXI B,31 ;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 ; Mod #4 LDA FILESW CPI ' ' JZ ENTRY ;IF WRITING A FILE, OPEN THE FILE ; LDA FILESW ; CPI 'F' ; JNZ ENTRY LXI D,MYFCB MVI C,ERASE CALL BDOS LXI D,MYFCB MVI C,FMAKE ;MAKE THE FILE CALL BDOS INR A JNZ ENTRY ;MAKE ERROR CALL ERXIT DB '++FILE MAKE ERROR$' ;PRINT AN ENTRY ENTRY MVI C,CONST ;CK STATUS OF KB CALL BDOS ;ANY KEY PRESSED? DCR A JZ ABORT ;YES, ABORT 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 ; Mod #5 LXI H,0BH DAD D MOV A,M STA NEWONE XCHG ;TABLE ENTRY TO HL LDA FILESW CPI 'D' CZ ADDSUB LDA FILESW CPI 'M' PUSH PSW CZ ADDSUB POP PSW CZ ADDSUB2 MVI B,8 ;FILE NAME LENGTH CALL TYPEIT ;TYPE FILENAME CALL PERIOD ;SPACE AFTER FN MVI B,3 ;GET THE FILETYPE CALL TYPEIT ;Mod #6 LDA FILESW CPI 'D' CZ ADDSUB2 CALL FILECR MOV A,M CALL XOB INX H ;SKIP EXTENT INX H ;SKIP INX H ;UNUSED MOV A,M ;GET REC COUNT DCR A ;FUDGE RAR ;DIVIDE RAR ;..BY 8 RAR ANI 1FH ;DELETE GARBAGE INR A ;MAKE RELATIVE TO 1, NOT 0 MOV B,A ;SAVE AS # EXTENTS MOV A,M ;RELOAD RECORD COUNT CALL XOB ;PRINT RECORD COUNT INX H ;SKIP RECORD COUNT MVI C,0 ;FOR EXTENT SKIP CTL EXTLP MOV A,M ;GET EXTENT BYTE ORA A ;EMPTY? JZ ENDEXT ;..YES CALL XO ;..NO, PRINT IT INR C ;INCR COUNT MOV A,C ;TIME TO SPACE? ANI 3 CZ SPACE INX H ;POINT TO NEXT CHR DCR B ;MORE IN EXTENT? JNZ EXTLP ;YES ;BUMP TOTAL FILE COUNT ENDEXT LDA NFILE ;GET # FILES INR A ;BUMP DAA ;MAKE DECIMAL STA NFILE ;SAVE IT BACK CALL CR ;END, TYPE C/R ;SEE IF MORE ENTRIES LDA COUNT DCR A STA COUNT JNZ ENTRY ;YES, MORE ; Mod #7 LDA FILESW CPI ' ' JZ NXT1 MVI A,'F' STA FILESW ;ALL DONE - PRINT # FILES NXT1: LDA NFILE CALL XOB LXI D,NMSG CALL WRCON ;CLOSE FILE IF NECESSARY LDA FILESW ; Mod #8 ; CPI 'F' ; JNZ EXIT CPI ' ' JZ EXIT XRA A STA NEWONE ; MVI A,'Z'-40H ;EOF CHAR CALL FILCHR ;WRITE IT CALL WRSEC ;WRITE FINAL SECTOR LXI D,MYFCB MVI C,FCLOSE CALL BDOS JMP EXIT NMSG DB 'FILES$' ;HEX OUTPUT W/BLANK XOB CALL XO JMP SPACE ;HEX OUTPUT XO PUSH PSW ;SAVE CHAR RAR RAR RAR RAR CALL NIBBL ;PRINT LEFT NIBBLE POP PSW ;GET VALUE BACK NIBBL ANI 0FH ;ISOLATE NIBBLE CPI 10 ;NUMBER? JC XNUM ;YES ADI 7 ;FUDGE ALPHA HEX XNUM ADI '0' ;MAKE PRINTABLE ;TYPE CHAR IN A TYPE PUSH B PUSH D PUSH H MOV E,A ;Mod #9 MVI C,WRCHR LDA FILESW CPI 'F' JZ NXT2 CPI ' ' NXT2 CZ BDOS POP H POP D POP B RET WRCON MVI C,PRINT JMP BDOS ; Mod #10 ADDSUB MVI A,'$' CALL L03B7 MVI A,'1' CALL L03B7 MVI A,' ' CALL L03BA MVI A,'$' CALL L03B7 MVI A,'2' JMP L03B7 ADDSUB2 MVI A,' ' CALL L03BA MVI A,'$' CALL L03B7 MVI A,'3' JMP L03B7 ; TYPEIT MOV A,M CALL FILCHR ;TO DISK IF REQ'D CALL TYPE INX H DCR B JNZ TYPEIT RET SPACE MVI A,' ' JMP TYPE CR MVI A,0DH CALL TYPE MVI A,0AH CALL TYPE RET ;CR MVI E,13 ;PRINT ; MVI C,2 ;C/R ; CALL BDOS ; MVI E,10 ;LF ; MVI C,2 ; JMP BDOS TEMP DS 1 ;SAVE DIR ENTRY ;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 ;ROUTINES FOR CREATING FILE ; ; Mod #11 ;WRITE CHAR IN A TO FILE ;(SAVES ALL REGS INCLUDING A) L03B7: ; FILCHR CPI ' ' RZ ;DON'T WRITE BLANKS L03BA: PUSH PSW LDA FILESW ;WRITING A FILE? ; CPI 'F' ; JNZ NOFILE CPI ' ' JZ NOFILE LDA NEWONE ORA A JNZ NOFILE ; POP PSW ;GET CHAR PUSH PSW ;SAVE IT BACK PUSH H LHLD BUFAD ;CURRENT BUFFER ADDR MOV M,A INX H SHLD BUFAD MOV A,H ;SEE IF FULL BUFF DCR A CZ WRSEC ;YES, WRITE SECTOR POP H NOFILE POP PSW ;RESTORE CHAR RET ;WRITE A SECTOR WRSEC PUSH B PUSH D LXI D,MYFCB MVI C,FWRTE CALL BDOS ORA A JZ WROK CALL ERXIT DB '++WRITE ERROR$' WROK LXI H,80H ;START OF BUFF SHLD BUFAD POP D POP B RET ;TYPE A PERIOD INTO THE FILE PERIOD MVI A,'.' ;GET PERIOD CALL FILCHR ;WRITE TO FILE JMP SPACE ;WRITE CR/LF INTO FILE FILECR MVI A,13 CALL FILCHR MVI A,10 CALL FILCHR JMP SPACE ;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 DS 30 ;STACK AREA STACK DS 2 ;SAVE OLD STACK HERE NFILE DB 0 ;NUMBER OF FILES PRINTED ; ; 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 ; " " ERASE EQU 19 ;NO RET CODE FREAD EQU 20 ;0=OK, 1=EOF FWRTE EQU 21 ;0=OK, 1=ERR, 2=?, 255=NO DIR SPC FMAKE EQU 22 ;255=BAD FREN EQU 23 ;255=BAD FDMA EQU 26 BDOS EQU 5 REBOOT EQU 0 NEXTT DW TABLE ;NEXT TABLE ENTRY NEWONE DS 1 ;******I think COUNT DB 0 ;ENTRY COUNT SCOUNT DB 0 ;# TO SORT SWITCH DB 0 ;SWAP SWITCH FOR SORT FILESW DS 1 ;'F' IF WRITING FILE BUFAD DW 80H ;OUTPUT ADDR MYFCB DB 0,'NAMES SUB',0 DS 19 DB 0 ;Modified table size for 512 Directory Entries ORDER DS 1024 ;ORDER TABLE TABLE EQU $ ;READ ENTRIES IN HERE END 100H