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
/
ALLDIR11.LBR
/
ALLDIR.MQC
/
ALLDIR.MAC
Wrap
Text File
|
2000-06-30
|
8KB
|
334 lines
; ALLDIR by ESKAY v1.10 09/21/85
;
; A directory program that displays all files on all disks
; sorted by name and user area.
;
; syntax:
; ALLDIR ; displays on screen
; ALLDIR -L ; displays on screen and printer
; ALLDIR -FFOO.BAR ; displays on screen and writes file "FOO.BAR"
;
; NOTE:
; Thanks to Richard Norman for bug fix and suggestions.
; version 1.10 now adds the following feature in addition to the
; bug fix:
; A special version of ALLDIR can be generated by changing the byte
; at 0101H to non-zero. If zero, operation is as usual. if nonzero,
; ALLDIR will only display files on the current drive.
; Also, the file SORT.REL has been added to the LBR file. To reassemble:
; 0A}M80 =ALLDIR
; 0A}LINK ALLDIR,SORT,SYSLIB[S]
; Note that I use Digital Research LINK rather than L80 because of
; L80's stupid placement of CSEG and DSEG. Use L80 at own risk!
;
.z80 ; use zilog mnemonics
;
; declaration section
; (externals dynamically declared)
;
cr equ 0dh ; RETURN
lf equ 0ah ; LINEFEED
;
dbuf equ 80h ; default dma buffer
;
cseg ; code section
;
start: ld a,0 ; change to LD A,1 for singledrive
sglflg equ $-1
ld sp,stack ; set up stack pointer
call print##
cr,lf,lf
'ALLDIR v1.10 by ESKAY',cr,lf,lf
'Reading directory on drive ',0
xor a ; set up drive
ld (drive),a
call codend## ; get buffer
ld (bufptr),hl ; save as buffer ptr
ld (lodrv),hl ; and as drive buffer ptr
ld hl,(5) ; get end of tpa
ld l,0 ; make even boundary
ld (bufend),hl ; store as end of buffer
ld hl,0
ld (count),hl ; zero count
ld c,24 ; get login vector
call bdos##
ld (ready),hl
ld a,(sglflg) ; check if single drive version
or a
jr z,loop ; no, behave normally
ld c,25 ; else get drive
call bdos##
jr loopx
;
; loop here until all drives are checked
;
loop: ld a,(sglflg) ; check if single
or a
jp nz,sortit ; done if single drive
ld a,(drive) ; get drive
loopx: ld e,a
inc a
ld (drive),a ; get ready for next drive
cp 16 ; is this one P:?
jp z,sortit ; yes, done reading
push af
ld hl,(ready) ; get ready vector
or a ; reset carry
ld a,h
rra
ld h,a
ld a,l
rra
ld l,a
ld (ready),hl
jp c,..rdy ; continue if ready...
pop af ; else clean up stack
jp loop ; and check next drive
;
..rdy: pop af
call print
8,0
ld e,a ; drive+1 in e
dec e
add a,40h ; make ascii drive letter
call cout##
ld c,14 ; select disk
call bdos##
ld hl,(bufptr)
ld (lodrv),hl
ld c,17 ; search for first
ld de,fcb ; select fcb
ld a,'?' ; bug fix: thanks to Richard Norman
ld (de),a ; " "
call bdos## ; get first entry
call movefn ; move fn if only one and not deleted
..rdlp: call print
':',8,0
ld c,18 ; search for next
ld de,fcb
call bdos##
cp 0ffh ; end of directory?
jp z,loop
call movefn ; move if ok
call print
' ',8,0
call condin## ; check for abort
cp 3
jp nz,..rdlp
jp exit
;
; come here to sort the whole mess
;
sortit: call print##
cr,lf
'Sorting file names...',0
ld hl,(count) ; get number of files...
ld b,h ; .. into bc
ld c,l
ld de,13 ; 13 bytes per entry
call codend## ; buffer start
call sort## ; do it now
call print##
cr,lf,cr,lf
' Total files displayed: ',0
ld hl,(count)
call phlfdc##
call print
cr,lf,cr,lf,0
call codend##
ld (bufptr),hl
ld a,21 ; first screen has only 21 lines of filenames
jp ..1st
;
; now print the buffer, a file at a time like " 5A:ALLDIR .COM"
;
ploop: ld a,24
..1st: ld (lps),a
ploop1: ld a,4 ; 4 file names per line
ld (npl),a ; set up variable
call crlf## ; start a new line
ploop2: ld hl,(bufptr) ; get pointer to next filename
ld d,h ; put into de also
ld e,l
ld bc,11 ; offset to user area
add hl,bc ; hl now points to user
ld a,(hl) ; get user
ld c,'0'-1 ; convert to decimal ascii
..cvrt: inc c
sub 10
jp nc,..cvrt
add a,'0'+10 ; a=units, c=tens
push af ; save units
ld a,c ; get tens
cp '0' ; if (leading) zero...
jp nz,..nz ; then skip...
ld a,' ' ; else blank
..nz: call cout##
pop af ; get tens
call cout##
inc hl
ld a,(hl) ; get drive
add a,'@'
call cout##
ld a,':'
call cout##
call pfn1## ; print file name
ld hl,(bufptr) ; get pointer
ld de,13 ; point to next name
add hl,de
ld (bufptr),hl ; save pointer
ld hl,(count) ; get count
dec hl ; count down
ld (count),hl
ld a,h
or l ; to zero
jp z,exit ; done if zero!
ld a,(npl) ; get name count
dec a
ld (npl),a
jp z,..nwl
call print## ; print fence
' | ',0
jp ploop2
;
..nwl: ld a,(lps) ; get line count
dec a
ld (lps),a
jp nz,ploop1
call cin##
cp 3
jp nz,ploop
;
; all finished
;
exit: call crlf##
rst 0
;
; subroutine section
;
; move filename into buffer
; a=dbuf-relative location. the filename is only moved if
; it does not already exist in the buffer
;
movefn: ld hl,dbuf ; hl points to buffer
ld de,32 ; offset
inc a ; make a=1..4
..cof: dec a
jp z,..gof ; go offset in hl if 0
add hl,de
jp ..cof
;
..gof: ld a,(hl) ; get user area byte
cp 0e5h ; if erased
ret z ; then return immediately
inc hl
push hl ; save dbuf pointer
;
; now make entry table compatible, ie UD:FN.EXT
;
push af ; save user area
ld b,11 ; 11 chars
..norl: ld a,(hl) ; get byte
and 7fh ; strip parity
ld (hl),a ; put it back
inc hl ; point to next byte
dec b ; count down
jp nz,..norl ; and loop until all 11 chars done
pop af ; get user back
ld (hl),a ; save user after name
inc hl
ld a,(drive) ; get drive (A=1..P=16)
ld (hl),a ; save after user
call codend## ; get buffer start
ld d,h
ld e,l ; into de
pop hl
;
; the following code checks for duplicates and returns immediately
; if a duplicate filename is found
;
ckdup: push hl ; save dbuf ptr
ld hl,(lodrv) ; get base for this drive
ld b,h
ld c,l ; into bc
ld hl,(bufptr) ; get buffer pointer
ld d,h
ld e,l ; into de
pop hl ; get dbuf ptr
push hl ; and save it again
..cdlp: ld a,b ; check if end of buffer reached
cp d
jp nz,..neb ; no
ld a,c
cp e
jp z,..ndup ; yes, done checking
..neb: push de ; save end pointer
push hl ; save dbuf ptr
ld de,13 ; 13 bytes to compare
..nebl: ld a,(bc) ; get byte
cp (hl) ; see if same
jp nz,..neeq ; no, advance ptrs
inc bc
inc hl
dec e
jp nz,..nebl ; loop until all checked
pop hl
pop de
pop hl
ret ; found a dupe
;
..neeq: push bc
pop hl
add hl,de
push hl
pop bc
pop hl
pop de
jp ..cdlp
;
..ndup: ld hl,(bufptr) ; get current buffer pointer
ld d,h
ld e,l ; into de
pop hl ; get dbuf ptr back
ld b,13 ; 13 bytes to move
..movl: ld a,(hl)
ld (de),a
inc hl
inc de
dec b
jp nz,..movl
ex de,hl
ld (bufptr),hl ; save buffer pointer
ld hl,(count) ; get count
inc hl ; bump it
ld (count),hl ; and save it
ld hl,(bufptr)
ld d,h
ld e,0
ld hl,(bufend)
ld a,h
cp d
ret nz ; dun
call print##
cr,lf,lf,7
'ERROR: memory full, processing buffer...',cr,lf,0
pop hl ; clean stack
jp sortit
;
; data storage and stack section
;
bufptr: dw 0 ; buffer pointer
lodrv: dw 0 ; low drive buffer pointer
bufend: dw 0 ; end of buffer space
count: dw 0 ; total file count
ready: dw 0 ; drive ready vector
drive: db 0 ; next drive
npl: db 0 ; names per line counter
lps: db 0 ; lines per screen counter
;
fcb: db '?' ; that is enough
ds 80 ; 40 level stack
stack equ $
end
pop hl
add hl,d