; ; FMAP.ASM ; (revised 6/12/80) ; ;ORIGINALLY WRITTEN BY WARD CHRISTENSEN ;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 ; ;10/30/79 MODIFIED TO ALLOW FOR 128 DIRECTORY ENTRIES ; (KEITH PETERSEN, W8SDZ). ;12/29/79 CORRECTED ERROR IN CONSTAT TEST ; FOR ABORTING PRINT. (KBP) ;06/12/80 ADD ANI 7FH TO REMOVE FILE ATTRIBUTES ; TO MAKE COMPATIBLE WITH CPM-2. (KBP) ; FCB EQU 5CH ;SYSTEM FCB ; ORG 100H JMP START ;SKIP PROGRAM ID DB '(FMAP 6/12/80)' ;SAVE THE STACK START 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 ;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? STA TEMP ;SAVE JNZ PRTTL ;GOT SOME - PRT TITLE, CONT LXI D,NONMSG CALL WRCON JMP EXIT ; NONMSG DB '++NOT FOUND$' ; ;PRINT TITLE PRTTL LXI D,TTL CALL WRCON CALL CR LDA TEMP ;RELOAD EXTENT JMP SOME ; TTL DB 'FILENAME TYP RC -----GROUPS------$' ; ;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,11 ;NAME 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 MVI B,20 ;REST OF ENTRY LENGTH ; TMOVE2 LDAX D ;GET ENTRY CHAR MOV M,A ;STORE IN TABLE INX D INX H DCR B ;MORE? JNZ TMOVE2 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 ;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 KBD CALL BDOS ;ANY KEY PRESSED? ORA A JNZ 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 XCHG ;TABLE ENTRY TO HL MVI B,8 ;FILE NAME LENGTH CALL TYPEIT ;TYPE FILENAME CALL PERIOD ;SPACE AFTER FN MVI B,3 ;GET THE FILETYPE CALL TYPEIT CALL FILECR 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 ;ALL DONE - PRINT # FILES LDA NFILE CALL XOB LXI D,NMSG CALL WRCON ;CLOSE FILE IF NECESSARY LDA FILESW CPI 'F' JNZ EXIT 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 MVI C,WRCHR CALL BDOS POP H POP D POP B RET ; WRCON MVI C,PRINT JMP BDOS ; 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 E,13 ;PRINT MVI C,2 ;C/R CALL BDOS MVI E,10 ;LF MVI C,2 JMP BDOS ; ;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 ; ;WRITE CHAR IN A TO FILE ;(SAVES ALL REGS INCLUDING A) FILCHR CPI ' ' RZ ;DON'T WRITE BLANKS PUSH PSW LDA FILESW ;WRITING A FILE? CPI 'F' 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 ; NFILE DB 0 ;NUMBER OF FILES PRINTED 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 80H ;OUTPUT ADDR MYFCB DB 0,'NAMES SUB',0 DS 19 DB 0 FILESW DS 1 ;'F' IF WRITING FILE TEMP DS 1 ;SAVE DIR ENTRY DS 60 ;STACK AREA STACK DS 2 ;SAVE OLD STACK HERE ORDER DS 256 ;ORDER TABLE (ROOM FOR 128 NAMES) 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 ; " " 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 ; END 100H