; 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