; ; D.ASM ver 2.9 ; RESTRICTED DIRECTORY LIST PROGRAM ; (revised 08/12/82) ; ;D.COM is a directory list program, which writes ;4 or 5 entries on a line, separated by colons. ; (THIS IS THE 'WHATSNEW' PROGRAM SEEN ON MANY RCPM SYSTEMS) ; ;The command contains an internal table of file names, ;which are not to be shown when just "D" is typed. ;(NOTE typing "D *.*" always shows all files) ; ;Why is this useful: A typical CP/M disk contains many ;utility files: ed.com, asm.com, submit.com, etc. When ;you do a directory listing, you typically aren't interested ;in seeing all those files, but rather just the "current" ;or "active" files. This is what "D.COM" can do. ; ;NOTE: Direct CBIOS calls are used for input and output ; in order to avoid echoing of inputted characters. ; This keeps a noisy phone line from causing garbage ; characters in the display. ; ;Revisions/updates: (in reverse order to minimize reading time) ; ;08/12/82 Added SUB file option to allow writing each new filename ; that appears in the "New Files" display to a .SUB file ; of the form: ; XSUB ; PIP ; $1=$2 Fn.Ft$3 ; $1=$2 Fn.Ft$3 ; etc. ; to allow a simple archive of new files to be performed ; by: SUBMIT D A:=B: [G1] ; Also repaired bug in EXIT routine and removed character ; 'gobbler' routine so that program will work better with ; 'type-ahead' BIOSes by Dave Hardy ; ;07/01/82 Modified TITLE feature to allow TITLE command to be ; easily changed. Previous version had hard-coded TITLE ; command length and TITLE start. Also removed TITSTART ; symbol (no longer needed) and cleaned up some of the ; comments (Dave Hardy) ; ;06/23/82 Added Title feature for disk.. allows you to set ; the title for the disk.(See Below) ; Bob Bowerman. ; ;06/19/81 Added BIAS for modified or standard CP/M. Ted Shapin. ; ;06/13/81 Fixed names counter in files not found routine. ; (KBP). ; ;06/12/81 Changed routines for printing so that CTL-C abort ; will work properly. Added ILPRT and TYPMEM routines ; to reduce program size. (KBP) ; ;05/20/81 Increased system file security by increasing pasword ; option to 3 characters. (By Howard Booker, W8IU) ; ;03/01/81 Added reset of DMA to 80H default on exit so D will ; work properly with submit. Deleted CEXIT routine, ; which was no longer used. Expanded documentation. ; (KBP) ; ;02/28/81 Mod. of 2/21 changed by popular demand to use of direct ; BIOS calls for freezing and aborting output. (CS) ; ;02/21/81 Abort on receipt of control-C character only (to prevent ; premature exit on remote systems with noisy telephone ; connections). Charlie Strom ; ;12/23/80 Changed sign-on message, revised documentation. (KBP) ; ;12/22/80 Fixed stack and file extent problems. Fully expanded ; macros so ASM may be used. Fixed problem in LOK routine ; By Keith Petersen, W8SDZ. ; ;12/07/80 Added drive select byte and expanded move macro in WRBACK ; routine. Also added "LOK" command. By Ron Fowler. ; ;12/02/80 Added "NOSYS" equate to ignore system files, code to strip ; attributes from files for CP/M 2.x, added date display and ; print options. Fixed up display format. By Ron Fowler ; ;12/01/80 Added "FILES NOT FOUND" feature of updated ; D.ASM of Ward Christensen. By Ron Fowler. ; ;11/23/78 Originally written by Ward Christensen. ; ;=================================================== ; ;Use: D *.* prints all names, 5 across. ; ; D *.ASM prints selected files just like DIR. ; ; D SET builds a table (in D.COM) of all ; names currently on the disk. (see *NOTE). ; ; D SET <DATE> adds the date for printing whenever ; D is called by 'A>D<CR>' with no options. ; If the date field is left blank, it will ; be ignored. Note that the date must be 8 ; characters or less (see *NOTE). ; ; D TIT <TITLE FOR DISK> sets an internal disk title ; which prints out each time the program is ; run (if a title has been set).(maximum of ; circa 70 chars please although it will ; handle a full CP/M input line. ; ; NOTE: To get rid of title (and accompanying ; print put type 'D TIT' and the title is ; set to null. ; ; D ADD FN.FT adds a name to the table in ; D.COM, so FN.FT won't be listed ; by the 'D' command (see *NOTE). ; ; D DEL FN.FT deletes a name from the table ; in D.COM, so if FN.FT is in the ; directory, it will be listed by 'D' ; (see *NOTE). ; ; D SUB causes a file named 'D.SUB' to be generated on ; the currently logged-in drive. The file contains ; all of the 'New Files' names, and is of the form: ; ; XSUB ; PIP ; $1<fn1.ft>$2 ; $1<fn2.ft>$2 ; $1<fn3.ft>$2 ; etc. ; ; D.SUB can be used to archive 'New Files' with a ; simple command line like: ; SUBMIT D B:=A: [G5] ; which would PIP all of the new files from B5: to A: ; ; D lists the directory, showing ; only those files NOT in D.COM, as ; put there by 'D SET' or 'D ADD FN.FT' ; ;*NOTE: the program must write itself back to disk, ;modified, so your disk must not be write protected. ; ;------------------------------------------------ ; ;Examples: Suppose your disk has: ; D.COM ; ASM.COM ; ED.COM on it initially. ; LOAD.COM ; DDT.COM ; ;You would type: D SET ;to set these names into the D.COM program. ; ;Typing "D" would then list: ; ; -->New files ; A: ++NONE++ ; ; -->Deleted files ; A: ++NONE++ ; ;Suppose you ED TEST.ASM, ASM it, and LOAD it. ;Typing D would then list: ; ; -->New files ; A: TEST ASM : TEST BAK : TEST HEX : TEST COM ; ; -->Deleted files ; A: ++NONE++ ; ;i.e. it tells you of the "current" files on the disk. ; ;Now, supposing you wanted to add TEST.COM as a "regular" ;file on your disk. Type: ; ; D ADD TEST.COM ; ;Now, typing D will show: ; ; -->New files ; A: TEST ASM : TEST BAK : TEST HEX ; ; -->Deleted files ; A: ++NONE++ ; ;i.e. TEST.COM is now considered a "permanent" file. ; ;----- ; ;Now, suppose you accidentally erased ASM.COM from your ;disk. Typing D gives: ; ; -->New files ; A: TEST ASM : TEST BAK : TEST HEX ; ; -->Deleted files ; A: ASM COM ; ;showing you are missing one of the "regular" files. ; ;If, in fact, you didn't want ASM.COM to be on the disk, ;type: ; ; D DEL ASM.COM ; ;which will delete the name from the D.COM table, so ASM.COM ;won't show up as "deleted". ; ;=================================================== ; ; SPECIAL NOTES FOR REMOTE SYSTEM USE: ; ;If you keep a dedicated copy of this program on each drive of ;your remote system, you can 'dedicate' each copy of this program ;to a drive by filling in the byte at 103H with the drive number. ;This prevents such things as: ; ; A>D B: ; or ; B>A:D ; ;Do this by using the command: ; ; A>D LOK A: to lock to a drive ; or ; A>D LOK to unlock ; ;If the conditional 'NOSYS' is set TRUE, $SYS files in CP/M 2.x ;will be ignored in both directory listings and when the "ADD" ;option is invoked, unless the override char is specified. This ;allows D.COM to be used as a "WHAT'S NEW" program for remote CP/M ;systems, where the $SYS files must not be listed. ; ;Examples: ; A>D *.* S displays everything ; A>D SET S puts ALL files in table ; A>D SET 12/23/80 sets date for reference ; (if you use 'D SET S', you lose the date option.. ; ..sorry about that). ; ;If you use this program on a remote system, you will likely ;want to change the commands (ADD, DEL, and SET) for security. ;You will also want to change the $SYS suppress override character. ;You may also want to change the name of the program to make the ;name itself more informative, e.g. "D.COM". ; ;-->IMPORTANT: If you want the program to be 'TAG'ed after every ;D SET (so it cannot be taken by XMODEM), see the note at label ;"WRBACK" for setting the F1 bit in the filename itself. ; ;Note that this program defines its own name for write-back ;purposes under the label "WRBACK". ; ;=================================================== ; ;NOTE: If you add improvements or otherwise update ;this program, please modem a copy of the new file ;to "TECHNICAL CBBS" in Dearborn, Michigan - phone ;313-846-6127 (110, 300, 450 or 600 baud). Use the ;filename D-XX.NEW. (KBP) ; ;=================================================== ; ; Define some stuff FALSE EQU 0 TRUE EQU NOT FALSE BIAS EQU 0 ;For STD CP/M or 4200H for ALTCPM BDOS EQU 5 + BIAS ;CP/M's BDOS access jump FCB EQU 5CH + BIAS ;CP/M's file control block FCBRNO EQU FCB + 32 ;Rec # in FCB CPMBUFF EQU 80H + BIAS ;CP/M command line buffer CR EQU 13 ;Carriage Return LF EQU 10 ;Line Feed ; ; Set the following for your system: NOSYS EQU TRUE ;TRUE means ignore $SYS files FENCE EQU ':' ;Character printed between filenames in display NPL EQU 4 ;Number of names to be displayed on each line ; ; The leader string for the SUB file (XSUB, PIP) is located at label SUBF4 ; ORG 100H+BIAS ; DENTRY: JMP AROUND ; DRIVE: DB 0 ;<---DRV # IS PUT HERE IF DEDICATED ; (this can be done with the LOK command) ;Init local stack AROUND: LXI H,0 ;HL=0 DAD SP ;HL=STACK SHLD STACK ;SAVE STACK POINTER LXI SP,STACK ;INIT LOCAL STACK ; ;Initialize direct CBIOS calls LHLD 1+BIAS LXI D,3 DAD D ;HL=CONSTAT SHLD TYPES+1 DAD D ;HL=CONIN SHLD CIC+1 DAD D ;HL=CONOUT SHLD TYPEC+1 ; ;Print ID message CALL ILPRT ;PRINT: DB 'D ver 2.9',CR,LF DB 'CTL-S pauses, CTL-C aborts',CR,LF,0 ; ;Print Disk Title ; PTITL LXI H,DTITLE ;get title address MOV A,M ;load it CPI 0 ;end of string JZ CONT ;don't print title CALL ILPRT ;print heading DB 'Title: ',0 LXI H,DTITLE ;load it again LOOP1: MOV A,M ;... CPI 0 ;zero? JZ ENDPRT ;all done CALL TYPE ;type this char INX H ;next char JMP LOOP1 ;repeat ... DTITLE: DB 0 ;storage for DS 7FH ;title ENDPRT: CALL CRLF ; ;Set file control block CONT: LDA DRIVE ORA A ;Non-dedicated? JZ NOND ;Jump if so STA FCB ; NOND: LHLD FCB+17 ;Get $SYS override characters SHLD SYSTOO ;and save for later LDA FCB+19 STA SYSTOO+2 ; ;See if request to add name to list LXI H,FCB+1 CALL ADDCM2 ADDCM: DB 'ADD ' ;11 characters (padded with spaces) ; ADDCM2: POP D ;Make DE point to ADD command LXI B,ADDCM2-ADDCM ;BC gets length of string CALL COMPR JNZ NOADD ; ;Got request to add name to table CALL DELNAM ;FIRST, DELETE THE NAME CALL FINDFF ;FIND END OF TABLE XCHG ;ADDR TO DE ; ;Move name to table LXI H,FCB+17 LXI B,11 CALL MOVER MVI A,0FFH STAX D ;SET NEW END JMP WRBACK ;WRITE PROGRAM BACK ; ;See if request to add title to disk ; NOADD: LXI H,FCB+1 CALL NOADD1A NOADD1B: DB 'TIT' ;MUST be your command to set title TITLEN DB ' ' ;# spaces here + length of your command = 11 NOADD1A: POP D ;GET TO LXI B,NOADD1A-NOADD1B CALL COMPR JNZ NOADD2A ; ;Process the title or erase it, if none given ; LXI H,CPMBUFF ;get length MOV A,M ;move it to A SUI TITLEN-NOADD1B+1 ;but don't include the title command JZ TITNO ;no title? LXI H,CPMBUFF+TITLEN-NOADD1B+2 ;Get START OF DTITLE LXI B,0000 MOV C,A ;Put length in BC LXI D,DTITLE ;Place to store CALL MOVER ;Move title in storage MVI A,00 ;And Mark End STAX D ;Of string JMP WRBACK ;And write back to disk ; ;No title - Clear title ; TITNO: LXI H,DTITLE ;load in space MVI M,00 ;store end of string JMP WRBACK ;and write back to disk ; ;See if request to lock D.COM to a drive ; NOADD2A: LXI H,FCB+1 CALL NOADD3 NOADD2: DB 'LOK ' ; NOADD3: POP D ;GET TO LXI B,NOADD3-NOADD2 CALL COMPR JNZ NOLOK ; ;Got request to lock LDA FCB+16 STA DRIVE STA FCB JMP WRBACK ; ;See if request to DEL name from list ; NOLOK: LXI H,FCB+1 CALL NOLOK3 NOLOK2: DB 'DEL ' ; NOLOK3: POP D ;GET TO LXI B,NOLOK3-NOLOK2 CALL COMPR JNZ NODEL ; ;Got request to delete a name from the file CALL DELNAM ;DELETE THE NAME JNC WRBACK ;WRITE BACK IF OK CALL MSGXIT DB '++NAME NOT IN TABLE++$' ; ;See if request is to make SUB file ; NODEL: LXI H,FCB+1 CALL SUBF3 SUBF2: DB 'SUB ' SUBF3: POP D LXI B,SUBF3-SUBF2 CALL COMPR JNZ NOSUB ; ;Got request to make SUB file, so say so, and set flag to force it CALL SAYSUB ;Notify console that SUB file will be made DB 'Writing SUBMIT file...',CR,LF,'$' SAYSUB: POP D MVI C,9 CALL BDOS MVI A,0FFH ;Set SUBFLG to tell program to make SUB file STA SUBFLG LXI H,SUBBUF ;Write SUB file start into file buffer CALL SUBF5 ;(XSUB, PIP, etc.) SUBF4: DB 'XSUB',CR,LF,'PIP',CR,LF SUBF5: POP D ;Use MOVER routine to copy it into SUB buffer XCHG LXI B,SUBF5-SUBF4 CALL MOVER XCHG SHLD SUBPTR ;Save SUB file buffer pointer LXI H,FCB+1 ;Then fill tail in with spaces to make MVI C,11 ; program think that no options chosen NXSPC: MVI M,' ' DCR C INX H JNZ NXSPC MVI C,36H ;Initialize local FCB LXI H,LFCB ;(Can't use default, because commands there) NXFCB: MVI M,0 DCR C INX H JNZ NXFCB LXI D,LFCB+1 ;Set up local FCB to write D.SUB file CALL UWR2 UWR1: DB 'D SUB',0 UWR2: POP H LXI B,UWR2-UWR1 CALL MOVER MVI C,ERASE ;Erase old file, if it exists LXI D,LFCB CALL BDOS XRA A STA LFCB ;Set up to write to DEFAULT drive STA FCBRNO ;Initialize record number MVI C,MAKE ;Create the file LXI D,LFCB CALL BDOS JMP NOSET ;Then jump off to display names as usual ; ;See if request to set up table from directory ; NOSUB: LXI H,FCB+1 CALL NODEL3 NODEL2: DB 'SET ' ; NODEL3: POP D ;GET TO LXI B,NODEL3-NODEL2 CALL COMPR JNZ NOSET ; ;Got request to setup table. ;Move the date (may be blank). LXI H,FCB+17 LXI D,DATE LXI B,8 CALL MOVER MVI A,1 ;TURN ON.. STA SETFLG ;..SET FLAG MVI A,0FFH ;CLEAR.. STA NAMES ;..NAMES TABLE CALL FILLQ ;MAKE FCB '????????.???' ; ; NOSET: LDA FCB+1 ;Get PRTFLG SUI ' ' STA PRTFLG PUSH PSW CZ HEAD1 POP PSW JNZ GOTNAM CALL FILLQ ;MAKE NAME ????????.??? ; GOTNAM: LDA FCB ORA A JZ NODISK DCR A MOV E,A MVI C,SELDSK CALL BDOS ; NODISK: MVI B,NPL ;NAMES PER LINE CALL LINMRK MVI C,SRCHF JMP CALLIT ; LINE: MVI B,NPL ;NAMES PER LINE CALL LINMRK ; NEXT: MVI C,SRCHN ; CALLIT: PUSH B LXI D,FCB CALL BDOS INR A JZ CKNONE DCR A ANI 3 MOV L,A MVI H,0 DAD H DAD H DAD H DAD H DAD H LXI D,81H+BIAS DAD D ; ;Check for $SYS attribute, then clear all attributes PUSH H LXI D,9 ;SYS ATT OFFSET DAD D MOV A,M ANI 80H STA SYSFLG POP H ;RETRIEVE FILENAME PTR PUSH H MVI E,11 ;11 CHARS IN FILENAME ; ATTLP: MOV A,M ;PICK UP CHAR ANI 7FH ;KILL ATTRIBUTE MOV M,A ;PUT BACK DOWN INX H DCR E JNZ ATTLP POP H ; ;See if name is to be printed XCHG ;NAME POINTER TO DE LDA SETFLG ;REQUEST TO SETUP TABLE? ORA A JNZ SETUP ;GO SET ENTRY INTO TABLE LDA PRTFLG ORA A JNZ GOPRNT ;EXPLICIT REQUEST FOR ALL PUSH D LXI H,NAMES ; CKNEXT: POP D ;GET NAME POINTER POP B PUSH B MOV A,M ;END OF TABLE? INR A ;WAS IT 0FFH? JZ GOPRNT MVI B,0 MVI C,11 ;NAME LENGTH PUSH D ; CKLP: LDAX D CMP M JNZ NOMACH INX D INX H DCR C JNZ CKLP ;LOOP FOR 11 CHARS ; ;Got match, mark it found and don't print it LXI D,-11 ;POINT BACK TO NAME DAD D MVI M,0 ;MARK IT FOUND POP D ;POP POINTER POP B JMP NEXT ;SKIP THE NAME ; ;Name didn't match, try next ; NOMACH: DAD B ;POINT TO NEXT NAME JMP CKNEXT ; ;Print the name ; GOPRNT: IF NOSYS CALL SYSCK JZ DONAME LDA SYSFLG RAL POP B JC NEXT PUSH B ENDIF ;NOSYS ; ; DONAME: LDA SUBFLG ;See if SUB file is to be made ORA A CNZ NAMSUB ;If so, then write the name into the SUB buffer MVI A,1 ;SAY WE GOT ONE STA GOTFLG MVI C,8 XCHG ;NAME BACK TO HL CALL TYPMEM MVI A,'.' CALL TYPE MVI C,3 CALL TYPMEM POP B CALL SPACE MVI A,FENCE DCR B PUSH PSW CNZ TYPE CALL SPACE POP PSW JNZ NEXT CALL CRLF JMP LINE ; ;Write the filename pointed to by DE into the SUB file buffer ; in the format: $1<fn.ft>$2<cr><lf> NAMSUB: PUSH H ;Save HL (whatever's in it) PUSH D ;Save filename pointer PUSH B ;Save BC (whatever's in it) LHLD SUBPTR ;Point HL to SUB buffer (DE points to filename) MVI C,8 ;Load counter for 8 characters of filename MVI M,'$' ;First write '$1' CALL INCPTR ;Increment file buffer pointer and write if full MVI M,'1' CALL INCPTR SNAM: LDAX D ;Get a character of the name CPI ' ' ;Don't transfer spaces to SUB buffer JZ SNAM2 ANI 7FH ;Trim off any nasty attributes MOV M,A ;Put the character into the SUB buffer CALL INCPTR ;Point to next SUB location SNAM2: INX D ;Point to next character of filename DCR C ;Decrement filename counter JNZ SNAM ;Continue until all 8 characters read MVI M,'.' ;Put a '.' into the SUB buffer to separate fn & ft CALL INCPTR ;Point to next location in SUB buffer MVI C,3 ;Now do the 3 character long filetype SNAM3: LDAX D CPI ' ' JZ SNAM4 ANI 7FH MOV M,A CALL INCPTR SNAM4: INX D DCR C JNZ SNAM3 MVI M,'$' ;Then write '$2<cr><lf>' on the end of the name CALL INCPTR MVI M,'2' CALL INCPTR MVI M,CR CALL INCPTR MVI M,LF CALL INCPTR SHLD SUBPTR ;Save the new SUB buffer pointer POP B ;Restore all the registers POP D POP H RET ;Then return back to DONAME ; ;Increment the HL file buffer pointer, and write the buffer if full ; INCPTR: INX H ;See if buffer is full MVI A,(SUBBUF+80H) AND 0FFH CMP L ;(See if LSH of HL = LSH of SUBBUF+80H) RNZ ;Return if buffer not full, else flush to disk WRTSBF: LXI H,SUBBUF ;Reset pointer to start of buffer WRTSB2: PUSH H PUSH D PUSH B LXI D,SUBBUF ;Set DMA address to SUB buffer MVI C,SETDMA CALL BDOS LXI D,LFCB ;Write the buffer to disk MVI C,WRITE CALL BDOS LXI D,CPMBUFF ;Now set DMA address back to default MVI C,SETDMA ; so that other routines can read directory CALL BDOS POP B POP D POP H ORA A ;Notify console and abort if write error JNZ WRERR RET ; CKNONE: LDA GOTFLG ;Some new files found? ORA A JNZ NOTFND ;Jump if yes LDA PRTFLG ;Print names? ORA A JNZ NOTFND ;Jump if yes CALL ILPRT ;Else say no new files found and fall through DB '++NONE++',CR,LF,0 ; ;Print the files not found ; NOTFND: LDA SETFLG ;IS THIS 'D SET'? ORA A JNZ FINI ;DONE IF SO LDA PRTFLG ;ARE WE PRINTING? ORA A JNZ CKNON2 ;DONE IF NOT ; ;If this D.COM is dedicated ("DRIVE" is non-zero), ;then be sure to print the "FILES NOT FOUND" LDA DRIVE ORA A JNZ NOCHK LDA FCB ;DRIVE SPECIFIED? ORA A JNZ FINI ;SKIP NOT FOUND IF SO ; NOCHK: CALL HEAD2 ;PRINT NOT FND HEADER LXI H,NAMES ;START OF TABLE LXI D,11 ; LINE2: MVI B,NPL CALL LINMRK ; NEXT2: MOV A,M ;FIRST CHAR OF NAME ORA A ;MARKED FOUND? JZ NOPRNT ;JUMP IF SO INR A ;CHECK FOR TABLE END JZ CKNON2 ;JUMP IF END MVI A,1 STA GOTNF MVI C,8 CALL TYPMEM MVI A,'.' CALL TYPE MVI C,3 CALL TYPMEM CALL SPACE MVI A,FENCE DCR B PUSH PSW CNZ TYPE CALL SPACE POP PSW JNZ NEXT2 CALL CRLF JMP LINE2 ; NOPRNT: DAD D JMP NEXT2 ; ;Print header ; HEAD1: CALL ILPRT ;PRINT: DB CR,LF,'-->New files',0 JMP HEAD3 ; HEAD2: CALL ILPRT ;PRINT: DB CR,LF,CR,LF,'-->Deleted files',0 ; HEAD3: LDA DATE CPI ' ' JZ NODATE CALL SYSCK JZ NODATE CALL ILPRT ;PRINT: DB ' since ' DATE: DB ' ' ;EIGHT SPACES DB 0 ;STRING TERMINATOR ; NODATE: MVI A,':' CALL TYPE JMP CRLF ; CKNON2: LDA GOTNF ORA A JNZ FINI ;JMP IF GOT NO 'NOT FOUND'S LDA PRTFLG ORA A JNZ FINI CALL ILPRT ;PRINT: (THEN FALL INTO 'FINI') DB '++NONE++',CR,LF,0 ; ;Finished. If building table, write back. ; If making a SUB file, then flush the file buffer and close it. FINI: LDA SUBFLG ;See if SUB file is to be written ORA A JNZ WRTSUB ;Jump if so, LDA SETFLG ;Else see if SET was performed ORA A JZ EXIT ;Jump out if not, JMP WRBACK ;Else write the program back to disk ; ;Write the SUB file to the currently logged in disk as 'D.SUB' WRTSUB: LHLD SUBPTR ;Fill unused part of last sector with EOF's XCHG LXI H,SUBBUF+7FH WNXTS: MVI M,1AH MOV A,L DCX H CMP E JNZ WNXTS CALL WRTSB2 ;Write the last sector to disk MVI C,CLOSE ;Close the file LXI D,LFCB CALL BDOS INR A ;If close error, then notify console and abort JZ BADWCL JMP EXIT ;Exit back to CP/M ; BADWCL: CALL MSGXIT DB 'BAD CLOSE, SUB file incomplete$' ; ;Set up the name in the table ; SETUP: IF NOSYS CALL SYSCK JZ SETU2 LDA SYSFLG RAL JC SETSKP ENDIF ;NOSYS ; SETU2: CALL FINDFF ;FIND END OF TABLE XCHG ;SETUP FOR MOVE ;(HL = name, DE = end of table) LXI B,11 CALL MOVER MVI A,0FFH ;GET TABLE END FLAG STAX D ;STORE IT ; SETSKP: POP B ;DELETE STACK GARBAGE JMP NEXT ;GET NEXT ENTRY ; ;Routine to type 'C' characters from memory (HL) ; TYPMEM: MOV A,M CALL TYPE INX H DCR C JNZ TYPMEM RET ; ;Inline print routine - prints string pointed to ;by stack until a zero is found. Returns to caller ;at next address after the zero terminator. ; ILPRT: XTHL ;SAVE HL, GET MSG ADRS ; ILPLP: MOV A,M ;GET CHAR CALL TYPE ;OUTPUT IT INX H ;POINT TO NEXT MOV A,M ;TEST ORA A ;..FOR END JNZ ILPLP XTHL ;RESTORE HL, RET ADDR RET ;RET PAST MSG ; CRLF: CALL ILPRT ;PRINT: DB CR,LF,0 RET ; SPACE: MVI A,' ' ;FALL INTO 'TYPE' ;Print character in A to console ; TYPE: PUSH B PUSH D PUSH H MOV C,A ;CHAR TO C FOR CBIOS TYPEC: CALL $-$ ;SUPPLIED AT START ; ;See if console key pressed ; TYPES: CALL $-$ ;SUPPLIED AT START ORA A ;KEY PRESSED? CNZ CKKB ;YES, SEE WHICH ONE POP H POP D POP B RET ; CKKB: CALL CI ;GET CHAR CPI 'S'-40H ;PAUSE? CZ CI ;YES, GET NEXT CHAR CPI 'C'-40H ;ABORT? RNZ ;NO, RETURN CALL MSGXIT DB CR,LF,'++ABORTED++$' ; ;Move (BC) bytes from (HL) to (DE) ; MOVER: MOV A,M STAX D INX D INX H DCX B MOV A,B ORA C JNZ MOVER RET ; ;Compare routine ; COMPR: LDAX D CMP M RNZ INX D INX H DCX B MOV A,B ORA C JNZ COMPR RET ;EQUAL MEANS Z=1 ; ;Routine to find 0FFH at end of table ; FINDFF: LXI H,NAMES ; FINDLP: MOV A,M INX H INR A ;0FFH? JNZ FINDLP DCX H ;BACK UP TO TABLE END RET ; ;Delete the name from the table ; DELNAM: LXI H,NAMES ; DELLP: MOV A,M CPI 0FFH STC RZ ;NOT FOUND LXI D,FCB+17 LXI B,11 CALL COMPR JZ DELETE DAD B ;CALC NEXT JMP DELLP ; ;Delete the name ; DELETE: XCHG ;NEXT NAME TO DE LXI H,-11 ;TO BACK UP.. DAD D ;..TO NAME TO DEL ; DELCH: LDAX D MOV M,A INX H INX D INR A ;MOVED THE 0FFH? JNZ DELCH ORA A ;SHOW FOUND RET ; ;Fill FCB with all '?' ; FILLQ: LXI H,FCB+1 MVI B,8+3 MVI A,'?' ; QMLOOP: MOV M,A INX H DCR B JNZ QMLOOP RET ; ;Write back the program - note that you may set any of the ;CP/M 2.x attribute bits in the file name (be sure to define ;all 11 characters of the name). ; WRBACK: LXI D,FCB+1 CALL WRBK2 WRBK1: DB 'D'+80H ;<--PUT 'D'+80H HERE TO SET TAG DB ' COM' ;SEE COMMENT ABOVE DB 0 ;EXTENT NUMBER ; WRBK2: POP H LXI B,WRBK2-WRBK1 CALL MOVER MVI C,ERASE LXI D,FCB CALL BDOS XRA A ;GET 0 STA SETFLG ;CLEAR THE FLAGS.. STA GOTFLG STA GOTNF STA SYSTOO STA FCBRNO ;ZERO RECORD NUMBER MVI C,MAKE LXI D,FCB CALL BDOS ; ;Before writing back, find end of table CALL FINDFF MOV B,H ;B=END PAGE INR B ;FOR COMPARE LXI D,100H+BIAS ;STARTING ADDR ; WRLP: PUSH B PUSH D PUSH H MVI C,SETDMA CALL BDOS MVI C,WRITE LXI D,FCB CALL BDOS POP H POP D POP B ORA A ;SUCCESSFUL WRITE? JNZ WRERR ;..NO LXI H,80H ;POINT TO.. DAD D ;..NEXT BLOCK XCHG ;ADDR TO DE MOV A,D ;GET PAGE CMP B ;PAST TABLE END? JC WRLP ;LOOP UNTIL DONE MVI C,CLOSE LXI D,FCB CALL BDOS INR A ;SUCCESSFUL CLOSE? JZ BADCLS ;..NO, PRINT ERR MSG CALL MSGXIT ;OK, EXIT W/MSG DB '++DONE++$' ; WRERR: CALL MSGXIT DB '++WRITE ERROR++$' ; BADCLS: CALL MSGXIT DB '++BAD CLOSE, D.COM CLOBBERED!!++$' ; ;Get console input via direct CBIOS call ; CI PUSH B ;CONSOLE INPUT PUSH D PUSH H CIC CALL $-$ ;SUPPLIED AT START POP H POP D POP B RET ; ;Exit with message (error or informational) ; MSGXIT: POP D ;GET MSG MVI C,PRINT CALL BDOS ; ;Exit, restoring DMA and stack, then return to CCP ; EXIT: LXI D,CPMBUFF ;RESET DMA ADR TO NORMAL MVI C,SETDMA CALL BDOS LHLD STACK ;GET OLD STACK SPHL ;RESTORE IT RET ;Return to CCP ; LINMRK: PUSH B PUSH D PUSH H LDA FCB ;GET DRIVE NAME FROM FCB ORA A ;ANY THERE? JNZ GOTDRV ;YES, GO PRINT IT MVI C,CURDSK ;ELSE GET CURRENT DISK CALL BDOS INR A ;MAKE 'A'=1 ; GOTDRV: ADI 40H ;MAKE ASCII CALL TYPE ;PRINT DRIVE NAME CALL ILPRT ;PRINT DB ': ',0 POP H POP D POP B RET ; ;Test for system file override ; SYSCK: PUSH H PUSH D PUSH B LXI H,SYSTOO LXI D,SYSOK MVI B,3 ; RSYSCK: LDAX D CMP M INX H INX D JNZ SYSOUT DCR B JNZ RSYSCK ; SYSOUT: POP B POP D POP H RET ; DS 64 ;ROOM FOR STACK STACK: DS 2 ;OLD STACK STORED HERE SUBFLG DB 00H ;Flag to order SUB file built SUBPTR DW 0000H ;Pointer to end of SUB file GOTFLG: DB 0 GOTNF: DB 0 SYSTOO: DB 0,0,0 SYSOK: DB 'S ' ;SYS SUPPRESSION OVERRIDE CHARS SETFLG: DB 0 ;1 => SETUP TABLE PRTFLG: DB 0 ;PRINT ONLY SOME SYSFLG: DB 0 ;$SYS ATTRIB INDICATOR LFCB DS 36H ;Local FCB used by SUB file write routines SUBBUF DS 128 ;Buffer used by SUB file write routines NAMES EQU $ ;Names NOT to print are stored here (i.e. current DIR) ; ;Note the names are initially built by the "D SET" command ; DB 0FFH ;END OF TABLE ; ; Miscellaneous BDOS equates RDCON EQU 1 DIO EQU 6 PRINT EQU 9 CONST EQU 11 SELDSK EQU 14 CLOSE EQU 16 SRCHF EQU 17 SRCHN EQU 18 ERASE EQU 19 READ EQU 20 WRITE EQU 21 MAKE EQU 22 CURDSK EQU 25 SETDMA EQU 26 ; END