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
/
BDOS
/
DOSPLSOR.ARK
/
INITDIR.MAC
< prev
next >
Wrap
Text File
|
1986-10-28
|
14KB
|
921 lines
; This program creates a directory structure suitable for
; time-stamping with DOS+. Any previous time-stamps are
; lost, and the directory is sorted.
;
; Usage:
; INITDIR d (to initialize drive d:)
; or
; INITDIR d X (to remove old time stamps)
;
; (If the disk is already time stamped INITDIR will abort unless
; the "x" parameter is supplied. Similarly, INITDIR will abort
; when too many directory entries are already used)
;
; It may be necessary to patch the "sec1st" value to 1 at location
; 0103h, if the bios system expects sectors from 1 up prior to
; sector translation.
;
; 1.0 86/10/28. Initial release. C.B. Falconer
;
ver equ 10
;
boot equ 0
bdos equ 5
;
cr equ 0dh
lf equ 0ah
;
; bdos calls
coute equ 2
putmsg equ 9
dosver equ 12
seldsk equ 14
galloc equ 27
getdpbp equ 31
offset equ 13; of "off" in dpblk
;
; offsets for bios entries (from COLD boot entry)
bdrvsel equ 001Bh
bsetrk equ 001Eh
bsetsec equ 0021h
bsetdma equ 0024h
bread equ 0027h
bwrite equ 002Ah
bsecxlt equ 0030h
;
tbuf equ 0080h; default DMA buffer & cmd line
;
vacant equ 00E5h; empty dir entries marked
timark equ 021h; marker for time-stamp entry
dentsiz equ 32; size of a directory entry (coded in)
;
jmp begin
;
sec1st: db 0; Patch if sectors do not
; start at zero (to secxlate)
begin: lxi sp,stack
lxi d,signon
call tstr
mvi c,dosver
call bdos; to get hl value
lxi d,badvermsg; DOS+ returns 23 up.
inr h
dcr h
jnz exeunt; maybe MPM?
cpi 20h
jc exeunt; maybe 1.4
cpi 30h
jnc exeunt; maybe 3.0
lxi h,tbuf
mov a,m
ora a
lxi d,help
jz exeunt; empty line
bgn1: inx h
mov a,m; skip blanks
ora a
jz exeunt; eol, empty line
cpi ' '
jz bgn1
ani 05fh; upshift
sui 'A'
cpi 16
jnc exeunt
sta drive
mov e,a
bgn2: inx h
mov a,m
ora a
jz bgn4; eol
cpi ' '
jnz bgn2; skip to next field
dcx h
bgn3: inx h
mov a,m; now skip blanks
ora a
jz bgn4
cpi ' '
jz bgn3
ani 05fh; upshift
sui 'X'
mvi a,0
jnz bgn4
mvi a,0ffh
bgn4: sta killmk; any non-zero does the kill
mvi a,seldsk
call dos; aborts on invalid drive
;
lxi d,loading
call tstr
mvi c,getdpbp
call bdos; Not dos, need HL
mov a,m
sta spt
inx h
inx h; +2
mov a,m
sta bsh
inx h
inx h
inx h; +5
mov e,m
inx h
mov d,m; get dsm
push d
inx h; +7
mov e,m
inx h
mov d,m; get drm
inx h
mov b,m; get al0
inx h; +10
mov c,m; get al1
inx h
inx h
inx h; +13, point to off
mov a,m
inx h
mov h,m
mov l,a
shld firstk; 1st storage track
xchg
inx h
shld dirmaxplus1
push h
call shlrt
call shlrt
shld dirsectors; := (dirmax+1)/4
pop h
pop d
;a=bsh, bc=diralloc bits, de=dsm, hl=dirmax+1
call setup; preserves af, hl:=dsm
inx h
shld dsmplus1
lda drive
mov c,a
mvi a,bdrvsel
call callbios
mov e,m
inx h
mov d,m
xchg
shld secxltptr
lhld dirsectors
mov b,h
mov c,l
lda sec1st
mov e,a
lhld firstk; 1st user track
shld track
lxi h,buffer
mvi d,bread
call rwdir; into buffer
jnz rdwrterror
lxi d,sortdirmsg
call tstr
;
call chkmk; look for old marks
call sort
call addstamps; add in time marker entries
;
lxi d,wrtdirmsg
call tstr
lhld dirsectors
mov b,h
mov c,l
lda sec1st
mov e,a
lhld firstk
shld track
lxi h,buffer
mvi d,bwrite
call rwdir; write dir. back
jnz rdwrterror
lxi d,statsmsg
call tstr
lhld dirmaxplus1
shld dircounter
mov e,l
mov d,h; * 3/4 for entries remaining
dad d
dad d; * 3
call shlrt
call shlrt; /4
mov a,l
ora a
lxi d,toomanymsg
jz exeunt
call tdhlzs
lxi d,entriesmsg
call tstr
lxi h,buffer
lxi d,0; entries vacant
mov b,d; entries used
mov c,e
;
L02BC: mov a,m; count entries used/vacant
cpi timark
jz L02C7
cpi vacant
jz L02C6
inx b
jmp L02C7
L02C6: inx d
L02C7: push d
lxi d,dentsiz
dad d
pop d
push h
lhld dircounter
dcx h
shld dircounter
mov a,l
ora h
pop h
jnz L02BC
push d
call tdbczs
lxi d,delentriesmsg
call tstr
pop h
call tdhlzs
lxi d,usrsactivemsg
call tstr
mvi e,0ffh
lhld dirmaxplus1
shld dircounter
lxi h,buffer
L02FA: mov a,m
cpi timark
jz L0314
push h
cpi vacant
jz L0312
cmp e
jz L0312
mov l,a
mvi h,0
call tdhlzs
mvi a,' '
call couta
L0312: pop h
mov e,m
L0314: push d
lxi d,dentsiz
dad d
push h
lhld dircounter
dcx h
shld dircounter
mov a,l
ora h
pop h
pop d
jnz L02FA
lhld dsmplus1
lda blksused
cma
mov e,a
mvi d,0ffh
inx d
xchg
dad d
push h
push d
mvi c,galloc
call bdos; get allocation map. Not DOS here
pop d
push h
call L0456
pop h
pop d
lxi b,0
L0346: push psw
push d
push h
inx b
ana m
jz L034F
dcx b
L034F: pop h
pop d
dcx d
mov a,d
ora e
jz L035E
pop psw
call rsha_cnt_in_hl
jmp L0346
L035E: pop psw
lda bsh
mov d,b
mov e,c
xchg
sui 3
jz L0382
L036A: dad h
push h
lhld dsmplus1
dad h
shld dsmplus1
pop h
dcr a
jnz L036A
;
L0382: xchg
lxi h,0
L0389: mov a,d
ora e
jz L0393
inx h
dcx d
jmp L0389
L0393: xchg
lhld dsmplus1
xchg
push h
mov a,e
sub l
mov e,a
mov a,d
sbb h
mov d,a
lda kbused
cma
mov l,a
mvi h,0ffh
inx h
dad d
lxi d,spaceusedmsg
call tstr
push h; save used
call tdhlzs
mvi a,'K'
call couta
lxi d,spacefreemsg
call tstr
pop d; used
pop h; free
push d; save used
call tdhlzs
mvi a,'K'
call couta
pop h; bc := used; hl := used
mov b,h
mov c,l
mvi e,0; extend used
call lshftehl; multiply by 100
inx h
call ehlplusbc
call lshftehl
call lshftehl
call lshftehl
call ehlplusbc
call lshftehl
call lshftehl
push h
lhld dsmplus1
mov b,h
mov c,l
pop h
mov a,c; bc := -dsmplus1
cma
mov c,a
mov a,b
cma
mov b,a
inx b
mvi d,-1
L03FD: inr d; d := ehl/bc
dad b
mov a,e
aci 0ffh
mov e,a
jc L03FD
mov l,d
mvi h,0
lxi d,pctfullmsg
call tstr
call tdhlzs
lxi d,percent
; " "
exeunt: call tstr
jmp boot
;
; console output from a
; a,f
couta: push d
mov e,a
mvi a,coute
call dos
pop d
ret
;
; string from de^ to console
tstr: mvi a,putmsg
; " "
; dos call (a), preserving regs
; a,f
dos: push h
push d
push b
mov c,a
call bdos
pop b
pop d
pop h
ret
;
lshftehl:
dad h
mov a,e
ral
mov e,a
ret
;
ehlplusbc:
dad b
rnc
inr e
ret
;
setup:
;a=bsh, bc=dirallocbits, de=dsm, hl=dirmax+1
push psw
mov h,b
mov l,c
mvi b,16
mvi c,0
setup1: dad h
jnc setup2
inr c
setup2: dcr b
jnz setup1
mov a,c
sta blksused
xchg
pop psw
push psw
push h
sui 3
mov c,a
lda blksused
mov b,a
jz setup4
setup3: add a
mov b,a
dcr c
jnz setup3
mov a,b
setup4: sta kbused
pop h
pop psw
ret
L0456: lda blksused
mov c,a
mvi b,080h
L045C: mov a,b
call rsha_cnt_in_hl
mov b,a
dcr c
jnz L045C
mov a,b
ret
rsha_cnt_in_hl:
ora a
rar
rnc
rar
inx h
ret
;
; read or write directory (complete). NZ for error.
; bc=sectors to rd/wrt, d=r/w opn, e=1st sector, hl=buff ptr
; a,f,b,c,d,e,h,l
rwdir: push b
push d
mov b,h
mov c,l
push h; stk = buff, sect, ct
lhld secxltptr;
xchg; l=logical sector
mvi h,0
mvi a,bsecxlt
call callbioshl; hl=physical sector
mvi a,bsetsec
call callbioshl; set sector
lhld track
mvi a,bsetrk
call callbioshl; set track
pop b; buff address
lxi h,080h; advance for next rd/wrt if any
dad b
push h
mvi a,bsetdma; setdma to bc, not advanced
call callbios
pop h
pop d
inr e; advance sector for next time
lda spt
cmp e
jnz rwdir1; more on this track
push h
lhld track; advance track for next time
inx h
shld track
pop h
lda sec1st; and reset sector
mov e,a
rwdir1: pop b
push b
dcx b
mov a,b
ora c; check for writing last sector
push d; save advanced sect/opn
push h; save advanced address
mov a,d; read or write
lxi b,0; for writes
jnz rwdir2; not last write
inx b; make it a directory write (flush)
rwdir2: call callbios; DO IT
pop h
pop d
pop b
ora a
rnz; i/o error occured
dcx b
mov a,b
ora c
jnz rwdir; more to read/write
ret
;
; call bios with argument hl, operation (a)
; a,f,b,c,d,e,h,l
callbioshl:
mov b,h
mov c,l
" "
; 0th is cold boot entry. 0,3,.. in (a)
; a,f,b,c,d,e,h,l
callbios:
push h
push d
lhld boot+1
dcx h
dcx h
dcx h
mov e,a
mvi d,0
dad d
pop d
xthl
ret
;
rdwrterror:
lxi d,rdwrterrmsg
mvi c,putmsg
call bdos
jmp exeunt
;
; write bc in decimal, zero suppress
; a,f,h,l
tdbczs: mov h,b
mov l,c
; " "
; write hl in decimal, zero suppress
; a,f
tdhlzs: push h
call dten
push psw
mov a,h
ora l
cnz tdhlzs; recursive, next digit
pop psw
pop h
adi '0'
call couta
ret
;
; divide hl by 10, remainder to a
; a,f,h,l
dten: push b
lxi b,0f00ah; c=divisor=10; b=iter.cnt=-16
xra a; clear
dten1: dad h
ral; shift off into a
cmp c
jc dten2; no bit
sub c; bit=1
inx h
dten2: inr b
jm dten1; not done
pop b
ret
;
sort: lhld dirmaxplus1
shld window
sort1: lhld window
call shlrt
shld window; window := window DIV 2
ora h
rz
xchg
lhld dirmaxplus1
dcx h
mov a,l
sub e
mov l,a
mov a,h
sbb d
mov h,a
shld top; := n-1 - window
lxi h,0
shld bottom
sort2: shld current
sort3: xchg
lhld window
dad d; window+current
call compare; de=current, hl=window+current
jnc sort4
call trade
lhld window
xchg
lhld current
mov a,l
sub e
mov l,a
mov a,h
sbb d
mov h,a
shld current; := current - window
jm sort4
ora l
jnz sort3
sort4: lhld bottom
inx h
shld bottom
xchg
lhld top
call cmphlde
xchg
jnc sort2
jmp sort1
;
cmphlde:
mov a,h
cmp d
rnz
mov a,l
cmp e
ret
;
; de=current, hl=window+current
; a,f,b,c,d,e,h,l
compare:
dad h
dad h
dad h
dad h
dad h
lxi b,buffer
dad b
xchg
dad h
dad h
dad h
dad h
dad h
dad b
mvi b,15
push d
push h
cp1: ldax d
cmp m
jnz cp2
inx h
inx d
dcr b
jnz cp1
cp2: pop h; rightentry
pop d; leftentry
ret; for possible trade
trade: mvi c,dentsiz
trade1: mov b,m
ldax d
mov m,a
mov a,b
stax d
inx d
inx h
dcr c
jnz trade1
ret
;
; right shift hl one place
shlrt: xra a
mov a,h
rar
mov h,a
mov a,l
rar
mov l,a
ret
;
; Add time-stamping entries to directory image. Every fourth entry
; becomes 021h, 0, .. 0 (32 total bytes).
addstamps:
lhld dirmaxplus1
mov c,l
mov b,h
lxi h,buffer
; Move entries up and inject time stamp operation.
addst1: dcx b
dcx b
dcx b; 3 entries
lxi d,3 * dentsiz
dad d; point to entry to inject
; now move (bc) entries up by 32 bytes
xchg
lxi h,dentsiz
dad d
xchg; hl = source, de = destination
dcx b; move 1 less entry
mov a,b
ora c
mov a,m; in case last entry
cnz moveup; leaves hl pointing to time entry
cpi vacant
jnz toomany; discarding real entry, abort
call inject; a timestamp entry, blank
mov a,b
ora c
jnz addst1; do next entry
ret
;
; inject timestamp entry at hl^. Advance hl past entry
inject: push b
mvi b,31
mvi m,timark
inj1: inx h
mvi m,0
dcr b
jnz inj1
inx h
pop b
ret
;
; moveup hl^ to de^ for bc 32 byte entries
moveup: push h
push d
push b
push h
mov l,c
mov h,b
dad h
dad h
dad h
dad h
dad h; *32 = dentsiz
mov c,l
mov b,h; bc is bytes to move
xchg
dad b; top + 1 destination
xchg
pop h
dad b; top + 1 source
mov a,m; keep the discarded 1st byte
push psw
movup1: dcx h
dcx d
mov a,m
stax d
dcx b
mov a,b
ora c
jnz movup1
pop psw; the discarded 1st byte
pop b
pop d
pop h
ret
;
; check bc entries from hl^ up for existing time marks
chkmk: lhld dirmaxplus1
mov c,l
mov b,h
lxi h,buffer
chkmk1: mov a,m
cpi timark
jnz chkmk4; not a mark
lda killmk
ora a
lxi d,oldmkmsg
jz exeunt
mvi m,vacant; erase this entry
inx h
mvi m,vacant; so sorts to high end
dcx h
chkmk4: lxi d,dentsiz
dad d
dcx b
mov a,b
ora c
jnz chkmk1; more
ret
;
; abort, too many directory entries to add timestamps
toomany:
lxi d,toomanymsg
jmp exeunt
;
help:
db 'usage: INITDIR d: [x:]'
db cr,lf,
db '(d is drive to sort/timestamp, '
db 'optional x: removes old timestamps)$'
badvermsg:
db cr,lf
db 'Run under DOS+ or CPM2.2 only$'
toomanymsg:
db cr,lf
db 'Too many files to add time-stamps, aborted$'
oldmkmsg:
db cr,lf
db 'Time stamps already present, aborted$'
rdwrterrmsg:
db cr,lf
db 'Read/Write Error!$'
loading:
db cr,lf
db 'Loading directory.$'
sortdirmsg:
db cr,lf
db 'Sorting directory.$'
wrtdirmsg:
db cr,lf
db 'Writing directory.$'
statsmsg:
db cr,lf,cr,lf
db ' Disk Statistics'
db cr,lf
db 'Possible entries : $'
entriesmsg:
db cr,lf
db 'Active entries : $'
delentriesmsg:
db cr,lf
db 'Deleted entries : $'
usrsactivemsg:
db cr,lf
db 'User area active : $'
spaceusedmsg:
db cr,lf
db 'Disk space used : $'
spacefreemsg:
db cr,lf
db 'Disk space free : $'
pctfullmsg:
db cr,lf
db 'Percent full : $'
percent:
db '%$'
signon:
db cr,lf
db 'INITDIR (DOS+ time-stamps) Ver. '
db ver / 10 + '0', '.', ver mod 10 + '0'
db ' (c) 1986 C.B. Falconer'
db cr,lf
db '$'
;
killmk: ds 1; flag remove old stamps
;
drive: ds 1
secxltptr: ds 2
firstk: ds 2; 1st storage track
spt: ds 2; sectors per track
dirmaxplus1: ds 2; dir entries available
dirsectors: ds 2; sectors in whole directory
;
; sort vars
top: ds 2
bottom: ds 2
window: ds 2
current: ds 2
;
track: ds 2
dircounter: ds 2
bsh: ds 1
blksused: ds 1
kbused: ds 1
dsmplus1: ds 2
ds 100
stack:
buffer: ds 0; the rest
end
╗╣