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
/
ZSYS
/
SIMTEL20
/
ZCPR3
/
XD.MAC
< prev
next >
Wrap
Text File
|
2000-06-30
|
18KB
|
856 lines
;
; PROGRAM: XD III
; AUTHOR: RICHARD CONN
; VERSION: 1.2
; DATE: 8 Apr 84
; PREVIOUS VERSIONS: 1.1 (14 Jan 84), 1.0 (19 Nov 83)
; DERIVATION: XDIR III, Version 1.6 (19 Nov 83)
;
vers equ 12
z3env SET 0f400h
;
; XD III -- Simple Extended Disk Directory Program
; ZCPR3 Only
;
; XD III produces a formatted, alphabetized listing of the contents
; of the disk directory of the implied (current logged-in) or specified disk.
;
; XD III is invoked by a command line of the following form --
;
; XD dir:filename.typ ooo...
; or
;
; XD /oooo...
;
; where:
; dir is an optional directory name or a disk/user specification (du)
; if dir is omitted, XD III defaults to the current disk/user
; filename.typ is an ambiguous file name and type (* and ? may be used)
; o are option letters as follows:
; Aa - Set the attributes of the files to be displayed;
; a=S for System Files, a=N for Non-System Files
; a=A for All Files (System and Non-System)
; Oo - Set Output Parameters;
; o=A to Toggle File Attributes, o=F to Form Feed at end
; o=G to Toggle Grouping, o=H to Toggle Hor/Vert
; P - Print display as well as show it on the screen
; PF - Same as POF
; Options may be combined as desired; note that AA is the same as AS and AN,
; but AS by itself negates AN and vice-versa, with AN taking precident
;
;
; CP/M Equates
;
base equ 0
wboot equ base
bdose equ base+5
fcb equ base+5ch
buff equ base+80h
cr equ 0dh
ff equ 0ch
lf equ 0ah
esize equ 16 ; size of directory entries
optch equ '/' ; option char
maxent equ 60 ; maximum number of entries/screen
;
; External Routines
;
ext bdos ; BDOS
ext z3init ; init ZCPR3 environment descriptor ptr
ext z3log ; log into ZCPR3 DU/DIR
ext dirqs ; quick directory load with sizes
ext dfree ; free space computer
ext dparam ; disk parameter extractor
ext fsize ; compute file size
ext retud ; get current user and disk
ext print ; print routines
ext pstr
ext lcrlf ; CRLF to printer
ext caps ; capitalize char
ext cin ; console in char
ext lout ; print char
ext cout ; console out char
ext crlf ; new line
ext fillb ; memory fill
ext moveb ; memory move
ext codend ; beginning of buffer area
ext sctlfl,sout,scrlf,sprint,spstr,shldc,sadc ; S-output
ext dutdir ; DU to DIR form
;
; Environment Definition
;
if z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
jmp start
db 'Z3ENV' ;This is a ZCPR3 Utility
db 1 ;External Environment Descriptor
z3eadr:
dw z3env
start:
lhld z3eadr ;pt to ZCPR3 environment
;
else
;
; Internal ZCPR3 Environment Descriptor
;
MACLIB Z3BASE.LIB
MACLIB SYSENV.LIB
z3eadr:
jmp start
SYSENV
start:
lxi h,z3eadr ;pt to ZCPR3 environment
endif
;
; Start of Program -- Initialize ZCPR3 Environment
;
call z3init ;initialize the ZCPR3 Env
;
; Branch to Start of Program
;
jmp start0
;
; Other Buffers (Set by GENINS)
;
igrp: db 0ffh ; Group by file type and name
ifmt: db 0 ; vertical format
iatt: db 10000000b ; Non-System files only
irs: db 0ffh ; enable attribute display (0=no)
iff: db 0 ; enable form feed at end (0=no)
;
; Command Line Option Table
;
optab:
db 'A' ; Attribute Selection
dw opta
db 'O' ; Output Control
dw opto
db 'P' ; Print Control
dw optp
db 0
;
; **** Start of XD III ****
;
start0:
; Save stack ptr for return later
lxi h,0 ; get stack
dad sp
shld stack ; save stack ptr for return
call codend ; determine free space (CODEND also pts to Command
; Line Save Area)
lxi d,100h ; block size to save
dad d
dad d ; allow for 256-byte stack
shld buffer ; start of free buffer area
sphl ; set stack ptr
; Save command line in CMDLNE buffer
call codend ; pt to command line buffer
xchg ; ... in DE
lxi h,buff+1 ; copy input line into command line buffer
start1:
mov a,m ; get byte
stax d ; put byte
inx h ; pt to next
inx d
ora a ; end of line?
jnz start1
; log into DU or DIR
lxi d,fcb ; extract file name into fcb, and get user and disk
call z3log ; ZCPR3 command line interpretation
; Get and save current user number
noext:
call retud ; get current user and disk
mov a,c ; get user into A
sta aflg ; current user number
; Set flag values
lda irs ; get RS display option
sta rsflg ; set RS display option
lda iff ; get form feed option
sta ffflg ; set form feed option
lda igrp ; set grouping (file name/type or type/name)
sta gflg
lda ifmt ; set listing format (vertical or horizontal, 0=vert)
sta hflg
lda iatt ; set file attributes
mov c,a ; save in c
lda aflg ; get current user number
ora c ; mask in file attributes
sta aflg ; save flag
xra a ; A=0
sta pflg ; set no printer output
inr a ; A=1 for console only
sta sctlfl ; set switched output flag
; Assume wild file name
lxi h,fcb+1 ; store '?' chars
mvi b,11 ; 11 chars
mov a,m ; check for entry specified
cpi ' ' ; test for space (means no entry)
mvi a,'?' ; prep for '?' fill
cz fillb
mov a,m ; check for option caught
cpi optch ; test for option flag
mvi a,'?' ; prep for '?' fill
cz fillb
; Scan command line for options
call codend ; pt to first char
call sblank ; skip over blanks
ora a ; end of line?
jz xdir ; begin main processing
inx h ; prep for invalid option
cpi optch ; option?
jz opt ; process options
dcx h ; ok to process for dir:filename.typ form
;
; Skip over characters of file name
;
skipo1:
mov a,m ; get char
inx h ; pt to next
cpi ' '
jz skipo2
ora a
jnz skipo1
jmp xdir ; run XDIR if no options follow
;
; Scan complete -- look for possible following option char
;
skipo2:
call sblank ; skip over blanks
mov a,m ; option char follows?
cpi optch
jnz opt
inx h ; skip over option char
;
; Look for options -- main loop; HL pts to next char
;
opt:
mov a,m ; get option char
inx h ; pt to next
ora a ; end of line?
jz xdir ; begin main processing
cpi ' ' ; skip over spaces
jz opt
cpi optch ; option char?
jz opterr ; loop back if so
lxi d,optab ; pt to option table
mov b,a ; option char in b
;
; Scan option table
;
opt1:
ldax d ; get option table char
ora a ; end of table?
jz opterr ; invalid option error
cmp b ; compare to passed option
jz opt2 ; process if match
inx d ; skip address
inx d
inx d ; pt to next opt char
jmp opt1
;
; Process option found
;
opt2:
inx d ; pt to low-order address
ldax d ; get it
mov c,a ; low in C
inx d ; pt to high-order address
ldax d ; get it
mov b,a ; high in B
push b ; BC on stack
ret ; Process option routine
;
; Option A -- File Attributes
;
opta:
mov a,m ; get next option letter
cpi 'N' ; Non-System files?
jz optan
cpi 'S' ; System files?
jz optas
cpi 'A' ; All files?
jnz opterr ; error if not
;
; Option AA -- All Files
;
optaa:
mvi c,11000000b ; System and Non-system
optaret:
lda aflg ; get flag
ani 3fh ; leave in user selection
ora c ; mask in sys/non-sys
sta aflg ; restore flag
inx h ; pt to next
jmp opt
;
; Option AS -- System Files
;
optas:
mvi c,01000000b ; System Only
jmp optaret
;
; Option AN -- Non-System Files
;
optan:
mvi c,10000000b ; Non-system Only
jmp optaret
;
; Option P -- enable it; Printer output
;
optp:
mvi a,0ffh ; ON
sta pflg
sta sctlfl ; set S-output control
mov a,m ; get possible 2nd letter
cpi 'F' ; set form feed if F
jnz opt ; process as next option letter if not F
inx h ; pt to next
jmp optof
;
; Option O -- control Output parameters
;
opto:
mov a,m ; get 2nd letter
inx h ; pt to next
cpi 'A' ; attributes?
jz optoa
cpi 'F' ; form feed?
jz optof
cpi 'G' ; grouping?
jz optog
cpi 'H' ; horizontal/vertical?
jz optoh
dcx h ; adjust back
jmp opterr
;
; Toggle File Attributes Flag
;
optoa:
lda rsflg ; flip flag
cma
sta rsflg
jmp opt
;
; Toggle Form Feed Flag
;
optof:
lda ffflg ; flip flag
cma
sta ffflg
jmp opt
;
; Toggle Grouping
;
optog:
lda gflg ; flip flag
cma
sta gflg ; 0=file name and type
jmp opt
;
; Toggle Horizontal/Vertical Listing
;
optoh:
lda hflg ; flip flag
cma
sta hflg ; 0=vertical
jmp opt
;
; Option error message
;
opterr:
mvi a,1 ; set console only
sta sctlfl ; set output control flag
call banner ; print banner
call print
db cr,lf,'Syntax:'
db cr,lf,' XD dir:filename.typ ooo...'
db cr,lf,'or XD /oooo...'
db cr,lf,'Option letters are:'
db cr,lf,' Aa - Set and Display of file attributes'
db cr,lf,' a=S for System, a=N for Non-System'
db cr,lf,' a=A for All Files (System and Non-System)'
db cr,lf,' Oo - Toggle Output Control Options'
db cr,lf,' o=A for File Attributes, o=F for Form Feed'
db cr,lf,' o=G for Grouping, o=H for Horiz/Vert Format'
db cr,lf,' P - Send display to printer'
db cr,lf,' PF - Same as POF'
db 0
; Return to CP/M
return:
lhld stack ; get old stack ptr
sphl
ret ; return to CP/M
; Memory Overflow Error
memerr:
call sprint
db 'TPA Error',0
jmp return
; Print banner of XD III
banner:
call sprint
db 'XD III Version '
db vers/10+'0','.',(vers mod 10)+'0',0
ret
;
; Begin XD III processing
;
xdir:
lxi d,fcb ; pt to FCB
xra a
stax d ; select current disk
; Check for Print Option and Print New Line if so
xdirst:
lda pflg ; printer output?
ora a ; 0ffH=yes
cnz lcrlf ; new line
; Get Files from Disk
push d ; save ptr to FCB
call dparam ; get disk parameters for DFREE
call dfree ; compute amount of free space on disk
xchg ; amount in hl
shld freesiz ; save free space count
pop d ; get regs
lhld buffer ; pt to free space
lda gflg ; get grouping flag
ani 20h ; mask for sort bit (0=name/type)
mov c,a
lda aflg ; get attributes flag
ora c ; mask in grouping bit
call dirqs ; quick directory load with file sizes
jz memerr ; memory overflow error?
shld firstf ; save ptr to first file
mov h,b ; HL=file count
mov l,c
shld fcount ; save file count
shld countf ; save file down count
lxi h,0 ; set file size counter
shld totsiz ; save counter
lda pflg ; set temp flag
sta pflgt
;
; Main Directory Print Routine -- This routine displays the directory to
; the console, printer, or disk as desired
;
; Print header lines and one screen of entries
xdir2:
lda pflg ; save printer output flag
sta pflgs
lda pflgt ; use temp flag
sta pflg
xra a ; A=0
sta pflgt ; clear temp flag
; Print: Main Banner
call banner ; print banner
; Check for any files
lhld countf ; get file down count
mov a,h ; any files?
ora l
jnz xdir6
call sprint ; print everywhere
db cr,lf,'No files selected',0
jmp xdir10
;
; This is the main looping entry point for each screen display
;
xdir6:
;
; This is the header which is printed if the files in only one user area are
; displayed
;
call scrlf ; specific user selected
call hdr2
lda rsflg
ora a ; Z=no
cnz sp0
call sp2
call hdr2
lda rsflg
ora a ; Z=no
cnz sp0
call sp2
call hdr2
lda rsflg
ora a
cnz sp0
call scrlf
call hdr1
lda rsflg
ora a
cnz sp1
call sp2
call hdr1
lda rsflg
ora a
cnz sp1
call sp2
call hdr1
lda rsflg
ora a
cnz sp1
jmp xdir6b
sp0:
call sprint
db ' RS',0
ret
sp1:
call sprint
db ' --',0
ret
sp2:
call sprint
db ' ',0
ret
hdr1:
call sprint
db '-------- --- ------',0
ret
hdr2:
call sprint
db 'Filename.Typ Size K',0
ret
;
; Prepare Columnar Output
;
xdir6b:
lda pflgs ; restore print flag
sta pflg
lhld countf ; get file count down
lxi d,maxent ; assume maxent entries to print
mov a,h ; within range?
ora a ; outside of range if not
jnz xdir7 ; subtract entries to print from total entries
mov a,l ; within range?
cpi maxent ; less than maxent entries left?
jnc xdir7 ; subtract entries to print from total entries
mov d,h ; DE=HL=number of entries to print
mov e,l
xdir7:
mov a,l ; subtract entries to print (DE) from total (HL)
sub e
mov l,a
mov a,h
sbb d
mov h,a ; HL=result
shld countf ; save new down count
mov b,h ; BC=count
mov c,l
lhld firstf ; pt to first file
;
; At this point, BC=number of remaining entries, DE=number of entries to
; print, and HL pts to first entry to print
;
shld ptr1 ; save ptr to 1st entry
lda hflg ; horizontal listing?
ora a ; 0ffh = yes
jnz xdir7c ; don't worry about columns if horizontal
push d ; save count
call divde3 ; divide DE by 3, result*esize in BC, remainder in A
lxi d,esize ; DE=ESIZE (size of entry)
dad b ; add BC as a minimum
ora a ; any remainder?
jz xdir7a ; skip if none
dad d ; add in ESIZE for additional length of 1st col
xdir7a:
shld ptr2 ; save ptr to col 2
dad b ; add BC as a minimum
cpi 2 ; if remainder 2, add ESIZE for additional
jc xdir7b
dad d ; add in ESIZE
xdir7b:
shld ptr3 ; save ptr to col 3
pop d ; get count in de
;
; Main entry print routine
;
xdir7c:
mvi d,1 ; set 3's counter
xdir8:
lhld ptr1 ; pt to first entry
call prentry ; print entry
shld ptr1 ; put ptr
lda hflg ; horizontal?
ora a ; 0ffh = yes
jnz xdir9
dcr e ; count down
jz xdir10
lhld ptr2 ; get ptr
call prentsp ; print entry with 2 leading spaces
shld ptr2 ; put ptr
dcr e ; count down
jz xdir10
lhld ptr3 ; get ptr
call prentsp ; print entry with 2 leading spaces
shld ptr3 ; put ptr
xdir9:
dcr e ; count down
jnz xdir8 ; continue if not zero
shld firstf ; save ptr to first of next set of entries to print
lhld countf ; get count of remaining entries
;
; At this point, HL=number of entries left
;
mov a,h ; anything left?
ora l
jz xdir10
lda pflg ; printer output?
ora a ; 0=no
jnz xdir6
call print ; screen break
db cr,lf,' --> Screen Break -- Strike any char <-- ',0
call cin ; get response
cpi 3 ; abort?
jz return
jmp xdir6 ; new screen display
;
; Print end statistics and exit
;
xdir10:
;
; Print DU
;
call sprint ; print everywhere
db cr,lf,' ',0
call retud ; get current disk
mov a,b ; ... in A
adi 'A' ; convert to ASCII
call sout ; print everywhere
mov a,c ; user in A
call sadc ; get number
call sprint
db ': ',0
call dutdir ; convert to DIR form
jz xdir11
;
; Print DIR Name
;
mvi b,8 ; output name
dirout:
mov a,m ; get char
cpi ' ' ; don't print spaces
cnz sout
inx h ; pt to next
dcr b ; count down
jnz dirout
;
; Print Selected File Statistics
;
xdir11:
call sprint
db ' --',0
lhld fcount ; print file count
call shldc ; print it everywhere
call sprint
db ' Files Using ',0
lhld totsiz ; get total of file sizes
call shldc ; print it everywhere
call sprint
db 'K',0
;
; Print Space Remaining on Disk
; Entry Point if No Files Found
;
call sprint
db ' (',0
lhld freesiz ; get amount of free space
call shldc ; print it everywhere
call sprint
db 'K Left)',0
lda pflg ; new line if printer output
ora a
jz return
call scrlf ; new line for printer
lda pflg ; print output
mov b,a
lda ffflg ; form feed
ana b ; if print and form feed ... NZ is set
mvi a,ff ; form feed char
cnz lout ; form feed to printer
jmp return
;
; General Utility Routines
;
;
; Print disk entry for normal directory display functions
;
prentsp:
call sp2 ; print entry with 2 leading spaces
prentry:
dcr d ; count <CRLF> counter
jnz prent1
mvi d,3 ; reset count
call scrlf
prent1:
shld entptr ; save entry ptr
inx h ; pt to first char of file name
mvi b,8 ; print 8 chars
call prch
mvi a,'.' ; print dot
call sout
push h ; save RS ptr
mvi b,3 ; print 3 chars
call prch
push d ; save de
lhld entptr ; pt to entry
call sp2 ; skip 2 spaces
call fsize ; compute file size
lhld totsiz ; get total file size counter
dad d ; add in new file
shld totsiz ; save new total file size counter
xchg ; get file size into HL
call shldc ; print HL value
pop d ; get de
pop h ; pt to RS
lda rsflg ; print RS fields?
ora a ; Z=no
jz pren2a
mvi a,' ' ; print 1 space
call sout
mvi b,'R' ; letter
call prletx ; print R if bit set
inx h
mvi b,'S' ; letter
call prletx ; print S if bit set
dcx h ; ... for following inx h
pren2a:
inx h ; point correctly
prent3:
lxi b,6 ; pt to next entry
dad b
ret
;
; Print B chars pted to by HL
;
prch:
mov a,m ; get char
inx h ; pt to next
ani 7fh ; mask out msb
cpi ' ' ; within range?
jnc prch1 ; print special char if not valid char
mvi a,'?' ; print ? if not valid char
prch1:
call sout ; print it
dcr b ; count down
jnz prch
ret
;
; Extended Print Routines
;
prletx:
mov a,m ; get byte
ani 80h ; look at msb
jz prlets
mov a,b ; get letter
jmp sout
prlets:
mvi a,' ' ; print <sp>
jmp sout
;
; Divide DE by 3; return with BC=result*esize, a=remainder
;
divde3:
push d ; save de, hl
push h
mvi d,0 ; make sure D=0
mov a,e ; value in A
divd31:
sui 3 ; subtract 3
jc divd32
jz divd33
inr d ; add 1 to result
jmp divd31
divd32:
adi 3 ; add back in
jmp divd34
divd33:
inr d ; add 1 for even division
divd34:
sta rem ; save remainder
lxi b,esize
lxi h,0
divd35:
mov a,d ; done?
ora a ; 0=yes
jz divd36
dcr d
dad b ; add in another ESIZE
jmp divd35
divd36:
mov b,h ; BC is result
mov c,l
lda rem ; A is remainder
pop h ; restore regs
pop d
ret
;
; Skip blanks
;
sblank:
mov a,m ; pt to char
cpi ' ' ; blank?
rnz
inx h ; pt to next
jmp sblank
;
; Buffers
;
aflg: ds 1 ; attibute flag
gflg: ds 1 ; 0=group by name/type
hflg: ds 1 ; 0=vertical list
pflg: ds 1 ; printer output on flag
crcnt: ds 1 ; entry counter
fmark: ds 1 ; first file marker
pflgt: ds 1
pflgs: ds 1
rsflg: ds 1 ; RS Display Flag
ffflg: ds 1 ; form feed flag
rem: ds 1 ; remainder buffer
firstf: ds 2 ; ptr to first file of group to print
fcount: ds 2 ; count of files
countf: ds 2 ; down count of files
freesiz:
ds 2 ; amount of free space on disk
totsiz:
ds 2 ; total size of all files
ptr1: ds 2 ; col output ptrs
ptr2: ds 2
ptr3: ds 2
entptr: ds 2 ; current entry ptr
buffer: ds 2 ; pointer to free area
stack: ds 2 ; stack ptr
end