; FILE.ASM ; ; v14 - 01 JUNE 83 - IRV HOFF ; ; ORIGINALLY WRITTEN BY R. RODMAN. RENAMED TO 'FILEFIND' BY ANOTHER ; PERSON IN APRIL 1981. NOW RESTORED TO ORIGINAL INTENDED NAME. ; ; THIS PROGRAM WILL SEARCH ALL USER AREAS OF ALL DRIVES (CAN BE LIMITED ; BY CHANGING THE 'MAXUSR' EQUATE) FOR ANY FILES MATCHING THE REQUEST ON ; THE COMMAND LINE. IT THEN DISPLAYS THOSE FILES. ALLOWABLE USER AREAS ; FOR CP/M ARE 0-15. ; ; ; EXAMPLE: FILE *.COM LISTS ALL .COM FILES ON ALL DRIVES AND ALL AREAS ; ; ; THIS PROGRAM MAKES A DIRECT CALL TO THE 'SELDSK' ROUTINE OF THE BIOS ; TO DETERMINE A DRIVE'S EXISTENCE WITHOUT CAUSING A BDOS ERROR. ; ; NOTE: THIS PROGRAM ASSUMES THAT ANY BIOS 'ILLEGAL DRIVE SELECT' TRAPS ; WILL CAUSE THE SYSTEM TO EXECUTE A WARM-BOOT BY JUMPING TO AD- ; DRESS 0. THIS OCCURS ON THE FIRST NON-EXISTANT DRIVE IT TRIES ; TO ACESS WHILE ATTEMPTING TO CHECK 0-15 DRIVES. IF A SELECT ; ERROR BYPASSES THE WARM-BOOT JUMP AT ADDRESS 0, THEN THE TRAP ; IN THIS PROGRAM WILL NOT WORK. IN THAT CASE, SET 'DRVTYPE' TO ; FALSE AND 'MAXDRV' TO THE NUMBER OF DRIVES YOU HAVE. ; ; ; PLEASE RETURN ANY UPDATES TO TECHNICAL CBBS DEARBORN MI (313) 846-6127 ; SO THE FILE WILL BE AVAILABLE TO ALL. ; ; ;======================================================================= ; ; ; 06/01/83 ADDED "searching..." TO SHOW THE REASON FOR NO ACTIVITY ON ; LONGER SEARCHES. REVISED THE ONE OF THE EXIT ROUTINES. ; OTHER MINOR CHANGES. -Irv Hoff ; ; 02/13/83 NOW PRINTS A NORMAL DISPLAY FOR DRIVE/USER AREA WHILE KEEP- ; ING NORMAL COLUMN WIDTH FOR JUSTIFICATION. SEVERAL OTHER ; MINOR CHANGES. ALWAYS STARTS AT FIRST DISK, USER 0, REGARD- ; LESS OF THE CURRENT DISK OR USER NUMBER. IT THEN RETURNS TO ; THE PRESENT DRIVE AND USER AREA. ; - Irv Hoff ; ; 02/02/82 ENABLED PROGRAM TO LOOK AT A SPECIFIC NUMBER OF DRIVES IN ; THE EVENT THE BIOS 'ILLEGAL DRIVE SELECT' IS NOT INCLUDED. ; - Larry Clive ; ; 08/02/81 CLEANED UP FILE AND REMOVED UNNECESSARY CODE. THANKS TO TOM ; AND SHAWN FOR ADDING SOME MORE GOODIES. ; - Dave Hardy ; ; 07/31/81 MODIFIED 'AVAIL' ROUTINE TO ABORT ONLY ON CTL-C FROM THE ; CONSOLE. CLEANED UP THE FILE, RESTORED ORIGINAL AUTHOR'S ; NAME TO THE HEADING. ADDED TUTORIAL TO BE PRINTED IF FILE- ; NAME (FCB) FIELD (FN.FT TAIL OF THE COMMAND LINE) IS BLANK ; (OMITTED BY THE INEXPERIENCED USER). SUBSTITUTED IN-LINE ; PRINT ROUTINE WHERE APPROPRIATE FOR ALL PRINTED MESSAGES. ; PRINTS MESSAGE ON EXIT IF NO FILES WERE FOUND (MATCHED). ; - Thomas V. Churbuck ; ; 07/30/81 MODIFIED 'AVAIL' ROUTINE TO ABORT PROGRAM IF ANY CHARACTER ; IS TYPED FROM THE CONSOLE. MODIFED USER NUMBER ROUTINE TO ; INCLUDE LEADING 0 WHEN PRINTING USER #'S 0-9 TO LINE UP ; PRINTOUT. - Shawn Everson ; ; ;======================================================================= ; ; ; DEFINE TRUE AND FALSE ; YES: EQU 0FFH NO: EQU 0 ;..... ; ; ; SET THE FOLLOWING AS DESIRED: ; SHOWSYS: EQU YES ;'YES' IF WANT TO SHOW SYSTEM FILES DRVTYP: EQU YES ;'YES' IF BIOS HAS 'ILLEGAL DRIVE SELECT' ;TRAP. SET 'NO' IF NO TRAP IN BIOS, ;THEN SET 'MAXDRV' TO NUMBER OF DRIVES TO ;SEARCH THROUGH FOR THE REQUESTED FILE. MAXDRV: EQU 2 ;NUMBER OF DRIVES TO SEARCH THROUGH MAXCOL: EQU 4 ;MAX NUMBER OF COLUMNS DESIRED IN DISPLAY MAXUSR: EQU 15 ;MAX USER # TO BE CHECKED (0-15 POSSIBLE) ;..... ; ; ; DEFINE SOME MISCELLANEOUS VALUES: ; BASE: EQU 0 ;SET TO BASE ADDRESS OF YOUR CP/M BDOS: EQU BASE+5 ;CP/M BDOS ENTRY POINT CR: EQU 0DH ;ASCII RETURN FCB: EQU BASE+5CH ;CP/M FILE CONTROL BLOCK ADDRESS LF: EQU 0AH ;ASCII LINEFEED TBUF: EQU BASE+80H ;DMA BUFFER ADDRESS ;..... ; ; ; DEFINE SOME BDOS FUNCTIONS: ; CONIN: EQU 1 ;CONSOLE INPUT FUNCTION CONOUT: EQU 2 ;CONSOLE OUTPUT FUNCTION PRINT: EQU 9 ;PRINT STRING AT CONSOLE FUNCTION CONSTAT: EQU 11 ;GET CONSOLE STATUS FUNCTION RTNVER: EQU 12 ;RETURN VERSION NUMBER FUNCTION SRCHFST: EQU 17 ;SEARCH FOR FIRST FUNCTION SRCHNXT: EQU 18 ;SEARCH FOR NEXT FUNCTION SETIOB: EQU 24 ;SET I/O BYTE SETDMA: EQU 26 ;SET DMA ADDRESS FUNCTION SETUSR: EQU 32 ;SET/GET USER CODE FUNCTION ;..... ; ; ORG BASE+100H ; ; LXI H,0 ;SET 'HL' TO ZERO DAD SP ;GET STACK POINTER INTO 'HL' SHLD STACK ;SAVE FOR EXIT TO 'CCP' STACK LXI SP,STACK ;SET UP LOCAL STACK CALL ILPRT ;PRINT SIGN-ON MESSAGE DB CR,LF,'FILE v14 - CTL-X to abort',CR,LF,0 LDA FCB+1 ;CHECK FOR FILENAME ON COMMAND LINE CPI ' ' JZ NONAME CALL ILPRT DB 'searching...',0 ; SETUP: LDA 0004H ;SAVE USER/DRIVE # STA UDNUM RRC ;1ST 4 BITS GIVE CURRENT USER # RRC RRC RRC ANI 0FH ;'AND' OFF THE DRIVE BITS STA CUN ;SAVE CURRENT USER # STA CTU ;SAVE AS CURRENT TRY #,TOO MOV B,A MVI A,MAXUSR CMP B JC OUTSIDE XRA A STA CTU ;SET CURRENT TRY USER TO 0: STA ORIGCTU ;SET ORIGINAL 'CTU' TO SAME MVI A,MAXUSR STA MAXTEMP ;SET MAXIMUM USER NUMBER TO 'MAXUSR' ; SBOOT: LHLD 0000H+1 ;GET WARM-BOOT ADDRESS SHLD WBOOT ;SAVE WARM-BOOT ADDRESS LXI D,SETIOB ;GET ADDRESS FOR 'SET I/O BYTE' DAD D ;INDEX INTO BIOS SHLD DSKSEL+1 ;GET JUMP TO BIOS 'DSKSEL' ROUTINE ; ; ; THE FOLLOWING CODE SETS A TRAP AT THE WARM-BOOT JUMP, SO THAT ; ANY 'ILLEGAL DRIVE SELECT' TRAPS IN THE BIOS WILL BE DEFEATED. ; LXI H,DONE ;REPLACE WARM-BOOT POINTER WITH TRAP SHLD 1 LXI D,TBUF MVI C,SETDMA CALL BDOS ;SET DMA ADDRESS MVI A,0 ;START LOOKING ON 0 DRIVE ("A") STA TRYDRV ;SET UP TO TRY DRIVE '0' FIRST ; TRY: MOV C,A ;TRY TO SELECT DRIVE CALL DSKSEL MOV A,L ORA H JZ DONE ;IF 'HL' IS 0, THEN NO MORE DRIVES LDA TRYDRV INR A STA TRYDRV ;GET READY FOR NEXT DRIVE, TOO STA FCB ;STORE 1+DRIVE# IN FCB (1=A, 2=B, ETC.) ; NXTUSR: LDA CTU ;SET USER TO 'CTU' VIA A BDOS CALL MOV E,A MVI C,SETUSR CALL BDOS ; AVAIL: MVI C,CONSTAT ;CHECK TO SEE IF KEY PRESSED CALL BDOS ORA A JZ NOPRESS ;IF NO KEY PRESSED, THEN CONTINUE MVI C,CONIN ;IF KEY PRESSED, THEN CHECK FOR ABORT CALL BDOS CPI 'C'-40H ;IS IT CTL-C? JZ AVAIL1 ;IF NO, THEN CONTINUE CPI 'X'-40H ;IS IT CTL-X? ; AVAIL1: JNZ NOPRESS ;IF NO, THEN CONTINUE CALL ILPRT ;IF YES, THEN PRINT ABORT MESSAGE DB CR,LF,CR,LF,'++ ABORTED ++',0 JMP DONE1 ;..... ; ; NOPRESS: LXI D,FCB MVI C,SRCHFST CALL BDOS ;CHECK FOR DIRECTORY MATCH WITH 'FCB' CPI 0FFH ;A-REG. HAS 0-3 IF FILE FOUND ELSE 0FFH JZ NXT ;DO NEXT DRIVE IF NO MORE MATCHES FOUND CALL SHOFIL ;IF MATCH FOUND, DISPLAY THE FILENAME ; SNEXT: MVI C,SRCHNXT CALL BDOS ;CHECK FOR NEXT MATCH WITH FCB CPI 0FFH JZ NXT ;NO MORE MATCHES? THEN DO NEXT DRIVE CALL SHOFIL ;IF MATCH FOUND, DISPLAY THE FILENAME JMP SNEXT ;CONTINUE UNTIL NO MORE MATCHES FOUND ; NXT: LDA CTU ;INCREMENT CURRENT TRY USER NUMBER INR A STA CTU MOV B,A LDA MAXTEMP CMP B JNC NXTUSR ;DO NEXT USER NUMBER IF ALL NOT DONE LDA ORIGCTU ;ELSE RESET USER # AND DO NEXT DRIVE STA CTU MVI C,RTNVER CALL BDOS ;SEE IF CP/M VERSION 1.4 OR 2.X MVI C,5 ;(IF CP/M 1.4, THEN BIOS MUST RETURN AN ORA A ;ERROR IF BAD DRIVE #, ELSE WON'T WORK) JZ FOUR ;IF 1.4 THEN FOUR DRIVES MAXIMUM ; IF DRVTYP MVI C,16+1 ;OTHERWISE 16 DRIVES MAXIMUM UNLESS ENDIF ;NO BIOS TRAP. ; IF NOT DRVTYP ;IF NO TRAP THEN MAX DRIVES NUMBER IS MVI C,MAXDRV ;IS SET MANUALLY. ENDIF ; FOUR: LDA TRYDRV CMP C JC TRY ;CONTINUE UNTIL ALL DRIVES CHECKED... ; ; ; ALL DONE NOW, RETURN TO CP/M ; DONE: LDA MFLAG ;SEE IF ANY FILES FOUND ORA A JNZ DONE1 ;IF YES, THEN DONE, SO EXIT CALL ILPRT ;IF NO, THEN SAY NONE FOUND FIRST DB CR,LF,CR,LF,'++ FILE NOT FOUND ++',0 ; DONE1: CALL ILPRT DB CR,LF,0 ;TURN UP A LINE LHLD WBOOT ;RESTORE WARM-BOOT JUMP SHLD 1 LDA UDNUM ;RESTORE USER/DRIVE NUMBER STA 4 ANI 0FH MOV C,A ;PUT THE DRIVE INTO 'C' CALL DSKSEL ; EXIT: JMP 0000H ;THEN RETURN TO CP/M VIA WARM REBOOT ;..... ; ; NONAME: CALL ILPRT ;ELSE, PRINT HELP MESSAGE AND EXIT DB CR,LF DB ' You must specify the file(s) you',CR,LF DB ' want to find. Wildcards are ok.',CR,LF,LF DB ' EXAMPLE: FILE MODEM7.DOC',CR,LF DB ' FILE MOD*.*',CR,LF DB ' FILE *.ASM',CR,LF DB ' FILE *.*',CR,LF,0 ; EXITSPCL: LHLD STACK ;GET THE ORIGINAL 'CCP' STACK ADDRESS SPHL ;SET STACK POINTER FROM 'HL' ADDRESS RET ;RETURN TO THE 'CCP' STACK ;..... ; ; OUTSIDE: LDA CUN STA CTU ;SET CURRENT TRY USER TO CURRENT USER # STA ORIGCTU ;SET ORIGINAL 'CTU' TO SAME STA MAXTEMP ;SET MAXIMUM USER NUMBER TO CURRENT JMP SBOOT ;AND CONTINUE... ; SHOFIL: MOV L,A ;GET FILENAME TO DISPLAY FROM DIRECTORY MVI H,0 ;WHICH CP/M PUTS AT DMA ADDRESS DAD H ;("A" REGISTER HAS RELATIVE POSITION OF DAD H ;NAME WITHIN DIRECTORY RECORD) DAD H DAD H DAD H ;MULTIPLY 'A' BY 32 TO POINT TO START OF LXI D,TBUF ;FILENAME DAD D ;NOW POINT TO FILENAME XCHG ;SAVE FILENAME POINTER IN 'DE' ; IF NOT SHOWSYS ;THEN IGNORE 'SYS' FILES LXI H,10 DAD D ;POINT TO 'SYS' FILE ATTRIBUTE MOV A,M ANI 80H ;CHECK FOR 'SYS' TYPE FILE RNZ ;DON'T DISPLAY IF 'SYS' ATTRIBUTE IS SET ENDIF ; LDAX D ;GET USER NUMBER INX D PUSH PSW ;SAVE THE USER NUMBER CPI 9+1 ;IS USER NUMBER = 0 THRU 9? JNC SHOFIL1 ;IF NOT, EXIT MVI A,' ' CALL AOUT ;PRINT THE EXTRA SPACE ; SHOFIL1: LDA TRYDRV ;GET THE DISK DRIVE ADI 'A'-1 ;CONVERT BINARY TO ASCII CALL AOUT ;DISPLAY DRIVE (A-P) POP PSW ;SAVE THE USER NUMBER CPI 9+1 ;0-9 ? JC USRL ;IF YES, EXIT ; SUI 10 ;USER NUMBER = 10 THRU 15 PUSH PSW ;REMAINDER IS <10 MVI A,'1' CALL AOUT2 ;PRINT A LEADING '1' POP PSW ;GET THE REMAINDER BACK ; USRL: ADI '0' ;CONVERT FROM BINARY TO ASCII # CALL AOUT2 ;PRINT DIGIT ; NOUSR: MVI A,':' ;FENCE CHARACTER CALL AOUT2 ;DISPLAY A ':' TO LOOK NICE ;;; MVI A,' ' ;;; CALL AOUT2 ;SEPARATE IT FROM THE FILE NAME MVI B,8 ;(8 CHARACTERS OR LESS IN FILENAME) ; PFN: LDAX D ;NOW PRINT THE FILENAME.. INX D CALL AOUT2 ;..ONE CHARACTER AT A TIME DCR B JNZ PFN ;CONTINUE FOR ALL 8 CHARACTERS MVI A,'.' CALL AOUT2 ;DISPLAY THE '.' BEFORE THE FILETYPE MVI B,3 ;NOW DO THE SAME FOR THE FILETYPE ; PXT: LDAX D INX D CALL AOUT2 DCR B JNZ PXT LDA COLUMN ;PRINT MAXCOL COLUMNS ACROSS THE SCREEN DCR A JZ DOCRLF STA COLUMN CALL TWOSPC ;PRINT TWO SPACES TO MAKE IT NEAT MVI A,0FFH ;SHOW THAT A FILE WAS FOUND STA MFLAG ;SUPPRESSES 'NOT FOUND' MESSAGE RET ;..... ; ; DOCRLF: MVI A,MAXCOL ;RESET COLUMN NUMBER AFTER LAST COLUMN STA COLUMN MVI A,CR CALL AOUT2 MVI A,LF CALL AOUT2 RET ;..... ; ; TWOSPC: MVI A,' ' CALL AOUT2 MVI A,' ' JMP AOUT2 ; AOUT: MOV B,A ;SAVE THE CHARACTER FOR NOW LDA FIRST ORA A JNZ AOUT1 CALL ILPRT DB CR,LF,CR,LF,0 MVI A,1 STA FIRST ; AOUT1: MOV A,B ; AOUT2: PUSH B ;SEND A CHARACTER TO THE CONSOLE PUSH D PUSH H ;SAVE REGISTERS IN CASE BDOS EATS THEM ANI 7FH ;STRIP PARITY BIT MOV E,A MVI C,2 CALL BDOS ;PRINT THE CHAR. IN 'A' ON THE CONSOLE POP H POP D POP B ;RESTORE THE REGISTERS RET ;..... ; ; ; INLINE PRINT ROUTINE ; ILPRT: XTHL ;SET HL TO POINT TO MESSAGE ; ILPLP: MOV A,M ;GET A CHARACTER FROM MESSAGE CALL AOUT2 ;OUTPUT IT INX H ;POINT TO NEXT CHARACTER MOV A,M ;CHECK FOR END OF MESSAGE ORA A ; (00H MARKS END OF MESSAGE) JNZ ILPLP XTHL ;GET PROPER RETURN ADDRESS ONTO STACK RET ;THEN RETURN TO PROGRAM ;..... ; ; COLUMN: DB MAXCOL ;COLUMN COUNTER CTU: DB 0 ;CURRENT TRY USER NUMBER CUN: DB 0 ;CURRENTLY LOGGED-IN USER NUMBER FIRST: DB 0 ;FIRST TIME USE OF 'AOUT' (FOR CR/LF) MAXTEMP: DB 0 ;MAXIMUM TRY USER NUMBER MFLAG: DB 0 ;FLAG SET TO NON-ZERO IF FILE IS FOUND ORIGCTU: DB 0 ;ORIGINAL CURRENT TRY USER NUMBER TRYDRV: DB 0 ;NUMBER OF DRIVE BEING TRIED UDNUM: DB 0 ;USER/DRIVE NUMBER IS SAVED HERE ; DSKSEL: DB 0C3H ;'JMP' INSTRUCTION DW 00000H ;(BIOS'S DSKSEL ADDRESS IS STORED HERE) ;(BYPASSES BDOS TO AVOID "BDOS CALL") WBOOT: DW 0000H ;CP/M WARM-BOOT ADDRESS IS SAVED HERE ;..... ; ; DS 64 ;32 LEVEL STACK SHOULD BE ENOUGH ROOM STACK: DS 2 ;..... ; ; END OOT ADDRESS IS SAVED HERE ;..... ; ; DS 64 ;32 LEVE