home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
UTILS
/
DIRUTL
/
DIRDIRS2.LBR
/
DIR.ZZ0
/
DIR.Z80
Wrap
Text File
|
2000-06-30
|
9KB
|
436 lines
;------------------------------------------------------------------------------
;
; A simple DIR program (with some extra features)
;
; Written to provide a substitute for the simple DIR and DIRSYS
; commands not supported internally by CCP103+.
;
; dir {du:}{filespec} or dirsys {du:}{filespec}
;
; du: is optional and can be any combination of a valid drive
; and/or user number, e.g. 13:, b:, b13:, 13b: or even 1b3:
;
; filespec is also optional and is a standard ambiguous or unambiguous
; file name.
;
; Program automatically adjusts directory display to the size of the
; host system's console screen.
;
; Create two versions of this program, DIR.COM and DIRSYS.COM (or
; DIRS.COM if you prefer the shorter form of the DIRSYS command).
; Put the two commands in COMMAND.LBR if you wish, and rename the
; standard DIR.COM to something else, e.g. XD.COM.
;
; To create the two versions, alter the byte at label 'dirsys:'
; appropriately and reassemble. Alternatively you may patch the
; fourth byte in the object code (103h) to zero for DIR or non-zero
; for DIRSYS.
;
; This program can be assembled with either Microsoft's M80 or the
; ex-Cromemco public domain ZASM assembler without altering the source
; code. (Note the /z switch and the .z80 extension in the M80 case.)
;
; For M80/L80 :- or ZASM/PROLINK :-
;
; m80 =dir.z80/z zasm dir.@@z
; l80 dir,dir/n/e pl link dir;exit
;
; Jon Saxton,
; P.O. Box 242,
; Dural, NSW 2158
; Australia
;
;------------------------------------------------------------------------------
;
; 19 Apr 87 - JRS
;
; Amended to sidestep an occasional weirdness which caused program
; to erroneously report "Invalid drive/user".
;
;------------------------------------------------------------------------------
BS equ 8
HT equ 9
CR equ 13
LF equ 10
BDOS equ 5
CONIN equ 1
CONOUT equ 2
PRINT equ 9
SRCH1ST equ 17
SRCHNXT equ 18
GETDRV equ 25
GSUSER equ 32
GSSCB equ 49
PARSEFN equ 152
PAGEMODE equ 2Ch ;Index of page mode byte in SCB
PAGELEN equ 1Ch ;Index of console page length in SCB
CONWIDTH equ 1Ah ;Index of console width in SCB
;begin: ;Linker inserts jp setStack at the beginning
; jp setStack ;of the object file (see 'end' statement)
dirsys:
defb 0 ;Set non-0 to display system files
setStack:
ld hl,(BDOS+1) ;Set stack up under the BDOS
ld l,0
ld sp,hl
ld a,(dirsys) ;Normalise the DIRSYS flag to 0 or 80h
or a
jr z,getLPS
ld a,80h
ld (dirsys),a
getLPS:
ld de,scbpb ;Get number of lines on screen
push de
ld a,PAGELEN
ld (de),a
ld c,GSSCB
call cpm
dec a ;One less to allow for [more] prompt
ld (lpp),a
ld (lines),a
pop de ;Get console width
ld a,CONWIDTH
ld (de),a
ld c,GSSCB
call cpm
ld b,8
ld c,a
ld a,15*8+1
getNPL: ;Calculate names per line (maximum 8)
cp c
jr c,setNPL
sub 15
djnz getNPL
setNPL:
ld a,b
ld (npl),a
ld (count),a
xor a ;Clear the user number
ld ix,du
ld (ix+1),a
ld c,GSUSER ;Get current user number
ld e,0FFh
call cpm
ld (curUsr),a ;Store it as default
ld c,GETDRV ;Get current disk
call cpm
inc a
ld (ix+0),a ;Store it as default
ld hl,80h ;Look at command-line tail
skipWs:
inc hl
ld a,(hl) ;Get a character
cp ' ' ;Skip leading white space
jr z,skipWs
cp HT
jr z,skipWs
ld b,4 ;Colon must be in first 4 characters
push hl
findColon:
ld a,(hl) ;Fetch byte from command tail
or a
jr z,noColon ;Exit [not found] if end of command tail
cp ':'
jr z,colon ;Exit [found]
inc hl ;Step the pointer
djnz findColon
noColon:
inc a
colon:
pop hl ;Point back at command line
jr nz,duDone ;Skip if there wasn't a colon
;If we get here then there was a colon in the command tail. We will
;rescan that part of the command tail preceeding the colon and attempt
;to extract a drive/user specification.
nxtChr:
ld a,(hl) ;Pick up a byte from the command tail
inc hl
cp ':' ;Test for colon terminator
jr z,duDone ;Exit if done
cp '0' ;Check for a digit
jr c,chkDrv
cp '9'+1
jr nc,chkDrv
call cnvUsr ;Build user number
jr nxtChr
chkDrv:
cp 'A' ;Check for A-P
jr c,badDU ;Error if out of range
cp 'Q'
jr nc,badDU
sub 'A'-1 ;Convert A-P to 1-16
ld (ix+0),a
jr nxtChr
badDU:
ld de,invDU
prtXit:
ld c,PRINT
call cpm
rst 0
cnvUsr:
sub '0'
ld c,a
ld a,(ix+1)
add a,a ;x2
add a,a ;x4
add a,(ix+1) ;x5
add a,a ;x10
add a,c
ld (ix+1),a
ld a,1
ld (gotUsr),a
ret
duDone:
ld a,(gotUsr) ;Did we get user number from command line?
or a
jr z,noUsr
ld a,(ix+1)
ld e,a
ld (curUsr),a
ld c,GSUSER ;Set user number to match command line
push hl
call cpm ;Just a temporary change
pop hl
noUsr:
; At this point we are in the correct user area for the DIR command,
; the byte at DU: holds the required disk drive number (or zero for
; current drive) and HL points at the beginning of the file spec.
ld a,(hl) ;If file specification is empty then
or a ;we leave the default *.* alone
jr z,setDrv
ld (pfcb),hl ;Let CP/M 3 do all the hard work
ld de,pfcb ;in setting up the FCB for the
ld c,PARSEFN ;directory search
call cpm
setDrv:
ld a,(ix+0) ;Pick up drive number
ld de,fcb
ld (de),a ;Plug into directory FCB
getDir:
ld hl,dirFn
ld c,(hl)
ld a,SRCHNXT
ld (hl),a
call cpm ;Get directory data
cp 0FFh ;Test for end
jr z,others?
ld de,81h ;Offset to first byte of file name
rept 5 ;Build pointer to file name
add a,a
endm
ld l,a
ld h,0
add hl,de
push hl ;Save file name pointer
ld de,9 ;Offset to T2 byte of file name [SYS|DIR]
add hl,de
ld a,(dirsys)
xor (hl)
bit 7,a ;Test if SYS or DIR matches dirsys
jr z,printIt
ld a,1
ld (others),a
pop hl
jr getDir
printIt:
ld hl,npl
ld a,(count) ;Count files displayed on this line
cp (hl) ;At end of line?
call z,newLine ;Yes - start new line, ..
call z,putDU ;.. and print drive/user
call nz,fence ;No - print separator
inc a ;Increment count of files on this line
ld (count),a ;Store count for next time
pop hl ;Recover file name pointer
call printFn ;Display current file name
ld a,1 ;Signal that we have displayed some files
ld (some),a
jr getDir
others?:
ld a,(others) ;See if we found ANY files at all
ld b,a
ld a,(some)
or b
ld de,noFiles
jp z,prtXit ;Tell user if none
xor a
or b ;See if any undisplayed files
jp z,0 ;Exit if none
ld de,crlf ;Start a new line
ld c,PRINT
call cpm
ld de,s
ld a,(dirsys)
or a
jp z,prtXit
ld de,nonS
ld c,PRINT
call cpm
ld de,ystem
jp prtXit
newLine:
ld a,(some) ;Is this the first time through?
or a
jr z,noNL ;Yes - do nothing
ld de,crlf ;No - start new line
ld c,PRINT
call cpm
ld a,(lines) ;Count number of lines displayed
dec a
ld (lines),a
jr nz,noNL ;Skip if not at end of screen
ld c,GSSCB ;Find out if console paging is in effect
ld de,scbpb
ld a,PAGEMODE
ld (de),a
call cpm
or a
jr nz,noNL ;Skip if not paging
ld de,more ;Display [more] prompt
ld c,PRINT
call cpm
ld c,CONIN ;Wait for a keystroke
call cpm
ld de,backSpace ;Backspace over the prompt and response
ld c,PRINT
call cpm
ld a,(lpp) ;Reset lines per page
ld (lines),a
noNL:
xor a
ret
fence: ;Display file name separator
push af
ld de,separator
ld c,PRINT
call cpm
pop af
ret
printFn: ;Display file name @HL
ld b,8
call outStr
push hl
ld e,'.'
call outChr
pop hl
ld b,3
call outStr
ret
outStr: ;Print string @HL for B bytes
ld e,(hl)
res 7,e
inc hl
push hl
push bc
call outChr
pop bc
pop hl
djnz outStr
ret
outChr: ;Print a single character from E register
ld c,CONOUT
call cpm
ret
putDU:
push af
call putDrv
call putUsr
ld e,':'
call outChr
pop af
ret
putDrv: ;Display drive letter
ld a,(ix+0)
add a,'A'-1
ld e,a
call outChr
ret
putUsr:
ld a,(curUsr)
cp 10 ;Two digits?
jr c,uLow ;No - just one
sub 10 ;Yes - output '1' and then the low-order digit
push af
ld e,'1'
call outChr
pop af
uLow:
add a,'0'
ld e,a
call outChr
ret
cpm:
push ix
call BDOS
pop ix
ret
;----------------------------------------------
crlf: defb CR,LF,'$'
separator:
defb ' | $'
count: defs 1
lines: defs 1
lpp: defs 1
npl: defs 1
some: defb 0
others: defb 0
dirFn: defb SRCH1ST
du: defw 0 ;Drive/user from command line
curUsr: defs 1 ;Current user number
gotUsr: defb 0 ;Flag for command-line user number
fcb: defb 0
defb '????????'
defb '???'
defw 0,0,0,0,0,0,0,0,0,0
pfcb: defw 0
defw fcb
scbpb: defs 1
defb 0
defs 2
invDU: defb 'Illegal drive/user$'
nonS: defb 'Non-s$'
S: defb 'S'
ystem:
defb 'ystem files exist$'
noFiles:
defb 'No files found$'
more:
defb '[more] $'
backSpace:
rept 15
defb BS
endm
defb '$'
end setStack