; DIRR5.ASM - Directory program with print and disk options - 01/07/86 ; ; Based on the Archives-supplied "D.COM" for which the original source ; code and supplier of same cannot be located but may have originally ; been written in 'C' by Rick Rump. ; ; Enhancements written by James R. King December 17,1983 ; ; NOTE: CAN BE USED WITH 8080, 8085 OR Z80 PROCESSORS. ; SUPPORTS BOTH CP/M V2.2 AND CP/M V3.0. - IMH ; ;----------------------------------------------------------------------- ; ; 01/07/86 Adapted to CP/M 3.0 so people with Commodore C128, Osborne ; v5 Executive One, and others with CP/M+ could use it as well as ; those with CP/M 2.2 versions. Suggest you rename it D.COM ; on your working disk, as very easy to type. ; - Irv Hoff W6FFC ; ; 12/09/85 Sorry for the new update so soon. The 'A' option for "all" ; v4 user areas did not work correctly with v3. Pre-distribution ; versions worked fine, until I decided to write some tighter ; code in the options area - then failed to test it adequately ; before release. My apology. Hopefully I was the first to ; notice that problem, when I tried it on somebody else's big ; system. It's fixed now. The 'A' option in conjunction with ; the 'E' and 'S' options are a wonderful feature of this pro- ; gram. - Irv Hoff ; ; 12/07/85 Rewritten for Intel 8080 code. Eliminated need for macro ; v3 libraries, can now be assembled with any normal assembler. ; Added "QUIT" routine so program may be easily aborted, also ; added a help guide. Extensively revised the header section. ; Added a "N" (non-stop) option. Rewrote the options to be ; compatible (where possible) with the SD directory program. ; Now checks both the 4th character of the file name as well ; as the last byte of the extent to see if the file has been ; archived, and displays an 'A' if using the 'E' option which ; shows attributes and archive bits. This all but eliminates ; any need for (or advantage to) any highlighting or reverse ; video. Now has an extra row for the filesize to display ; files over 100k without jamming them against the end of the ; file extent. Made the special printer and terminal routines ; optional with assembly-time equates. Rewrote the stack area ; which was backwards. Numerous other changes. ; - Irv Hoff ; ;----------------------------------------------------------------------- ; NO EQU 0 YES EQU 0FFH ; Some assemblers cannot use NOT NO here ; FALSE EQU NO TRUE EQU NOT NO ; Some assemblers cannot use 0FFH here ; ; ; The following two must be TRUE or FALSE, the YES or NO won't work ; properly with some assemblers, which need a 16-bit value for "IF" con- ; ditionals, while others have to have a 8-bit value (such as 0FFH) for ; YES for DB strings, sorry but that's the only way it can be made to ; work properly with "any assembler". PNTRSP EQU FALSE ; TRUE if using special printer calls VIDEO EQU FALSE ; TRUE if using VIDEO for highligting, ; ; reverse, etc., then set in proper ; ; values for your terminal, starting ; ; at TRMINI: label, below ; ; BDOS equates ; BDOS EQU 0005H ; CP/M BDOS entry point DFCB EQU 005CH ; Default file control block ALTFCB EQU 006CH ; Alternate file control block SBUFFR EQU 5000H ; Location of stolen 'DI' output TBUF EQU 0080H ; Default buffer location ; RDCON EQU 1 ; CP/M console input function WRCON EQU 2 ; Send character to console WRLST EQU 5 ; List output CONST EQU 11 ; Check console status CPMVER EQU 12 ; CP/M version SELDSK EQU 14 ; Select disk drive function CLOSEF EQU 16 ; Close disk file function SRFST EQU 17 ; Search for first FCB match SRNXT EQU 18 ; Search for next FCB match DELETE EQU 19 ; Delete file function WRSEQ EQU 21 ; Write sequentially to disk function MAKEF EQU 22 ; Make file function CURDSK EQU 25 ; Get current disk function STDMA EQU 26 ; Set direct memory access function GETADR EQU 27 ; Get the allocation block address PARMS EQU 31 ; Get disk parameters address GETUSR EQU 32 ; Get (or set) the user code ; ; CR EQU 0DH ; ASCII carriage return LF EQU 0AH ; ASCII line feed FF EQU 0CH ; ASCII form feed ESC EQU 1BH ; ASCII escape code (lead-in) PLINES EQU 56 ; Number of lines for page printer ; ; ;*********************************************************************** ; ; ORG 100H ; ; JMP START ; ; The user flags start at 0103H and can be changed from NO to YES to ; default to that option. ; AFLAG: DB NO ; Checks all user areas CFLAG: DB NO ; Compresses display by suppressing size EFLAG: DB NO ; Extended display - users & attributes FFLAG: DB NO ; Disk file flag NFLAG: DB NO ; Non-stop flag PFLAG: DB NO ; Printer off, YES = default to printer SFLAG: DB NO ; Display system files if YES VFLAG: DB NO ; Shows version number and date ; DB 0,0,0,0 ; Reserved for 4 extra flag bytes ; HEIGHT: DB 24,0 ; Lines per screen NUMROW: DB 4 ; Number of rows per line ; ; ;======================================================================= ; p r i n t e r i n i t i a l i z a t i o n c o d e s ;======================================================================= ; ; Enter the escape codes to be sent to the printer here, such as bold ; type, compressed type, etc. Maximum of 15 user bytes, 16th must = 0. ; Sent to list device prior to sending any characters and only if the ; "$P" (output to list device) option is selected. ; IF PNTRSP PTRONM: DB ESC,'Q' ; C. ITOH compressed (17 cpi) type DB CR,LF ; Flush printer buffer DW 0,0,0,0,0,0 ; Patch area fills to 012fh ; ; ; Enter the escape sequence to be sent to printer at conclusion of ; directory printing to clear the special effects introduced above. ; Maximum is 16 bytes and the last byte must be 0. This is sent after ; all other text has been sent, to restore normal printer attributes. ; PTROFM: DB ESC,'N' ; C. ITOH pica pitch (10 cpi.) select DB CR,LF ; Flush buffer DB FF,CR ; Form feed and flush again DW 0,0,0,0,0 ; Patch area ends with "0" ENDIF ; PNTRSP ; ; ;======================================================================= ; t e r m i n a l p a t c h a r e a b e g i n s h e r e ;======================================================================= ; ; Used to initialize terminal background. This is sent prior to any ; characters fron the directory listing. ; IF VIDEO TRMINI: DB ESC,019H ; Set attributes for normal background DW 0,0 ; During directory screen display. sent DW 0,0 ; To terminal before anything else. DW 0,0,0 ; User gets 15 bytes, 16th must be = 0 ; FGNDON: DB ESC,01FH ; Code required to highlight, underline, DW 0,0,0 ; etc. Sent to terminal before send- ; ing character with bit 7 set ($R/O, ; $SYS or archived) file flag indi- ; cator in screen display. Sequence ; is used for highlighting, underlin- ; ing, inverse video, etc. as desired. ; FGNDOF: DB ESC,019H ; Code to "UNDO" the above after one DW 0,0,0 ; special character has been sent. ; Returns attributes to normal. May ; use the same code "TRMINI" above. ; 8 bytes, must end with 0.be ; CRSRUP: DB CR ; Move cursor to far left column, move DB ESC,0CH ; cursor up one line (HZ1500) Patch DB 0,0,0,0,0 ; area must end with 0. User gets 7 ; 7 bytes, 8th must = 0 ; CLREOL: DB ESC,0FH ; Patch clear to end-of-line code here DW 0,0,0 ; supported by your terminal. Cannot ; exceed 7 bytes, 8th byte must be 0. ; ; ; "TRMUNI" is sent to the terminal after all directory characters have ; been sent to the terminal. this is used to restore the normal terminal ; characteristics. TRMUNI: DB ESC,019H ; Background follows (HZ1500) DW 0,0,0 ; 15 bytes for user to restore normal DW 0,0,0,0 ; screen attributes prior to return to ; CP/M, last byte must be 0. ; PG2MSG: DB CR,LF,0FH ; Sent after hitting space for next page DW 0,0,0,0 ; display, insert carriage return and ; 'clear to end of line' code here. ; Else insert CR,LF ENDIF ; VIDEO ; ; ;======================================================================= ; s t a r t o f m a i n p r o g r a m ;======================================================================= ; ; START: LXI H,0 DAD SP ; Get CCP stack in SHLD STACK ; Save for direct exit to CCP LXI SP,STACK ; Set up the local stack ; ; ; Program to run the directory program, send the directory to the print- ; er printer if 'P' toggle is set, save the directory output to a disk ; file if the 'F' toggle is set, and return to CP/M command without in- ; voking a warm reboot. ; SETUP: LHLD BDOS+1 ; Get BDOS vector in SHLD HERE+1 ; Store in the 'save' routine SHLD LSTOT1+1 ; Store in the printer output routine SHLD SNDC1+1 ; Store in the console output routine LHLD HEIGHT ; Compensate for the [more] message DCX H SHLD HEIGHT ; Screen height minus [more] message LDA NFLAG ; Non-stop flag set to default? ORA A JZ SETUP1 ; If not, exit LXI H,0FFFFH SHLD HEIGHT ; Else prevent any stopping ; ; ; Get command for enhancements portion of program ; SETUP1: LXI H,DFCB+1 ; Point to command line tail MOV A,M ; Get a byte in the accumulator CPI '$' ; Dollar sign there? JZ SETUP2 ; Yes, check the command tail LXI H,DFCB+17 ; Check alternate FCB too MOV A,M ; Get that byte to check for "$" CPI '$' ; Well, is there one here? JNZ CKFNDO ; No, use defaults ; ; ; We scan whichever file control block we find the "$" heading in while ; looking for the printer, file non-stop toggles. (no "$", no scan.) ; Original program will scan file control block for the rest of them. ; SETUP2: INX H ; Bump the pointer to the next byte MVI B,8 ; We will check 9 bytes for options ; SETUP3: PUSH B ; Save the count PUSH H ; Save the memory pointer MOV A,M ; Get a byte from tail (isn't this fun?) ANI 7FH ; Strip off any parity CPI '?' ; Help wanted? JZ HELP ; Exit if help is requested CPI 'F' ; Disk file save flag CZ STSAVF ; Set the flag true CPI 'N' ; Non-stop request CZ NOSTOP ; Set the non-stop flag CPI 'P' ; Want a printer copy? CZ SPFLAG ; Set the printer flag POP H ; Restore memory pointer INX H ; Bump the pointer POP B ; Restore count to DCR B JNZ SETUP3 ; Loop until done ; CKFNDO: LDA FFLAG ; Making a disk file? ORA A CNZ SNITCH ; Yes, set up for data capture LDA PFLAG ; Get the printer toggle flag ORA A ; Is flag set to true? CNZ PTRON ; Turn printer on if so LXI SP,STACK ; Expected location CALL DBEGIN ; Now do the directory JMP EXITJ ; Do the exit routine ;..... ; ; ;======================================================================= ; m a i n o p e r a t i n g l o o p ;======================================================================= ; DBEGIN: CALL SELDRV ; Select proper drive CALL SEARCH ; Search for requested files XRA A LXI D,XTNL10 ; Get address of (?????) in CALL A0B23 ORA L JZ A022D MVI A,1 LXI H,XTNL10 CALL A0B2E JNC A022A CALL A04AA ; A022A: CALL A0665 ; A022D: XRA A LXI D,XTNL0E CALL A0B23 ORA L ; Did we find any files that match? JZ XIT ; Exit if no files to display CALL SIGNON ; Else we are on our way ; XIT: CALL SUMMRY ; Get and display disk parameters RET ; Exit from directory program here ;..... ; ; SPACE1: MVI C,' ' ; ASCII space in for F2OUT ; SP1A: JMP F2OUT ; Send space to console, auto return ; CRLF: MVI C,CR ; ASCII carriage return in for F2OUT CALL F2OUT ; Send the CR MVI C,LF ; ASCII line feed in for F2OUT JMP SP1A ; Send the line feed, auto return ;..... ; ; A0256: LXI H,XTNL42 MOV M,D DCX H MOV M,E DCX H MOV M,B DCX H MOV M,C LXI B,XTNL41 LXI D,XTNL3F CALL CMP16B ; 16B compare sets carry if (BC) < (DE) LHLD XTNL41 RNC ; @@@ added LHLD XTNL3F RET ;..... ; ; GETCMD: LDA DFCB+1 ; Beginning of command tail CPI '?' JNZ GETCME LDA DFCB+2 ; Check 2nd character CPI ' ' JZ HELP ; GETCME: CPI '$' ; Request delimiter there? JNZ A028E ; Skip if not there LXI B,12 ; 12 characters to move PUSH B ; Store 12 on stack LXI D,ALTFCB ; points to alt FCB (destination) LXI B,DFCB+1 ; points to FCB (source) CALL MOVMEM ; Move the FCB to new location LXI H,DFCB+1 ; Back to the first character MVI M,' ' ; Insert an ASCII space there ; ; ; Initialize the options flag area (original toggles) ; A028E: LXI H,FLGIND ; Initialize the options flag area MVI M,0 LXI H,XTNL43 MVI M,0 ; FLSCAN: CALL QUIT ; Want to quit? LXI D,12 LDA XTNL43 CALL A0B0C JC CFLGCK ; Check compressed filesize flag ; LHLD XTNL43 ; = flag MVI H,0 ; Zap but leave in place LXI B,ALTFCB ; Point to alternate file control block DAD B ; Alt FCB address in MOV A,M ; Get first byte STA XTNL44 ; Store it for later reference CPI 'A' ; Want to check all user areas? JNZ C1 ; Not there, check for other commands STA AFLAG ; C1: LDA XTNL44 CPI 'C' ; Check for "compressed" toggle JNZ E1 ; Not there, check for other commands STA CFLAG ; And store it at the proper location ; E1: LDA XTNL44 CPI 'E' ; Check for "extended" toggle JNZ N1 ; Not there, check for other commands STA EFLAG ; And store it for later reference ; N1: LDA XTNL44 CPI 'N' ; Check for non-stop JNZ S1 MVI A,0FFH STA HEIGHT STA HEIGHT+1 ; S1: LDA XTNL44 CPI 'S' ; Want to check system files also? JNZ V1 ; Not there, check for other commands STA SFLAG ; And store it at the proper location ; V1: LDA XTNL44 CPI 'V' JNZ A02F4 STA VFLAG ; A02F4: LXI H,XTNL43 INR M JMP FLSCAN ; Loop until done ;..... ; ; CFLGCK: LDA CFLAG ; Check for filesize ORA A ; Carry flag is set if flag is "YES" JZ ENHCK ; No, check for "extended" LXI H,NUMROW ; Point to number of rows per line INR M ; Add one, file size not being used RET ;..... ; ; ; Here we check for extended option & reduce screen width if EFLAG "YES" ; ENHCK: LDA EFLAG ; Get 'extended' flag in ORA A RZ ; No, finished LXI H,NUMROW ; Byte for number of rows per line DCR M ; Additional information, reduce by one RET ;..... ; ; PAGECK: LXI B,HEIGHT ; 'Number of lines on screen' byte LXI D,LINECT ; Line count storage location CALL CMP16B ; Sets carry if BC ORA A ; Contains ASCII space if "$" delimited ; command follows in alt FCB, else ; drive code if other drive requested JZ WLDCRD ; Default to current drive if empty DCR A ; Reduce by one for disk select function MOV E,A ; In for disk select MVI C,SELDSK ; CP/M disk select function CALL BDOS ; Completes disk select ; WLDCRD: LDA DFCB+1 ; Check for contents of command tail CPI ' ' ; ASCII blank indicates wildcard search JNZ USER ; Skip if no ASCII space MVI C,11 ; Number of bytes to fill PUSH B ; Save the count MVI E,'?' ; Fill with "???????????" for wildcard LXI B,DFCB+1 ; Beginning of area to be filled CALL FILL ; Fill it ; USER: LDA AFLAG ; Get "USER" flag - true if $A appeared in tail RAR ; Set carry flag if false JNC GUSRCD ; Get user code if true - skip if false LXI H,INTFCB ; User code storage location is first byte MVI M,'?' ; ASCII "?" for search of all user areas JMP MKFCB ; Make a file control block ; GUSRCD: LXI D,0FFH ; 0FFH in for "GET" MVI C,GETUSR ; Get/set user function CALL BDOS ; Get current user code in STA INTFCB ; Store user code in memory ; MKFCB: MVI C,11 ; Number of bytes in filename+ext PUSH B ; Save the count in LXI D,INTFCB+1 ; Internal file control block for search parms LXI B,DFCB+1 ; Beginning of dfcb input/output line CALL MOVMEM ; Move the DFCB to the internal FCB ; ; ; Now fill the default file control block with question marks ; MVI C,13 ; contains number of bytes to fill PUSH B ; Save count in on stack MVI E,'?' ; Fill with ASCII "?" LXI B,DFCB ; Point to the default file control block CALL FILL ; Fill the DFCB with ????? MVI C,PARMS ; Get disk parameter address in CALL BDOS LXI D,INTDPB ; Store 15 bytes into INTDPT area MVI B,15 ; RPTFCB: MOV A,M STAX D INX D INX H DCR B JNZ RPTFCB LXI H,STACK ; Get address of stack in SHLD STAKAD ; Save the address of the stack here LHLD DPBDRM ; Get maximum number of entries possible in dir INX H ; Add one for zero offset INX H ; Then another for headroom DAD H ; Double it XCHG ; Now put it in LHLD STAKAD ; Get address of stack in DAD D ; Add them together SHLD LSTLOC ; Store the sum here as pointer for first entry LHLD DPBBLM ; = block mask, = extent mask MVI H,0 ; Eliminate the extent mask INX H ; Add for zero offset MVI C,007H ; Multiplier for use in H2CPWR routine CALL H2CPWR ; Multiply *, times SHLD XTNL21 LHLD DPBDRM ; = number of directory entries possible INX H ; Add one for zero offset SHLD XTNL23 MVI C,10 LXI H,XTNL21 CALL A0AF2 SHLD XTNL25 MVI A,0FFH LXI H,DPBDSM ; Point to disk storage capacity data in DPB CALL A0B2E SBB A STA XTNL27 RET ;..... ; ; ; Search the directory for the files specified on the command line ; SEARCH: LXI D,DFCB ; Point to default file control block MVI C,SRFST ; Search for first match function CALL BDOS ; Get first match at 080H + 32*offset STA NDSRCH ; A*32 = offset from 080H = start pos. ; ; ; Now get all the files that match our requirements written into memory ; as they come into the buffer area at 080H. ; GETONE: LDA NDSRCH ; Get a directory entry in buffer at 080H + offset CPI 0FFH ; Did the last pass reach the end of matches RZ ; And done here if no more matches LDA NDSRCH ; Redundant load gets last offset in ANI 3 ; Strip all but 2l ADD A ; Multiply accumulator by 32 ADD A ; *4 ADD A ; *8 ADD A ; *16 ADD A ; *32 = offset now in ADI 080H ; Dma address + offset = true address of fn.ext MOV L,A ; Put the address in MVI H,0 ; Put 0 in since we are in page 0 SHLD BUFLOC ; Store the buffer location here MOV A,M ; Get the first byte in CPI 0E5H ; Has it been erased? JZ SNEXT ; Search for next match if so LHLD XTNL23 ; Else get (?) in DCX H ; Decrease it one SHLD XTNL23 ; And put the decremented (?) back in same place LHLD BUFLOC ; Get the buffer location in MOV B,H ; And transfer it to MOV C,L CALL A0A59 ; (?) RAR ; Rotate LSB into carry JNC SNEXT ; Search for next match if no carry LXI B,16 ; Number of bytes to move LHLD BUFLOC ; Where to get them DAD B ; Add the count MOV B,H ; Move to MOV C,L ; now = CALL A0A7F LXI B,13 PUSH H LHLD LSTLOC DAD B POP B MOV M,C INX H MOV M,B LHLD XTNL0C DAD B SHLD XTNL0C MVI L,11 PUSH H LHLD BUFLOC INX H MOV B,H MOV C,L LHLD LSTLOC XCHG POP H ; A0465: LDAX B STAX D INX B INX D DCR L JNZ A0465 LHLD BUFLOC ; Get buffer location in LXI B,11 ; Number of characters in filename+ext PUSH H LHLD LSTLOC ; Last used location in DAD B ; Add 11 to last used location POP D LDAX D MOV M,A LHLD XTNL10 INX H SHLD XTNL10 DAD H XCHG LHLD STAKAD ; Get the address of the stack in DAD D PUSH H LHLD LSTLOC ; Get last location used in XCHG ; Now in POP H MOV M,E INX H MOV M,D LXI D,15 ; Number of bytes in memory per filename stored LHLD LSTLOC ; Last location used DAD D ; Add 15 to the last location used SHLD LSTLOC ; And store it for the next pass ; SNEXT: LXI D,0 ; Zap MVI C,SRNXT ; Search for next function call CALL BDOS ; Continue the search beginning at last found STA NDSRCH ; Returns 0FFH if no more matches JMP GETONE ; Get one (more) directory entry that matches ;.... ; ; A04AA: LXI H,XTNL53 MVI M,1 LXI H,1 SHLD XTNL56 LHLD XTNL10 SHLD XTNL6E ; A04BB: XRA A ; Zap LXI H,XTNL53 ; Point to (?) CMP M RNC ; Return if no carry LHLD XTNL53 MVI H,0 LXI B,XTNL54 DAD H ; Multiply by 2 DAD B MOV E,M INX H MOV D,M XCHG SHLD XTNL4B DCX B LDAX B MOV C,A MVI B,0 LXI H,XTNL6C DAD B DAD B MOV E,M INX H MOV D,M XCHG SHLD XTNL4D LDA XTNL53 DCR A STA XTNL53 ; A04ED: LXI B,XTNL4D LXI D,XTNL4B CALL CMP16B ; 16b compare sets carry if (BC) < (DE) JNC A04BB LHLD XTNL4B SHLD XTNL47 LHLD XTNL4D SHLD XTNL49 XCHG LHLD XTNL4B DAD D ; Get XTNL4D + XTNL4B in MVI C,1 CALL A0AF6 DAD H XCHG LHLD STAKAD DAD D MOV E,M INX H MOV D,M XCHG SHLD XTNL4F ; A051C: LXI D,XTNL49 LXI B,XTNL47 CALL CMP16B ; 16B compare sets carry if (BC) < (DE) JC A05C7 ; A0528: LHLD XTNL47 DAD H XCHG LHLD STAKAD DAD D MOV C,M INX H MOV B,M LHLD XTNL4F XCHG CALL CMPR12 CPI 0FFH JNZ A054A LHLD XTNL47 INX H SHLD XTNL47 JMP A0528 ; Loop until done ;..... ; ; A054A: LHLD XTNL49 DAD H XCHG LHLD STAKAD DAD D MOV E,M INX H MOV D,M LHLD XTNL4F MOV B,H MOV C,L CALL CMPR12 CPI 0FFH JNZ A056D LHLD XTNL49 DCX H SHLD XTNL49 JMP A054A ; Loop until done ;..... ; ; A056D: LXI D,XTNL49 LXI B,XTNL47 CALL CMP16B ; 16B compare sets carry if (BC) < (DE) JC A051C LHLD XTNL47 DAD H XCHG LHLD STAKAD DAD D MOV E,M INX H MOV D,M XCHG SHLD XTNL51 LHLD XTNL49 DAD H XCHG LHLD STAKAD DAD D PUSH H LHLD XTNL47 DAD H XCHG LHLD STAKAD DAD D XTHL MOV C,M INX H MOV B,M POP H MOV M,C INX H MOV M,B LHLD XTNL49 DAD H XCHG LHLD STAKAD DAD D PUSH H LHLD XTNL51 XCHG POP H MOV M,E INX H MOV M,D LHLD XTNL47 INX H SHLD XTNL47 LHLD XTNL49 DCX H SHLD XTNL49 JMP A051C ; Back to beginning of big loop ;..... ; ; A05C7: LXI B,XTNL4B LXI D,XTNL49 CALL CMP16B ; 16B compare sets carry if (BC) < (DE) LXI B,XTNL47 LXI D,XTNL4D PUSH H CALL CMP16B ; 16B compare sets carry if (BC) < (DE) POP D CALL A0B05 JNC A0621 LXI B,XTNL4D LXI D,XTNL47 CALL CMP16B ; 16B compare sets carry if (BC) < (DE) JNC A0618 LDA XTNL53 INR A STA XTNL53 MOV C,A MVI B,0 LXI H,XTNL54 DAD B DAD B PUSH H LHLD XTNL47 XCHG POP H MOV M,E INX H MOV M,D LHLD XTNL53 MVI H,0 LXI B,XTNL6C DAD H DAD B PUSH H LHLD XTNL4D XCHG POP H MOV M,E INX H MOV M,D ; A0618: LHLD XTNL49 SHLD XTNL4D JMP A065E ;..... ; ; A0621: LXI B,XTNL49 LXI D,XTNL4B CALL CMP16B ; 16B compare sets carry if (BC) < (DE) JNC A0658 LDA XTNL53 INR A STA XTNL53 MOV C,A MVI B,0 LXI H,XTNL54 DAD B DAD B PUSH H LHLD XTNL4B XCHG POP H MOV M,E INX H MOV M,D LHLD XTNL53 MVI H,0 LXI B,XTNL6C DAD H DAD B PUSH H LHLD XTNL49 XCHG POP H MOV M,E INX H MOV M,D ; A0658: LHLD XTNL47 SHLD XTNL4B ; A065E: JMP A04ED ;..... ; ; A0665: LXI H,0 ; Zap SHLD XTNL84 SHLD XTNL86 ; A066E: LXI B,XTNL10 LXI D,XTNL86 CALL CMP16B ; 16B compare sets carry if (BC) < (DE) JNC A0723 LHLD XTNL86 INX H SHLD XTNL86 DAD H XCHG LHLD STAKAD DAD D PUSH H LHLD XTNL84 INX H SHLD XTNL84 DAD H XCHG LHLD STAKAD DAD D XTHL MOV C,M INX H MOV B,M POP H MOV M,C INX H MOV M,B ; A069D: LXI B,XTNL10 LXI D,XTNL86 CALL CMP16B ; 16B compare sets carry if (DE) < (BC) SBB A PUSH PSW LHLD XTNL84 DAD H XCHG LHLD STAKAD DAD D PUSH H LHLD XTNL86 LXI B,2 DAD H DAD B XCHG LHLD STAKAD DAD D MOV E,M INX H MOV D,M POP H MOV C,M INX H MOV B,M CALL CMPR12 SUI 0 SUI 1 SBB A POP B MOV C,B ANA C RAR JNC A066E LHLD XTNL86 INX H SHLD XTNL86 DAD H XCHG LHLD STAKAD DAD D MOV E,M INX H MOV D,M XCHG SHLD LSTLOC LXI B,13 LHLD LSTLOC DAD B MOV E,M INX H MOV D,M XCHG SHLD XTNL88 LHLD XTNL84 DAD H XCHG LHLD STAKAD DAD D MOV E,M INX H MOV D,M XCHG SHLD LSTLOC LHLD LSTLOC DAD B LXI D,XTNL88 CALL A0AAA LXI B,13 PUSH H LHLD LSTLOC DAD B POP B MOV M,C INX H MOV M,B JMP A069D ; Loop until done ;..... ; ; A0723: LHLD XTNL84 SHLD XTNL0E RET ;..... ; ; A072A: LXI H,XTNL8B MOV M,B DCX H MOV M,C LHLD XTNL8A DAD H XCHG LHLD STAKAD DAD D MOV E,M INX H MOV D,M XCHG SHLD LSTLOC LXI H,XTNL8C MVI M,0 ; A0745: MVI A,10 LXI H,XTNL8C CMP M JC A0769 ; Send filesize when done here LHLD XTNL8C MVI H,0 XCHG LHLD LSTLOC DAD D MOV C,M ; Character in for output CALL CHROUT ; Send a character & hilite if necessary LDA XTNL8C INR A STA XTNL8C CPI 8 JNZ A0745 ; Loop until done ;;; ;;; MVI C,' ' ; *** (PUT A SPACE IF PREFERRED) MVI C,'.' ; *** (PERIOD BETWEEN FILENAMD AND EXT.) ;;; CALL CHROUT JMP A0745 ;..... ; ; ; See if using 'compressed', if not, compute and show file size. ; A0769: LDA CFLAG ; Get compressed size flag in CMA ; Complement the bits in RAR ; Rotate thru carry RNC ; Skip if flag was false ; LXI B,13 ; 13 bytes used if "C" option LHLD LSTLOC ; Get the last address used in DAD B ; Add 13 to it MOV E,M INX H MOV D,M LHLD XTNL25 ; Get filesize CALL A0AD4 MOV B,H MOV C,L MVI E,4 ; *** filesize, plus leading spaces CALL A0B66 ; Compute and display the filesize MVI C,'k' ; Tag the filesize with "k" CALL F2OUT ; Send it to the console device LDA EFLAG ; Want extended display? RAR ; Carry set if flag is YES RNC ; Skip the listing if flag was false LXI B,11 ; 11th byte is dir/sys status byte LHLD LSTLOC ; Get filename pointer in DAD B ; Add offset to get dir/sys status MOV C,M ; Get status byte in MVI B,0 ; Zap MVI E,3 CALL A0B66 ; Compute and display dir/sys status CALL SPACE1 ; Insert a space in display LXI B,3 ; User archive bit (4th char. in name) LHLD LSTLOC ; Address at start of filename DAD B ; Index into the name for archive bit MOV A,M ; Get the character there CPI 80H ; See if high bit is set JC NOTAA ; If not, this file not archived ; SENDA: MVI C,'A' ; Else show it is archived CALL F2OUT JMP NOTDR ; Skip the DRI archive check ; NOTAA: LXI B,10 ; Special DRI archive byte, end of extent LHLD LSTLOC ; Start of filename DAD B ; Index into filename to end of extent MOV A,M ; Get the character at end of extent CPI 80H ; See if the high bit is set JNC SENDA ; If yes, display it CALL SPACE1 ; Else put a blank for archive display ; NOTDR: LXI B,8 ; Count in = 8 LHLD LSTLOC ; Get base address of filename DAD B ; Add offset to filetype PUSH H MOV A,M ; Get first byte of extent in CPI 80H ; Check for R/O status JC NOTRR ; Skip - not R/O file MVI C,'R' ; R/O indicator CALL F2OUT ; Send indicator JMP A07BE ; Do next ; NOTRR: CALL SPACE1 ; A07BE: POP H ; Get address of R/O byte in extent back INX H ; Next byte is the system flag byte MOV A,M ; Get the byte in CPI 080H ; Check for system file MVI C,'S' ; System file, put "S" on screen too JNC F2OUT JMP SPACE1 ; Send space if not system file, done ;..... ; ; SIGNON: LDA VFLAG ; Want to show the version number? ORA A LXI B,VERMSG CNZ SNDCON LDA PFLAG ; Get the printer flag byte INR A ; Set appropriate cpu flags JZ SKPSIN ; Skip the cursor controls if printer on ; IF VIDEO LXI B,TRMINI ; Point to user terminal initialization string CALL SNDCON LXI B,CRSRUP ; Move cursor up one line CALL SNDCON LXI B,CLREOL ; Clear the line CALL SNDCON LXI B,CRSRUP ; Move cursor up one line CALL SNDCON LXI B,CLREOL ; Clear the line CALL SNDCON ENDIF ; VIDEO ; SKPSIN: DCX B ; Back up the pointer to the DCX B ; Then to the at end of message STAX B ; And stop the crlf output there LXI H,ROWCNT ; Point to present row number count byte MVI M,1 ; Make this the first row ; HEADER: LDA NUMROW ; Number of rows per line LXI H,ROWCNT ; Row number count CMP M ; Carry set if NUMROW < current number JC A0827 ; LDA CFLAG ; Get compressed size flag CMA ; Invert it RAR ; Rotate through carry JNC ADD3SP ; Skip if flag was set YES to suppress ; ADD3SP: LXI H,NUMROW ; Number of rows per line LDA ROWCNT ; Row count totalizer byte CMP M ; Carry set if this is not the last row JNC BMPCNC ; Skip sending 3 spaces if last row LXI B,SPCS3M ; Send 3 spaces CALL SNDMSG ; This call does it ; BMPCNC: LDA ROWCNT ; Get current row number count INR A ; Bump it STA ROWCNT ; Store the incremented count JNZ HEADER ; Loop until done ; A0827: LHLD XTNL0E SHLD XTNL95 LXI H,1 SHLD XTNL91 ; A0833: XRA A ; Zap LXI H,XTNL95 CALL A0B2E RNC ; Done here if no carry LHLD XTNL95 XCHG LHLD NUMROW ; Number of rows per line MVI H,0 ; Make sure not more that 255 rows CALL A0AB5 XCHG SHLD LINECT ; Store the line count LHLD XTNL95 XCHG LHLD NUMROW ; Number of rows per line MVI H,0 ; Make sure not more than 255 CALL A0AB5 XRA A ; Zap CALL A0B02 ORA L ; Are we done? JZ A086A LHLD LINECT ; Get line count in INX H ; Bump the count SHLD LINECT ; And put it back ; A086A: LHLD HEIGHT ; Get number of lines per screen MOV B,H ; Put high order byte in MOV C,L ; Put low order byte in LHLD LINECT ; Get current line count in XCHG ; Then put line count in CALL A0256 SHLD LINECT ; Store the line count LXI H,0 SHLD XTNL8D ; Make zero for fresh start A087F: LXI B,LINECT ; Point to current screen line number LXI D,XTNL8D CALL CMP16B ; 16B compare returns carry if (BC)=(DE) JNC A08FA CALL CRLF ; Send CRLF at end of line LXI H,0 ; Zap SHLD XTNL8F MOV A,L STA ROWCNT ; Restore present row count to 0 ; A0898: LDA ROWCNT ; Get present row count in INR A ; Bump it up one STA ROWCNT ; Store the incremented number MOV C,A ; Now put it in for comparison LDA NUMROW ; Number of rows per line CMP C ; Compare, carry set if not done JC A08F0 ; Bump the pointers and loop until done LHLD XTNL8F XCHG LHLD XTNL8D DAD D PUSH H LHLD XTNL91 POP B DAD B SHLD XTNL93 LXI D,XTNL0E LXI B,XTNL93 CALL CMP16B ; 16B compare sets carry if (BC) < (DE) JC A08E2 MVI A,1 LXI H,ROWCNT ; Point to present row count CMP M ; Set carry if more rows to follow JNC A08D3 LXI B,CDELIM ; Row delimiter = ":" in CALL SNDMSG ; Show it to user on console ; A08D3: LHLD XTNL93 MOV B,H MOV C,L CALL A072A LHLD XTNL95 DCX H SHLD XTNL95 ; A08E2: LHLD LINECT ; Line count in XCHG ; Put it in LHLD XTNL8F DAD D SHLD XTNL8F JMP A0898 ; A08F0: LHLD XTNL8D INX H SHLD XTNL8D JMP A087F ; A08FA: LHLD NUMROW ; Number of rows per line into MVI H,0 ; Make sure not more that 255 XCHG ; Row count in LHLD LINECT ; Get line count in CALL A0AD4 XCHG LHLD XTNL91 DAD D SHLD XTNL91 CALL PAGECK ; Check for full screen or page JMP A0833 ; SUMMRY: LHLD DPBDSM ; Get maximum disk storage capacity in INX H ; Add one for the zero offset SHLD XTNL9E ; Save as maximum capacity SHLD XTNLA0 SHLD XTNLA2 LHLD DPBAL0 ; Get alloc vect 0 in alloc vector 1 in SHLD XTNL9C ; Store the space used data ; A0928: XRA A ; Zap LXI D,XTNL9C ; Point to the drive space used data CALL A0B23 ORA L JZ A0952 ; Calculate space remaining, display LDA XTNL9C RAR JNC A0942 LHLD XTNL9E DCX H SHLD XTNL9E ; A0942: MVI C,1 LXI H,XTNL9C CALL A0AF2 XCHG DCX H MOV M,E INX H MOV M,D JMP A0928 ;..... ; ; ; Calculates disk space remaining, check first if CP/M 3.0 ; A0952: MVI C,CPMVER ; Check version # CALL BDOS MOV A,L CPI 30H ; Version 3.0? JC A0955 ; Use normal method if not CP/M+ ; POP H ; Remove "call CKCPM3" from stack MVI C,CURDSK CALL BDOS MOV E,A MVI C,46 ; CP/M+ compute free space call CALL BDOS MVI C,3 ; Answer is 3 bytes long (24 bits) ; A0953: LXI H,TBUF+2 ; Answer is located here MVI B,3 ; Convert to 'k' length ORA A ; A0954: MOV A,M RAR MOV M,A DCX H DCR B JNZ A0954 ; Loop for 3 bytes DCR C JNZ A0953 ; Shift 3 times LHLD TBUF ; Get result in 'k' JMP A0961 ; Display result ;..... ; ; A0955: MVI C,PARMS ; Current disk parameter block CALL BDOS INX H INX H MOV A,M ; Get block shift factor STA A0964 INX H ; Bump to block mask MOV A,M ; Get it STA A0963 INX H INX H MOV E,M ; Get maximum block number INX H MOV D,M XCHG SHLD A0962 ; Put it away MVI C,GETADR ; Address of CP/M allocation vector CALL BDOS XCHG ; Get its length LHLD A0962 INX H LXI B,0 ; Initialize block count to zero ; A0956: PUSH D ; Save allocation address LDAX D MVI E,8 ; Set to process 8 blocks ; A0957: RAL ; Test bit JC A0958 INX B ; A0958: MOV D,A ; Save bits DCX H MOV A,L ORA H JZ A0959 ; Quit if out of blocks MOV A,D ; Restore bits DCR E ; Count down 8 bits JNZ A0957 ; Do another bit POP D ; Next count of allocation vector INX D JMP A0956 ; Process it ; A0959: POP D ; Clear alloc vector pointer from stack MOV L,C ; Copy block to HL MOV H,B LDA A0964 ; Get block shift factor SUI 3 ; Convert from records to thousands (k) JZ A0961 ; Skip shifts if 1k blocks ; A0960: DAD H ; Multiply blocks by 'k' per block DCR A JNZ A0960 ; A0961: SHLD XTNLA0 JMP A09B6 ;..... ; ; ; Uninitialized storage ; A0962: DB 0,0 ; Highest block number on drive A0963: DB 0 ; Rec/blk - 1 A0964: DB 0 ; # of shifts to multiply by rec/blk ;..... ; ; A09B6: CALL CRLF CALL CRLF LHLD LINECT ; Get the line count for the printer INX H SHLD LINECT ; Increment it for this new line CALL QUIT ; Want to quit now? LXI D,0 MVI C,CURDSK ; Get current disk function call CALL BDOS ; Get it with BDOS call ADI 'A' ; Make it ASCII MOV C,A ; F2OUT expects character in CALL F2OUT ; Send the drive code MVI C,':' ; ASCII colon in CALL F2OUT ; Send colon following drive code MVI C,' ' ; Space after the colon CALL F2OUT ; LHLD XTNL9E XCHG LHLD XTNL25 CALL A0AD4 ; Compute total capacity of drive MOV B,H MOV C,L MVI E,1 CALL A0B66 LXI B,TCAPM ; Total capacity in k CALL SNDMSG LXI B,USEDM CALL SNDMSG ; LHLD XTNL0E MOV B,H MOV C,L MVI E,1 CALL A0B66 ; Compute number of files on disk LXI B,FILESM ; Total files CALL SNDMSG ; LHLD XTNL0C XCHG LHLD XTNL25 CALL A0AD4 ; Compute amount of space used MOV B,H MOV C,L MVI E,001H CALL A0B66 LXI B,KOFMSG CALL SNDMSG ; LHLD XTNL23 ; Get number of entries remaining MOV B,H ; Move to MOV C,L ; Complete the above move MVI E,1 CALL A0B66 ; Send the number remaining MVI C,'/' CALL F2OUT ; LHLD XTNLA0 ; Get space remaining in HL MOV B,H ; Put into BC MOV C,L MVI E,001H ; Offset CALL A0B66 ; Send remaining space figures MVI C,'k' CALL F2OUT CALL CRLF ; CALL PAGECK ; Check for full screen (or page) ; IF VIDEO LXI B,TRMUNI ; Point to user terminal restoration string CALL SNDCON ; Send exit de-initialization if installed ENDIF ; VIDEO ; RET ;..... ; ; ; Compare 12 characters (user area, filename, ext.) ; CMPR12: MVI L,12 ; Load character count ; CMPRLP: LDAX D ; Get byte in ANI 07FH ; Strip the parity if set MOV H,A ; Save stripped byte in LDAX B ; Get a byte in ANI 07FH ; Strip this one too SUB H ; 0 if equal JNZ DIFF12 ; Jump if they are not equal INX D ; Equal, bump the pointers INX B ; Bump both pointers DCR L ; Reduce the count JNZ CMPRLP ; Loop until done RET ;... ; ; DIFF12: MVI A,0FFH ; Set flag for return if (DE) > (BC) RC ; is larger MVI A,1 ; Else flag shows is smaller than RET ; And done here ;..... ; ; ; Check for match in INTFCB parms with user number ; A0A59: LXI H,INTFCB ; Get address of first byte of search parms MVI E,12 ; 12 bytes to check ; A0A5E: MOV A,M ; Get drive/user code in CPI '?' ; Wildcard? JZ A0A6C ; Yes, search all user areas MOV D,A ; Get user area in LDAX B ; Get user area from immediate filename ANI 07FH ; Strip the high bit if set CMP D ; Are they equal? MVI A,0 ; Zap , cannot use XRA A here RNZ ; Not same, no match, check no further ; ; ; Arrive here if we have match or all user areas to be shown ; A0A6C: INX B ; Bump the filename pointer INX H ; Bump the memory pointer too DCR E ; One less byte to go JNZ A0A5E ; Loop until done LDA SFLAG ; Get system flag in ORA A ; Set the appropriate cpu flags RNZ ; Return if system flag is true DCX B ; Back up the pointer DCX B ; Pointer set to 2nd extent byte LDAX B ; Get it in the CMA ; Set carry if system file RLC ; Rotate carry into bit 0 position ANI 1 ; Isolate bit 0 RET ; Return 0 if dir file or 1 if system ;..... ; ; A0A7F: LXI H,0 ; Zap ; A0A8B: LDAX B ORA A JZ A0A91 INX H ; A0A91: INX B DCR E JNZ A0A8B RET ;..... ; ; A0A97: MVI E,008H ; A0A99: LDAX B MOV D,A INX B LDAX B ORA D JZ A0AA2 INX H ; A0AA2: INX B DCR E JNZ A0A99 RET ;..... ; ; A0AAA: MOV C,M INX H MOV B,M LDAX D ADD C MOV L,A INX D LDAX D ADC B MOV H,A RET ;..... ; ; A0AB5: MOV B,H MOV C,L LXI H,0 MVI A,16 ; A0ABC: PUSH PSW DAD H XCHG SUB A DAD H XCHG ADC L SUB C MOV L,A MOV A,H SBB B MOV H,A INX D JNC A0ACE DAD B DCX D ; A0ACE: POP PSW DCR A JNZ A0ABC RET ;..... ; ; A0AD4: MOV B,H MOV C,L LXI H,0 MVI A,16 ; A0ADB: DAD H XCHG DAD H XCHG JNC A0AE3 DAD B ; A0AE3: DCR A JNZ A0ADB RET ;..... ; ; ; Raise the count in to the power of number in ; H2CPWR: DAD H ; Double DCR C ; Reduce the count JNZ H2CPWR ; Loop until done RET ;..... ; ; A0AF2: MOV E,M INX H MOV D,M XCHG ; A0AF6: MOV A,H ORA A RAR MOV H,A MOV A,L RAR MOV L,A DCR C JNZ A0AF6 RET ;..... ; ; A0B02: MOV E,A MVI D,0 ; A0B05: MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A RET ;..... ; ; A0B0C: MOV C,A MVI B,0 MOV A,E SUB C MOV L,A MOV A,D SBB B MOV H,A RET ;..... ; ; ; 16 bit comparison routine. At entry points to memory address ; of the high limit and points to memory address of the present ; count to be checked. Returns with two's complement of the actual ; difference in , carry flag is set if memory at is greater ; than that at , zero flag if difference is zero, contains ; low order two's complement ( = . ; CMP16B: MOV L,C ; Move low order of count address to MOV H,B ; Move high order of count address to MOV C,M ; Move the low order count limit into INX H ; Point to high order of count limit MOV B,M ; contains 16 bit count limit LDAX D ; Get the low order present count in SUB C ; Subtract high limit from present count MOV L,A ; Move the remainder to INX D ; Point to high order of 16 bit present count LDAX D ; Move high order bits of present ct to SBB B ; Subtract high limit from present MOV H,A ; contains difference, = RET ;..... ; ; A0B23: MOV L,A MVI H,0 LDAX D ; Get ? from memory at SUB L MOV L,A INX D LDAX D ; Get next ? from memory SBB H MOV H,A RET ;..... ; ; A0B2E: MOV E,A MVI D,0 MOV A,E SUB M MOV E,A MOV A,D INX H SBB M MOV D,A XCHG RET ;..... ; ; HILITE: PUSH B ; Save pointer ; IF VIDEO LXI B,FGNDON ; Point to foreground on string CALL SNDCON ; Send the string ENDIF ; VIDEO ; POP B ; Recover pointer LDAX B ; Get the character INX B ; Bump the pointer PUSH B ; And save again ANI 07FH ; Clear the high bit MOV C,A ; In for output CALL F2OUT ; Send character ; IF VIDEO LXI B,FGNDOF ; Point to foreground off string CALL SNDCON ; Send the turn off code ENDIF ; VIDEO ; POP B ; Recover the pointer ; SNDMSG: LDAX B ; Get byte of message in CPI 80H ; High bit set? JNC HILITE ; Show it highlited if so ORA A ; Are we done yet? RZ ; Return if so ; PUSH B ; Else save MOV C,A ; Put the character in for F2OUT CALL F2OUT ; Send a character POP B ; Get address back INX B ; Bump the pointer JMP SNDMSG ; Loop until done ;..... ; ; ; Send "FGNDON" to console, send one character after stripping the ; high bit, then send "FGNDOF" to return to normal attributes ; CHROUT: MOV A,C ; Get character in for testing CPI 080H ; Is bit 7 high? JC F2OUT ; No, use F2OUT routine ANI 7FH ; Now strip the high bit MOV C,A ; And put in ; IF VIDEO PUSH B ; Alt. entry point for printer code output LXI B,FGNDON ; Point to foreground "ON" escape sequence CALL SNDCON ; Sent the escape sequence to the console POP B ; Recover character in ENDIF ; VIDEO ; CALL F2OUT ; Send the character ; IF VIDEO LXI B,FGNDOF CALL SNDCON ENDIF ; VIDEO ; RET ;..... ; ; ; Send a string to the console only. Does not go to disk file or list ; device (printer) ; SNDCON: LDAX B ; Get character in ORA A ; Are we done? RZ ; Return if done PUSH B ; Save pointer MOV E,A ; Character to for console output MVI C,2 ; Console output function ; SNDC1: CALL $-$ ; Address provided at initialization POP B ; Recover pointer INX B ; Increment to next character JMP SNDCON ; And loop until done ;..... ; ; ; CP/M function 2 (console output) ; F2OUT: MOV E,C ; Move character from to PUSH D ; Store the value MVI C,WRCON ; Console output function CALL BDOS POP D ; Get character in back again LDA PFLAG ; Printing also? ORA A JZ QUIT MVI C,5 ; If yes, send character to printer CALL BDOS JMP QUIT ; Want to quit now? ;..... ; ; ; See if operator has typed CTL-C to quit if yes, delete partial file ; QUIT: PUSH H PUSH D PUSH B MVI C,CONST ; Get keyboard status CALL BDOS RAR ; Anything typed? JNC QUIT2 ; If not, back to work MVI C,RDCON ; Otherwise get the character CALL BDOS CPI 'C'-40H ; "CTL-C" to quit JZ QUIT1 CPI 'X'-40H ; "CTL-X" to quit JZ QUIT1 ANI 5FH ; Change to upper-case if needed CPI 'K' JZ QUIT1 CPI 'X' JNZ QUIT2 ; If neither, back to work ; QUIT1: POP B ; Restore the stack POP D POP H POP H ; Remove 'call quit' from stack JMP EXIT ; QUIT2: POP B ; Restore the stack POP D POP H RET ;..... ; ; ; Arrive here with source location in , destination in , and ; byte count on the stack just above the return address ; MOVMEM: POP H ; Get the return address in XTHL ; Put it back on the stack ; MOVMOR: LDAX B ; Get byte here STAX D ; Put it there INX B ; Bump pointers INX D ; Both pointers DCR L ; Reduce the count remaining JNZ MOVMOR ; Loop until done RET ;..... ; ; ; Arrive here with fill byte in , count as low order byte on stack ; just above return address, and beginning address to fill in ; FILL: POP H ; Return address from last call in XTHL ; Put return address back on stack and ; get number of bytes to fill in MOV A,E ; Fill byte now in ; FLOOP: STAX B ; Store it at address indicated in INX B ; Bump memory pointer DCR L ; Reduce count remaining JNZ FLOOP ; Loop until done RET ;..... ; ; A0B66: LXI H,XTNLA8 MOV M,E DCX H MOV M,B DCX H MOV M,C LHLD XTNLA6 PUSH H MVI E,6 LXI B,XTNLAB CALL A0BBC STA XTNLAA INR A STA XTNLA9 ; A0B81: LDA XTNLA8 LXI H,XTNLA9 CMP M JC A0B97 MVI C,' ' ; ASCII space character CALL F2OUT ; Send the space to the console LXI H,XTNLA9 INR M JMP A0B81 ; A0B97: LXI H,XTNLA9 MVI M,0 ; A0B9C: LDA XTNLAA DCR A LXI H,XTNLA9 CMP M RC ; Done here if carry flag set LHLD XTNLA9 MVI H,0 LXI B,XTNLAB DAD B MOV C,M CALL CHROUT LXI H,XTNLA9 INR M JNZ A0B9C ; Loop until done RET ; Else done here ;..... ; ; A0BBC: POP H ; Get return address from the stack XTHL ; Restore return addr, get passed value in MVI D,1 XRA A PUSH PSW INX SP ; A0BC4: DCR E JZ A0BD5 INR D CALL A0BE1 ADI '0' PUSH PSW INX SP MOV A,L ORA H JNZ A0BC4 ; Loop until done ; A0BD5: MOV E,D DCR E ; A0BD7: DCX SP POP PSW STAX B INX B DCR D JNZ A0BD7 MOV A,E RET ; A0BE1: PUSH B LXI B,0100AH XRA A ; A0BE6: DAD H RAL CMP C JC A0BEE SUB C INX H ; A0BEE: DCR B JNZ A0BE6 POP B RET ;..... ; ; ; This module to "STEAL" the directory output from the BDOS by changing ; the BDOS jump address at 0006H to jump to this module, leave a byte ; intended for the console in memory, and then continue its journey with ; the console output byte unaltered. ; SNITCH: PUSH H ; Save the pointer LXI H,GETIT ; Point to beginning of getit routine SHLD BDOS+1 ; Set the BDOS pointer to "GETIT" module LXI H,SBUFFR ; Set pointer to save buffer MVI M,CR ; Insert a carriage return at beginning INX H ; Bump pointer MVI M,'Z'-40H ; End of file marker SHLD NXTLOC ; Store the updated pointer POP H ; Restore the pointer RET ;..... ; ; NXTLOC: DB 0,60H ; Page for buffer location HLSTG1: DB 0,0 ; Storage for when it arrives with BDOS call HLSTG2: DB 0,0 ; Stacktop stored here so we can push the psw to stack ; ; ; We arrive here with output character in . "GETIT" will get the ; character and store it for the save. We store in local memory, ; pop to get the top of the stack in , store that and then push ; the PSW in case the flags need to be saved. We reverse the procedure ; on the way out thus preserving things the way they were. This method ; takes time and space but leaves the stack undisturbed for the direct- ; ory program. ; GETIT: SHLD HLSTG1 ; Save register POP H ; Get stack top in SHLD HLSTG2 ; Save stack top here PUSH PSW ; Save accumulator and flags on stack MOV A,C ; Get the function call in ; CKFNC: CPI 2 ; Console output call? JNZ NOPE ; Not correct function so do not save LHLD NXTLOC ; Get next buffer location MOV M,E ; Save the byte INX H ; Bump pointer SHLD NXTLOC ; Save the incremented pointer for next pass NOPE: POP PSW ; Restore the accumulator LHLD HLSTG2 ; Get the old stack top in PUSH H ; And put it back on the stack LHLD HLSTG1 ; Restore ; HERE: JMP BDOS ; Now jump to the BDOS via the old vector ; This jump has the vector from 006H inserted ; Under program control ;..... ; ; ; Put things in order, then do the exit routine ; EXITJ: LHLD HERE+1 ; Get true BDOS vector back in SHLD BDOS+1 ; And make it like it was LHLD NXTLOC ; Get last written address in MVI M,01AH ; End of file indicator LDA FFLAG ; Saving to disk? ORA A JNZ SAVDIR ; If so, save the directory output ; EXITJ1: JMP BK2CCP ; This jump instruction gets changed by "PTRON" ; if printer is selected ;..... ; ; ; Insert printer restoration code in DUNMSG as needed ; BK2CCP: LHLD HERE+1 ; Get proper BDOS address in SHLD BDOS+1 ; Make it so LHLD STACK ; Get the original stack return again SPHL ; Set stack pointer to old stack RET ; And back to CCP without a warm reboot ;..... ; ; DONEPR: IF PNTRSP LXI B,PTROFM ; Point to end message CALL LSTOUT ; Send the message ENDIF ; PNTRSP ; JMP BK2CCP ; Return to CCP without a warm reboot ; LSTOUT: LDAX B ; Get character ORA A ; Test it RZ ; Done if zero PUSH B MOV E,A ; Character in for output MVI C,WRLST ; List device call ; LSTOT1: CALL BDOS ; Send the character to list device POP B ; Recover pointer INX B ; Point to next character JMP LSTOUT ; Loop until string sent ;..... ; ; ;======================================================================= ; ; Save routine used in new directory program to save the output to a ; a file called (name inserted at "NUNAME") when "F" is toggled. ; ; Fill the last record with ^Z (1AH), and send all the data to a disk ; file named in the file control block ; SAVDIR: LHLD NXTLOC ; Get last storage address in ; NOTYET: MVI M,'Z'-40H ; Fill with CTL-Z EOF markers INX H ; Bump memory pointer MOV A,L ; Get low order byte in ORA A ; Are we done yet? JNZ NOTYET ; No, do it again ; INX H ; H = # of 256 byte blocks (including offset) LXI D,SBUFFR ; Get buffer address (MSB) in MOV A,H ; Get last block (MSB) address in SUB D ; = # of 256 byte blocks ADD A ; = # of 128 byte blocks STA SAVENN ; # of 128 byte blocks to save to disk file LXI H,NUNAME ; Point to our internal file control block LXI D,DFCB ; The CP/M default file control block MVI B,32 ; Thirty-two bytes to move ; SETNOT: MOV A,M STAX D INX H INX D DCR B JNZ SETNOT ; MVI C,CURDSK ; Get current disk number CALL BDOS ; Number returns in 'A' PUSH PSW ; Save for set drive function ; ; ; Note =====>>> If save on current drive is desired, change the next ; byte to 0AFH, exclusive OR with . ; CURRENT:NOP ;*This is the one to change, saves disk ; file to drive directory is from INR A ; Bump it up one for fcb to select drive ; Since FCB wants 1=A, 2=B, etc. STA DFCB ; Store it there for later STA NUNAME ; Store it there too POP PSW ; Get current disk number back MOV E,A ; Put current disk in e for disk select MVI C,SELDSK ; Disk selection code CALL BDOS ; Select current disk as active disk MVI C,DELETE ; Delete file function call LXI D,DFCB ; We will erase NUNAME.EXT if present now CALL BDOS ; Erase old file if present in directory MVI C,MAKEF ; Make file function LXI D,DFCB ; Point to the name again CALL BDOS ; Return with error code in CPI 0FFH ; Error? JZ ERROR ; Send error message LXI D,SBUFFR ; Beginning of data left by directory program ; SETDMA: PUSH D ; Save the pointer MVI C,STDMA ; Set DMA address function CALL BDOS ; Set DMA MVI C,WRSEQ ; Write sequential function LXI D,NUNAME ; Point to filename in FCB CALL BDOS ; Write a 128 byte block ORA A ; Check for successful write JNZ ERROR ; Zero returned if all ok LDA SAVENN ; Get number of remaining blocks DCR A ; Reduce it and check for zero remaining JZ CLOSE ; Close the file if zero STA SAVENN ; Save it for the next pass POP H ; Get old DMA pointer back, this time in LXI D,080H ; Raise it 128 bytes here.... DAD D ; By adding to old value now in XCHG ; And exchanging to get new DMA address in JMP SETDMA ; Loop until done ;..... ; ; ERROR: LXI B,ERRMSG ; Point to error message CALL SNDMSG ; Send the bad news JMP EXIT ; Quit here ;..... ; ; CLOSE: LXI D,NUNAME ; Point to name of file again MVI C,CLOSEF ; Close file function CALL BDOS ; Returns 0FFH on error CPI 0FFH ; Check for proper close JZ ERROR ; Send error message and quit EXIT: JMP EXITJ1 ; Return to calling module ;..... ; ; SAVENN: DB 0 ; This number will be changed during ; Execution to save the correct file size. ;..... ; ; NOSTOP: LDA NOSTPF ; Printer flag set? ORA A RNZ ; If yes, disregard this request LHLD 0FFFFH ; Maximum number of lines SHLD HEIGHT ; Will not stop each screenful RET ;..... ; ; SPFLAG: LDA PFLAG ; Get the printer request flag CMA ; Reverse its sense STA PFLAG ; And leave it there for later use STA NOSTPF RET ; NOSTPF: DB 0 ;..... ; ; STSAVF: MVI A,0FFH ; Set the 'disk save' flag STA FFLAG ; Store it for later reference MVI A,PLINES ; Store for possible printing later STA HEIGHT RET ;..... ; ; PTRON: MVI A,5 STA CKFNC+1 ; Checks for printer ready MVI A,PLINES ; Put this number of lines on printer STA HEIGHT ; Also change display height to agree ; IF PNTRSP LXI B,PTRONM ; Printer setup codes CALL LSTOUT ; Send the message ENDIF ; PNTRSP ; LXI H,DONEPR ; Get address of DONEPR in SHLD EXITJ1+1 ; Hot patch the exit jump address RET ;..... ; ; FORMFD: LXI B,FORMFEED ; Point to formfeed string JMP LSTOUT ; Send formfeed, auto return ; FORMFEED: DB CR,FF,CR,0 ;..... ; ; ;----------------------------------------------------------------------- ; help message ; HELP: LXI B,HLPMSG CALL SNDMSG JMP BK2CCP ; HLPMSG: DB 'DIRR extended directory program v5, 01/07/86',CR,LF DB CR,LF,' Directory program, accepts ' DB 'wildcards, extra commands via $ char:',CR,LF,CR,LF DB ' B>DIRR ? help guide',CR,LF DB ' B>DIRR all normal files ' DB 'in current user area',CR,LF DB ' B>DIRR $ANV all on this user ' DB 'area plus options A,N,V',CR,LF DB ' B>DIRR *.ASM $A all .ASM files plus ' DB 'option A',CR,LF,CR,LF,' Options:',CR,LF,CR,LF DB '103H A - files from all user areas, this ' DB 'drive (nice with ''E'' below)',CR,LF DB '104H C - compressed display, extra ' DB 'row, no filesize, aborts extended',CR,LF DB '105H E - extended display, includes ' DB 'user area and any attributes',CR,LF DB '106H F - makes a disk file named ~DIR ' DB 'after displaying the request',CR,LF DB '107H N - do not stop each screenful, ' DB 'else say [more] when full',CR,LF DB '108H P - send output to the printer ' DB '(paginates if more than one page)',CR,LF DB '109H S - include any system files that ' DB 'meet the request',CR,LF DB '10AH V - version number and date',CR,LF,CR,LF DB ' CTL-X, CTL-C, X or K to abort at any time.' DB CR,LF,CR,LF,0 ;...... ; ; ;----------------------------------------------------------------------- ; message area ; VERMSG: DB 'DIRR extended directory program v5, 01/07/86',CR,LF,0 ERRMSG: DB 'DISK FULL',0 HTSPCM: DB CR,LF,'[more]',0 SPCS3M: DB ' ',0 ; 3 spaces used in output formatting CDELIM: DB ' : ',0 ; Row delimiter USEDM: DB 'Used: ',0 FILESM: DB '/',0 ; Follows number of files computation KOFMSG: DB 'k Free: ',0 ; Displays total space used TCAPM: DB 'k ',0 ; Follows total space avail. on disk ;..... ; ; ;----------------------------------------------------------------------- ; ; ; The following 12 bytes are not directly addressed in the program ; DW 0,0,0,0,0,0 ; Do not remove these. ; XTNL0C: DW 0 XTNL0E: DW 0 XTNL10: DW 0 NDSRCH: DB 0 ; Contains offset from 080H or 0FFH... ; At end of search INTFCB: DB 0 ; Contains current drive or "?" for.... ; Wildcard search if "U" flag set true DB 0,0,0,0 ; Internal file control block bytes 2 DB 0,0,0,0 ; thru 12. Filled with search parms DB 0,0,0 ; to be loaded into DFCB for lookup XTNL21: DW 0 XTNL23: DW 0 XTNL25: DW 0 XTNL27: DB 0 LINECT: DW 0 ; Current screen line number BUFLOC: DW 0 ; Location of filename in buffer beginning at 080H ; ; ;----------------------------------------------------------------------- ; disk parameters ; INTDPB: ; Copy of the search disk parameter block ; DPBSPT: DW 0 ; Sectors per track DPBBSH: DB 0 ; Block shift factor DPBBLM: DB 0 ; Block mask (2[bsh-1]) DPBEXM: DB 0 ; Extent mask ; DPBDSM: DW 0 ; Disk storage maximum DPBDRM: DW 0 ; Directory maximum entries DPBAL0: DB 0 ; Alloc vector 0 DPBAL1: DB 0 ; Alloc vector 1 ; DPBCKS: DW 0 ; Directory check vector DPBOFF: DW 0 ; Number of reserved tracks ; ;----------------------------------------------------------------------- ; LSTLOC: DB 0,0 STAKAD: DB 0,0 ; XTNL3F: DB 0,0 XTNL41: DB 0 XTNL42: DB 0 XTNL43: DB 0 ; XTNL44: DB 0 FLGIND: DB 0,0 XTNL47: DB 0,0 XTNL49: DB 0,0 ; XTNL4B: DB 0,0 XTNL4D: DB 0,0 XTNL4F: DB 0,0 XTNL51: DB 0,0 ; XTNL53: DB 0 XTNL54: DB 0,0 XTNL56: DW 0,0,0,0,0,0,0,0,0,0,0 XTNL6C: DB 0,0 ; XTNL6E: DW 0,0,0,0,0,0,0,0,0,0,0 XTNL84: DB 0,0 XTNL86: DB 0,0 XTNL88: DB 0,0 ; XTNL8A: DB 0 XTNL8B: DB 0 XTNL8C: DB 0 XTNL8D: DB 0,0 ; XTNL8F: DB 0,0 XTNL91: DB 0,0 XTNL93: DB 0,0 XTNL95: DB 0,0 ; ROWCNT: DB 0 ; Row number counter XTNL98: DB 0,0 ALLOCV: DB 0,0 XTNL9C: DB 0,0 XTNL9E: DB 0,0 ; XTNLA0: DB 0,0 XTNLA2: DB 0,0 XTNLA4: DB 0 XTNLA5: DB 0 ; XTNLA6: DB 0,0 XTNLA8: DB 0 XTNLA9: DB 0 XTNLAA: DB 0 ; XTNLAB: DW 0,0,0,0,0,0,0 ; 21 bytes total DB 0,0,0,0,0,0,0 ;..... ; ; ; The file control block must be filled with the information shown at ; "NUNAME". Thirty-two (32) bytes are required, the first byte is the ; drive specification and the next eleven (11) are the filename and ex- ; tention. Do not use the '.' between filename and extent. The rest of ; the bytes are set to '0' and MUST be in place. ; NUNAME: DB 0 ; Drive number (0 = default drive) DB '~DIR ' ; ***** name of new file ***** DB 0,0,0,0,0,0 ; ***** leave space in FCB ***** DB 0,0,0,0,0,0 ; ***** do not alter this ***** DB 0,0,0,0,0,0 DB 0,0 DB 0,0,0,0 ; Four byte buffer zone for good measure DS 40 ; Reserved for the stack area ; STACK: DS 2 ; END