home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol060
/
d-24.asm
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
17KB
|
885 lines
; D.ASM ver 2.4
; RESTRICTED DIRECTORY LIST PROGRAM
; (revised 03/01/81)
;
;D.COM is a directory list program, which writes
;5 entries on a line, separated by colons.
;
;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.
;
;
;Revisions/updates: (in reverse order to minimize reading time)
;
;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 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 lists the directory 5 across, listing
; only those files NOT in D.COM, as
; put there by 'D SET' or 'D ADD FN.FT'
; command.
;
;*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. "WHATSNEW.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".
;
;===================================================
;
FALSE EQU 0
TRUE EQU NOT FALSE
;
BDOS EQU 5
FCB EQU 5CH
FCBRNO EQU FCB+32
CR EQU 13 ;CARRIAGE RETURN
LF EQU 10 ;LINE FEED
;
NOSYS EQU TRUE ;SET TRUE TO IGNORE SYSTEM FILES
FENCE EQU ':' ;FILENAME SEPARATOR
NPL EQU 5 ;NAMES PER LINE
SYSOK EQU 'S' ;OVERRIDE CHAR FOR SYS SUPPRESSION
;
ORG 100H
;
DENTRY: JMP AROUND
;
DRIVE: DB 0 ;<---DRV # IS PUT HERE IF DEDICATED
;
;Init local stack
AROUND: LXI H,0 ;HL=0
DAD SP ;HL=STACK
SHLD STACK ;SAVE STACK POINTER
LXI SP,STACK ;INIT LOCAL STACK
CALL START
DB 'D ver 2.4',CR,LF
DB 'CTL-S pauses, CTL-C aborts',CR,LF,'$'
;
;Print ID message
;
START: POP D ;GET ID ADDRESS
MVI C,PRINT ;GET PRINT FNC
CALL BDOS ;PRINT ID MSG
LHLD 1
LXI D,3
DAD D ;HL=CONSTAT
SHLD CSTSC+1
DAD D ;HL=CONIN
SHLD CIC+1
;
;Set file control block
LDA DRIVE
ORA A ;NON-DEDICATED?
JZ NOND ;JUMP IF SO
STA FCB
;
NOND: LDA FCB+17 ;GET SYS OVERRIDE CHAR
STA SYSTOO ;SAVE FOR LATER
;
;See if request to add name to list
LXI H,FCB+1
CALL ADDCM2
ADDCM: DB 'ADD '
;
ADDCM2: POP D ;GET TO
LXI B,ADDCM2-ADDCM
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 lock D.COM to a drive
;
NOADD: 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 to setup table from directory
;
NODEL: 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
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,0EH
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 03H
MOV L,A
MVI H,00H
DAD H
DAD H
DAD H
DAD H
DAD H
LXI D,81H
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: CALL CSTS ;KEY PRESSED?
ORA A
CNZ CKKB ;YES, SEE WHICH ONE
;
IF NOSYS
LDA SYSTOO
CPI SYSOK
JZ DONAME
LDA SYSFLG
RAL
POP B
JC NEXT
PUSH B
ENDIF ;NOSYS
;
DONAME: MVI A,1 ;SAY WE GOT ONE
STA GOTFLG
MVI C,8
XCHG ;NAME BACK TO HL
;
NAMELP: MOV A,M
CALL TYPE
INX H
DCR C
JNZ NAMELP
MVI A,'.'
CALL TYPE
MVI C,3
;
NLP2: MOV A,M
CALL TYPE
INX H
DCR C
JNZ NLP2
POP B
MVI A,' '
CALL TYPE
MVI A,FENCE
DCR B
PUSH PSW
CNZ TYPE
MVI A,' '
CALL TYPE
POP PSW
JNZ NEXT
CALL CRLF
JMP LINE
;
CKNONE: LDA GOTFLG
ORA A
JNZ NOTFND
LDA PRTFLG
ORA A
JNZ NOTFND
LXI D,NONMSG ;PRINT "NONE"
MVI C,PRINT
CALL BDOS
;
;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: CALL LINMRK
MVI C,NPL
;
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 B,8
;
NAMLP2: MOV A,M
CALL TYPE
INX H
DCR B
JNZ NAMLP2
MVI A,'.'
CALL TYPE
MVI B,3
;
NLP3: MOV A,M
CALL TYPE
INX H
DCR B
JNZ NLP3
MVI A,' '
CALL TYPE
MVI A,FENCE
DCR C
PUSH PSW
CNZ TYPE
MVI A,' '
CALL TYPE
POP PSW
JNZ NEXT2
CALL CRLF
JMP LINE2
;
NOPRNT: DAD D
JMP NEXT2
;
;Print header
;
HEAD1: LXI D,NEWMSG
JMP HEDPRT
;
HEAD2: LXI D,DELMSG
;
HEDPRT: MVI C,PRINT
CALL BDOS
LDA DATE
CPI ' '
JZ NODATE
CPI SYSOK
JZ NODATE
LXI D,ASOF
MVI C,PRINT
CALL BDOS
;
NODATE: MVI A,':'
CALL TYPE
JMP CRLF
;
NEWMSG: DB CR,LF,'-->New files$'
;
DELMSG: DB CR,LF,CR,LF,'-->Deleted files$'
;
CKNON2: LDA GOTNF
ORA A
JNZ FINI ;JMP IF GOT NO 'NOT FOUND'S
LDA PRTFLG
ORA A
JNZ FINI
LXI D,NONMSG
MVI C,PRINT ;ELSE PRINT 'NONE'
CALL BDOS
JMP FINI
;
;Set up the name in the table
;
SETUP:
IF NOSYS
LDA SYSTOO
CPI SYSOK
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
;
CRLF: MVI A,CR
CALL TYPE
MVI A,LF
;
TYPE: PUSH B
PUSH D
PUSH H
MOV E,A
MVI C,02H
CALL BDOS
POP H
POP D
POP B
RET
;
;MOVE ROUTINE
;
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
;
;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' ;<--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 ;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!!++$'
;
;Finished. If building table, write back
;
FINI: LDA SETFLG
ORA A
JZ EXIT ;NOT WRITING
JMP WRBACK
;
;Direct BIOS calls follow
;
CSTS PUSH B ;CONSOLE STATUS
PUSH D
PUSH H
CSTSC CALL $-$ ;SUPPLIED AT START
POP H
POP D
POP B
RET
;
CI PUSH B ;CONSOLE INPUT
PUSH D
PUSH H
CIC CALL $-$ ;SUPPLIED AT START
POP H
POP D
POP B
RET
;
CKKB: CALL CI
CPI 'S'-40H
CZ CI
CPI 'C'-40H
JZ ABORT
RET
;
ABORT: CALL MSGXIT
DB CR,LF,CR,LF,'++ABORTED++',CR,LF,'$'
JMP EXIT
;
;Exit with message (error or informational)
;
MSGXIT: POP D ;GET MSG
MVI C,PRINT
CALL BDOS
;
;Exit, restoring dma and stack, then return
;
EXIT: LXI D,80H ;RESET DMA ADR TO NORMAL
MVI C,SETDMA
CALL BDOS
LHLD STACK ;GET OLD STACK
SPHL ;RESTORE IT
RET ;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 GOTDR2 ;THEN ': '
DB ': $'
;
GOTDR2: POP D ;GET MSG ADR
MVI C,PRINT ;PRINT IT
CALL BDOS
POP H
POP D
POP B
RET
;
DS 64 ;ROOM FOR STACK
STACK: DS 2 ;OLD STACK STORED HERE
GOTFLG: DB 0
GOTNF: DB 0
SYSTOO: DB 0
NONMSG: DB '++NONE++',CR,LF,'$'
ASOF: DB ' since '
DATE: DB ' '
DB '$'
SETFLG: DB 0 ;1 => SETUP TABLE
PRTFLG: DB 0 ;PRINT ONLY SOME
SYSFLG: DB 0 ;$SYS ATTRIB INDICATOR
NAMES EQU $ ;NAMES NOT TO PRINT, STORED HERE
;
;Note the names are initially built by: D SET
;
DB 0FFH ;END OF TABLE
;
;BDOS equates
;
RDCON EQU 1
DIO EQU 6
PRINT EQU 9
CONST EQU 11
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