home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
utils
/
dirutl
/
d-31.asm
< prev
next >
Wrap
Assembly Source File
|
1994-07-13
|
26KB
|
1,293 lines
; D.ASM v3.1 - 05/05/84
;
; RESTRICTED DIRECTORY LIST PROGRAM
;
; 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,
; such as ED.COM, ASM,COM, PIP.COM, STAT.COM, etc. When you do a direc-
; tory listing, you typically are not 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.
;-----------------------------------------------------------------------
;
; 05/05/84 Line with the "use FILE xxx*.*" now only appears on the line
; v3.1 with the message about moved or deleted files.
; - Irv Hoff
;
; 05/01/84 Changed the "Deleted files since --- " to "Files moved else-
; v3.0 where or deleted", then added a line "use FILE xxx*.* to see
; if available." With 20-40 megabyte disk systems now common,
; this is a convenient way to locate files which are no longer
; in the "Whatsnew" user area. It was misleading when reading
; the files had been deleted when most have merely been moved.
; (Every SYSOP needs FILE.COM on his system.) SD xxx*.* $U0AD
; may also be used, but gives information that is superfluous.
; Standardized the format. - Irv Hoff
;
; 08/12/82 Added SUB file option to allow writing each new filename
; v2.9 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 the program
; will work better with 'type-ahead' BIOSes.
; - Dave Hardy
;
; 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 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 about 70 characters, 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 will not
; 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 current-
; ly 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: A>ED TEST.ASM, A>ASM TEST and LOAD TEST.
; 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 will not up as "deleted".
;
;=======================================================================
;
; SPECIAL NOTES FOR REMOTE SYSTEM USE:
;
; If you keep a dedicated copy of this program on each drive of your re-
; mote 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 YES, $SYS files in CP/M 2.x will be
; ignored in both directory listings and when the "ADD" option is in-
; voked, 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..
;
; 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".
;
;=======================================================================
;
; Define some stuff
;
YES: EQU 0FFH
NO: EQU 0
;
;
BIAS: EQU 0 ;for std cp/m or 4200h for altcpm
BDOS: EQU 5+BIAS ;cp/m's BDOS access jump
CPMBUFF:EQU 80H+BIAS ;cp/m command line buffer
CR: EQU 0DH ;carriage return
FCB: EQU 5CH+BIAS ;cp/m's file control block
FCBRNO: EQU FCB+32 ;rec # in fcb
LF: EQU 0AH ;line feed
;
;
; Set the following for your system:
;
NOSYS EQU YES ;yes=ignore $sys files
FENCE EQU ':' ;file name separator
NPL EQU 4 ;file names per 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)
;
;Initialize the 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 v3.1',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
ORA A ;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
ORA A ;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' ;total of this and the next line must..
TITLEN: DB ' ' ;be 11, change for a longer title name
;
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
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 ' ;must be 11 total
;
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 ' ;must be 11 total
;
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 ;tell console that sub file will be made
DB 'Writing SUBMIT file...',CR,LF,'$'
;
SAYSUB: POP D
MVI C,9
CALL BDOS
MVI A,0FFH ;tell prgm 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 to 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 ;(no 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 ' ;must total 11
;
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
;
LXI H,FCB+17
LXI D,DATE1
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 but do not 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 ;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 ;hl to sub buffer (de to filename)
MVI C,8 ;8 characters in filename
MVI M,'$' ;first write '$1'
CALL INCPTR ;increment file buffer pointer and..
MVI M,'1' ;..write if full
CALL INCPTR
;
SNAM: LDAX D ;get a character of the name
CPI ' ' ;do not 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 '.' separator into the sub buffer
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..
CALL INCPTR ;.. of the name
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
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 so
MVI C,SETDMA ;..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
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 HEAD3 ;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
LDA DATE
CPI ' '
JZ HEAD2
CALL SYSCK
JZ HEAD2
CALL ILPRT ;print:
DB ' since '
;
DATE: DB ' ' ;eight spaces
DB 0 ;string terminator
JMP CRLF
;
HEAD2: MVI A,':'
CALL TYPE
JMP CRLF
;.....
;
;
HEAD3: CALL ILPRT ;print:
DB CR,LF,CR,LF,'-->Files moved elsewhere or deleted',0
LDA DATE
CPI ' '
JZ HEAD5
CALL SYSCK
JZ HEAD5
CALL ILPRT ;print:
DB ' since '
;
DATE1: DB ' ' ;eight spaces
DB 0 ;string terminator
;
HEAD4: CALL ILPRT
DB CR,LF,' (use FILE xxx*.* to see if available)'
DB CR,LF,0
RET
;
HEAD5: MVI A,':'
CALL TYPE
JMP HEAD4
;.....
;
;
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 rest 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..
JZ BADWCL ;..and abort
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,' '
;
;
; 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 YES
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
SUBBUF DS 128 ;buffer used by sub file write routines
NAMES EQU $ ;names not to print are stored here..
;..(i.e., the 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