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
/
RCPM
/
LUX80.ARK
/
LUXDIR12.MAC
< prev
next >
Wrap
Text File
|
1987-02-02
|
13KB
|
607 lines
; LUXDIR12.MAC LUX Utility DIR transient 01-23-84
;
; Copyright 1983 by Steven R. Holtzclaw and entered into the public domain.
;
; Modification history in reverse order:
;
; 01-23-84 Small formatting changes - Added documentation header.
; LUXDIR12 Mark Howard
;
; 11-26-83 Original version ??
; LUXDIR11
;
;
.Z80
ASEG
ORG 100H
;
CR EQU 0DH
LF EQU 0AH
;
DBUF EQU 80H ; default buffer
FCB EQU 05CH ; default fcb
FCB2 EQU 06CH
MAXCOL EQU 4 ; number of dir columns
FENCE EQU '|' ; fence character
;
BEGIN: LD HL,0
ADD HL,SP
LD (STAKER+1),HL
LD A,(FCB2+1) ; any files specified ?
CP 020H ; space?
JR NZ,BEGN2 ; ...no - continue
LD HL,FCB2+1 ; index fcb2 filename
LD A,'?' ; wildcard
LD B,11 ; 11 bytes to fill
BEGN1: LD (HL),A ; put a byte
INC HL ; next byte
DJNZ BEGN1 ; do all 11 bytes
;
BEGN2: LD HL,FCB
LD DE,FCB1
LD BC,12
LDIR ; move to local fcb
LD DE,DBUF ; set default dma address
LD C,26
CALL 5
LD DE,FCB1 ; index .fcb for search
LD C,17
CALL 5 ; search for first
INC A
JP Z,NOFILE ; barf if not found
LD DE,FCB1 ; index fcb for open
LD C,15
CALL 5 ; open the file for input
XOR A
LD (DIRS),A ; set dir sector count = 0
LD (COL),A ; set column count to 0
LD HL,(6) ; get bdos location
LD DE,ORDER ; get end of our program
SBC HL,DE ; available free memory
;
; calculate the approximate max number of directory entries
;
LD B,4 ; loop here 4 times
DIVLOP: SRL H
RR L ; * 2
DJNZ DIVLOP ; hl=hl/16
LD (MAXDIR),HL ; set the max number of dirs
ADD HL,HL
LD DE,ORDER
ADD HL,DE ; calculate the start of name table
LD (NAMBUF),HL ; base location for name table
LD (TBLOC),HL ; dito
CALL ILPRT
DEFB 13,10
DEFB 'LBR directory for ',0
CALL PFLNAM ; print the file name
CALL ILPRT
DEFB 13,10,10,0
GETLP: CALL RDBLOK ; get a block
LD A,(DIRS) ; increment
INC A ; directory
LD (DIRS),A ; and sector count
LD HL,DBUF ; point to first entry
LD A,(HL) ; get status byte
OR A
JP Z,STATOK ; skip if active
;
; the first entry of this sector is inactive.
; if its not sector 1, all's well. if it is,
; we dont have a lbr file!
;
LD A,(DIRS)
DEC A
JP NZ,ENT2 ; skip if not first sector
CALL ILPRT
DEFB CR,LF
DEFB 'Directory error in ',0
CALL PFLNAM ; print the filename
CALL ILPRT
DEFB 13,10,0
JP EXIT
;
STATOK: LD A,(DIRS) ; check if first entry
DEC A
JP NZ,NOTD ; skip if not 1st sector
LD HL,DBUF+14 ; get lbr directory size...
LD A,(HL) ; ...into a
LD (DIRSIZ),A ; save dir size...
JP ENT2 ; ...and skip
;
NOTD: LD HL,DBUF+00H
CALL ADDBUF
ENT2: LD HL,DBUF+20H ; point to second entry
CALL ADDBUF ; process it
ENT3: LD HL,DBUF+40H ; third entry
CALL ADDBUF
ENT4: LD HL,DBUF+60H ; last entry for this sector
CALL ADDBUF
LD A,(DIRS) ; get # of sectors done
LD HL,DIRSIZ ; compare with...
CP (HL) ; ...total directory size
JP NZ,GETLP ; loop if not finished...
JP SPRINT ; ...else sort and print the directory
;
; add a member name to nambuf names queue
;
ADDBUF: LD A,(HL) ; get status
OR A
RET NZ ; skip if empty/inactive
INC HL
LD A,(HL) ; get first byte of member name
OR A
RET Z ; skip if a null entry
PUSH HL ; save dbuff pointer
LD DE,FCB2+1 ; index
LD B,11 ; 11 characters to compare
ADDBU1: LD A,(DE) ; get character from fcb2
CP '?' ; '?' matches all
JR Z,ADDBU2
CP (HL) ; same a command line
JR NZ,ADDBU3 ; ...no - skip this entry
ADDBU2: INC HL
INC DE
DJNZ ADDBU1 ; loop for 11 character compares
POP HL
LD BC,(COUNT) ; dump entry counter
INC BC
LD (COUNT),BC
LD DE,(NAMBUF) ; get destination of move
LD BC,11 ; 11 character file name
LDIR ; move it
INC HL ; point to file size
INC HL
LD BC,2 ; 2 byte file size
LDIR ; move it
LD (NAMBUF),DE ; save destination of next move
RET
ADDBU3: POP HL ; balance stack
RET
;
; sort and print
;
SPRINT: LD HL,(COUNT) ; get file name count
LD (MAXNUM),HL ; set number of times to print
LD (MEMBRS),HL ; set total number of members
LD A,L
OR H ; any found?
JP Z,DONE ; exit if no files found
PUSH HL ; save file count
LD (SUPSPC),A ; enable leading zero suppression
;
;
; initialize the order table
;
LD HL,(TBLOC) ; get start of name table
EX DE,HL ; into de
LD HL,ORDER ; point to order table
LD BC,13 ; entry length
;
BLDORD: LD (HL),E ; save low order address
INC HL
LD (HL),D ; save high order address
INC HL
EX DE,HL ; table addr to hl
ADD HL,BC ; point to next entry
EX DE,HL
EX (SP),HL ; save tbl addr, fetch loop counter
DEC HL ; count down loop
LD A,L
OR H ; more?
EX (SP),HL ; (restore tbl addr, save counter)
JP NZ,BLDORD ; yes, go do another one
POP HL ; clean loop counter off stack
LD HL,(COUNT) ; get count
LD (SCOUNT),HL ; save as # to sort
DEC HL ; only 1 entry?
LD A,L
OR H
JP Z,DONE ; yes, so skip sort
;
;
; this sort routine is adapted from software tools by kernigan and
; plaugher.
;
SORT: LD HL,(SCOUNT) ; number of entries
;
SORT0: OR A ; clear carry
LD A,H ; gap=gap/2
RRA
LD H,A
LD A,L
RRA
LD L,A
OR H ; is it zero?
JP Z,DONE ; then none left
LD A,L ; make gap odd
OR 1
LD L,A
LD (GAP),HL
INC HL ; i=gap+1
;
SORT2: LD (VARI),HL
EX DE,HL
LD HL,(GAP)
LD A,E ; varj=i-gap
SUB L
LD L,A
LD A,D
SBC A,H
LD H,A
;
SORT3: LD (VARJ),HL
EX DE,HL
LD HL,(GAP) ; jg=varj+gap
ADD HL,DE
LD (VARJG),HL
LD A,12 ; compare 12 chars
CALL COMPARE ; compare (varj) and (jg)
JP P,SORT5 ; if a(varj)<=a(jg)
LD HL,(VARJ)
EX DE,HL
LD HL,(VARJG)
CALL SWAP ; exchange a(varj) and a(jg)
LD HL,(VARJ) ; varj=varj-gap
EX DE,HL
LD HL,(GAP)
LD A,E
SUB L
LD L,A
LD A,D
SBC A,H
LD H,A
JP M,SORT5 ; if varj>0 goto l3
OR L ; check for zero
JP Z,SORT5
JP SORT3
;
SORT5: LD HL,(SCOUNT) ; for later
EX DE,HL
LD HL,(VARI) ; i=i+1
INC HL
LD A,E ; if i<=n goto l2
SUB L
LD A,D
SBC A,H
JP P,SORT2
LD HL,(GAP)
JP SORT0
;
; new compare routine
;
COMPARE:
LD BC,ORDER-2
ADD HL,HL
ADD HL,BC
EX DE,HL
ADD HL,HL
ADD HL,BC
EX DE,HL
LD C,(HL)
INC HL
LD B,(HL)
EX DE,HL
LD E,(HL)
INC HL
LD D,(HL)
EX DE,HL
LD E,A ; count
;
CMPLPE: LD A,(HL)
AND 7FH
LD D,A
LD A,(BC)
AND 7FH
CP D
INC BC
INC HL
RET NZ
DEC E
JP NZ,CMPLPE
RET
;
;
; swap entries in the order table
;
SWAP: LD BC,ORDER-2 ; table base
ADD HL,HL ; *2
ADD HL,BC ; + base
EX DE,HL
ADD HL,HL ; *2
ADD HL,BC ; + base
LD C,(HL)
LD A,(DE)
EX DE,HL
LD (HL),C
LD (DE),A
INC HL
INC DE
LD C,(HL)
LD A,(DE)
EX DE,HL
LD (HL),C
LD (DE),A
RET
;
; sort is all done - print entries
;
DONE:
PLOOP: LD HL,(MAXNUM) ; get number of entries to print
LD A,H
OR L
JP Z,PLOOP6 ; if all done
;
PLOOP1: LD HL,ORDER ; index order
LD E,(HL) ; get entry lsb
INC HL ; next
LD D,(HL) ; get entry msb
INC HL ; next
LD (PLOOP1+1),HL ; set next order address
EX DE,HL ; hl scans the entry
;
LD B,8 ; 8 character file name
PLOOP2: LD A,(HL) ; get a byte
CALL CTYPE ; print it
INC HL ; next character
DJNZ PLOOP2 ; do 8 characters
LD A,'.'
CALL CTYPE ; print the seperator
LD B,3 ; 3 character file name
PLOOP3: LD A,(HL) ; get a byte
CALL CTYPE ; print it
INC HL ; next character
DJNZ PLOOP3 ; do 3 characters
LD E,(HL) ; get the number of sectors into de
INC HL
LD D,(HL)
EX DE,HL ; put number into hl
CALL ADDTOT ; add to total sectors
LD B,3
PLOOP4: SRL H
RR L
DJNZ PLOOP4
INC HL ; round up to nearest k
CALL PNUMB1 ; print hl as 5-digit decimal
CALL ILPRT ; print the "s" in "sectors"
DEFB 'k',0
LD C,6 ; bdos direct function call
LD E,0FFH
CALL 5 ; get keyboard character
CP 3 ; control c?
JP Z,EXIT ; ...yes - abort
LD HL,(MAXNUM)
DEC HL
LD (MAXNUM),HL ; bump counter down
LD A,(COL) ; increment...
INC A ; ...column count
LD (COL),A
CP MAXCOL ; reached max column?
JR NZ,PLOOP5 ; not yet - back to caller
XOR A ; reached max column...
LD (COL),A ; ...set it to zero...
CALL CRLF ; ...and start a new line
JP PLOOP
PLOOP5: LD A,L
OR H
JP Z,PLOOP
CALL ILPRT
DEFB ' ',FENCE,' ',0
JP PLOOP
;
PLOOP6: LD HL,(SECTRS) ; get sector count
LD A,L
OR H ; test for no files
JR NZ,PLOO6A ; ...if there are any sectors in .lbr
CALL ILPRT
DEFB 'No file(s)',0
JP EXIT
;
PLOO6A: CALL ILPRT
DEFB 13,10,13,10,'This file contains ',0
LD HL,(MEMBRS)
CALL PNUMB0
CALL ILPRT
DEFB ' members in ',0
LD HL,(SECTRS)
CALL PNUMB0
CALL ILPRT
DEFB ' active sectors for a total of ',0
LD HL,(SECTRS)
LD B,3
PLOOP7: SRL H
RR L
DJNZ PLOOP7
INC HL
CALL PNUMB0
CALL ILPRT
DEFB 'k',13,10,0
JP EXIT
;
RDBLOK: LD DE,DBUF
LD C,26
CALL 5
LD DE,FCB1 ; point to our fcb
LD C,20
CALL 5
OR A
RET Z
CALL ILPRT
DEFB 13,10,'Premature eof in file',13,10,0
JP EXIT ; abort
;
ADDTOT: PUSH HL ; save sector count
EX DE,HL ; keep sector count in 'DE' for the add
LD HL,(SECTRS)
ADD HL,DE
LD (SECTRS),HL ; put number back
JR NC,ADDTO1 ; if no overflow
LD A,(SECTRS+2) ; get sectors msb
INC A ; + 1
LD (SECTRS+2),A ; put ot back
ADDTO1: POP HL ; restore sector count
RET ; return to caller
;
NOFILE: CALL ILPRT
DEFB CR,LF
DEFB 'No such file on disk',CR,LF,0
JP EXIT
;
EXIT:
STAKER: LD SP,STACK
RET
;
PFLNAM: LD HL,FCB1+1
LD B,8 ; 8 character file name
PFLNA1: LD A,(HL) ; get character
CP 020H ; space ?
CALL NZ,CTYPE ; no - print the character
INC HL ; next character
DJNZ PFLNA1 ; do 8 characters
LD A,'.'
CALL CTYPE
LD B,3 ; 3 character file type
PFLNA2: LD A,(HL) ; get character
CP 020H ; space ?
CALL NZ,CTYPE ; no - print the character
INC HL ; next character
DJNZ PFLNA2 ; do 3 characters
RET
;
; write a string of characters to the crt
;
ILPRT: EX (SP),HL ; save return address/get character pointer
ILPRT1: LD A,(HL) ; get a byte
OR A ; test it
JR Z,ILPRT2 ; null - end of string
CALL CTYPE ; else type the character
INC HL ; next character
JR ILPRT1 ; loop for more
ILPRT2: EX (SP),HL ; restore return address
RET ; return to caller
;
CTYPE: PUSH AF ; save all registers
PUSH BC
PUSH DE
PUSH HL
AND 07FH ; be sure its ascii
LD E,A ; into 'E'
LD C,6 ; cpm direct console function
CALL 5
POP HL ; restore all registers
POP DE
POP BC
POP AF
RET ; return to caller
;
CRLF: LD A,13
CALL CTYPE
LD A,10
JR CTYPE
;
PUTRG MACRO
PUSH BC ; save bc, de, hl
PUSH DE
PUSH HL
ENDM
GETRG MACRO
POP HL ; restore hl, de, bc
POP DE
POP BC
ENDM
;
PNUMB0:
PUSH AF ; save all regs
PUTRG
LD A,1 ; a=1
LD (LSFLG0),A ; turn on leading <sp>
LD (SPCFLG),A
JR PHDC
;
;
; print hl as decimal characters w/leading spaces in 5-char field
;
PNUMB1: PUSH AF ; save all regs
PUTRG
LD A,1 ; a=1
LD (LSFLG0),A ; turn on leading <sp>
LD A,0
LD (SPCFLG),A
;
PHDC: LD DE,1000 ; print 1000'S
CALL PHDC1
LD DE,100 ; print 100'S
CALL PHDC1
LD DE,10 ; print 10'S
CALL PHDC1
LD A,L ; print 1'S
ADD A,'0' ; convert to ascii
CALL CTYPE
GETRG ; restore all regs
POP AF
RET
;
LSFLG0: DEFS 1 ; leading <sp> flag
;
; divide hl by de and print quotient with leading <sp>s
;
PHDC1: LD C,0 ; set count
PHDC2: LD A,L ; sub e from l
SUB E
LD L,A ; result in l
LD A,H ; sub d from h w/borrow
SBC A,D
LD H,A ; result in h
JP C,PHDC3 ; done if carry set (further borrow)
INC C ; incr count
JP PHDC2
PHDC3: LD A,L ; add e to l
ADD A,E
LD L,A ; result in l
LD A,H ; add d to h w/carry
ADC A,D
LD H,A ; result in h
LD A,C ; get result
OR A ; check for zero
JP NZ,PHDC4
LD A,(LSFLG0) ; check for leading <sp>
OR A ; print value if not (a=0)
JP Z,PHDC4
LD A,(SPCFLG)
OR A
RET NZ
LD A,' ' ; print <sp>
CALL CTYPE
RET
PHDC4: XOR A ; turn off leading <sp>
LD (LSFLG0),A
LD A,C ; get value
ADD A,'0' ; convert to ascii
CALL CTYPE
RET
;
SPCFLG: DEFB 0
SECTRS: DEFB 0,0,0
MAXNUM: DEFW 0
MAXDIR: DEFW 0
NAMBUF: DEFW 0
MEMBRS: DEFW 0
DIRS: DEFB 0 ; # of dir sectors processed
DIRSIZ: DEFB 0 ; # of total dir sectors
COL: DEFB 0 ; column count
SUPSPC: DEFB 0
TBLOC: DEFW 0
COUNT: DEFW 0
SCOUNT: DEFW 0
GAP: DEFW 0
VARI: DEFW 0
VARJ: DEFW 0
VARJG: DEFW 0
FCB1: DEFS 36
DEFS 50 ; 25 level stack
STACK: DEFW 0 ; save cp/m stack pointer here
ORDER EQU $
;
END