home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
utils
/
dskutl
/
diskstat.mac
< prev
next >
Wrap
Text File
|
1994-07-13
|
47KB
|
2,433 lines
.z80
title DISKSTAT Disk statistics
name ('DISKST')
;------------------------------------------------------------------
; Utility to display disc characteristics and file allocation
;
; Copyright 1983 D. Powys-Lybbe
; Author: D. Powys-Lybbe, MML Systems Ltd., London
; Date: 20th June 1983
;
;------------------------------------------------------------------
; Revisions
; =========
;
;------------------------------------------------------------------
;------------------------------------------------------------------------
page
public def.dsk,dpb,dph2,dph3,dpb.ptr,dph.ptr,vers,vers.rel,vers.os
public savesp
public BADSEL,selmsg,badvers,vermsg,BIOS,badbios,jmpmsg
public BIOSPB,BIOS.FUNC,BIOS.AREG,BIOS.BCREG,BIOS.DEREG,BIOS.HLREG
public waitcr,waitbuff,waitlen,fetchdp
public clearscrn,csnmsg,screen1,s1msg,s1dsk
public option,optquit,optmsg,optbuf,optlen,optchr
public makehex,wrdhex,dblhex,bythex,nblhex,testhex,nexthex
public hexchr,hextxt
public makedec,dec2,errdec,gigdec,megdec,wrddec,bytdec,txtdec,zrobcd
public tobcd,bcd,testdec,nextdec,decchr,dectxt
public makemax,makem1,makem2,makem3,makem4,makem5,makem6,makem8
public makem7,makem9,make01,make02,make03,make04,makem0
public makedir,dirdb,dbsize,maked0,maked1,maked2,maked3,maked4
public makedat,maked5,maked6
public maketot,maked7,maked8
public mmegx8,mmegx4,mmegx2,mgigx8,mgigx4,mgigx2,mgigx128
public showblk,posn,sdbmsg,sdbdsk,sdbhex,sdbdec,sdbmax
public sdbdir,sdbdat,sdbtot
public showhdr
public showalv,salmsg,saldsk
public showfil,sflmsg,sfldsk
public showdir,sdrmsg,sdrdsk
public goodvers,useccp,main,task1,table1,return
;------------------------------------------------------------------------
page
; ===============
; DISC DATA AREAS
; ===============
;--------------------------------------------------------------
;
; CP/M disc parameters
;
;--------------------------------------------------------------
dseg
def.dsk: db 0 ; Selected disc
dpb: ; Drive disk parameter block
dpb.spt: ds 2
dpb.bsh: ds 1
dpb.blm: ds 1
dpb.exm: ds 1
dpb.dsm: ds 2
dpb.drm: ds 2
dpb.al0: ds 1
dpb.al1: ds 1
dpb.cks: ds 2
dpb.off: ds 2
len.dpb2 equ $-dpb ; length of CP/M 2 dpb
dpb.psh: ds 1
dpb.phm: ds 1
len.dpb3 equ $-dpb ; length of CP/M + dpb
dph2: ; CP/M 2 disk parameter header
dph2.xlt: ds 2
dph2.zro: ds 6
dph2.dir: ds 2
dph2.dpb: ds 2
dph2.csv: ds 2
dph2.alv: ds 2
len.dph2 equ $-dph2 ; length of CP/M 2 dph
dph3: ; CP/M + disk parameter header
dph3.xlt: ds 2
dph3.zro: ds 9
dph3.mf: ds 1
dph3.dpb: ds 2
dph3.csv: ds 2
dph3.alv: ds 2
dph3.dir: ds 2
dph3.dat: ds 2
dph3.hsh: ds 2
dph3.bnk: ds 1
len.dph3 equ $-dph3 ; length of CP/M + dph
dpb.ptr: dw 0 ; address of dpb
dph.ptr: dw 0 ; address of dph
vers: ; O.S. Version number
vers.rel: ds 1 ; O.S. Version/Release number
vers.os: ds 1 ; O.S. number
posn: dw 0 ; pointer to text string
; ------;
; stack ;
; ------;
ds 64 ; dont know how much stack BIOS requires
savesp: dw 0
; ----------------;
; address equates ;
; ----------------;
bdos equ 5 ; BDOS entry point
deffcb equ 5ch ; CCP puts default FCB here
defdma equ 80h ; CCP sets default DMA here
; -----------------;
; constant equates ;
; -----------------;
bs equ 08h ; <BACK SPACE>
cr equ 0dh ; <RETURN>
lf equ 0ah ; <LINE FEED>
jump equ 0c3h ; JP instruction
cseg
;-------------------------------------------------------------------------;
page
;-------;
; start ;
;-------;
cseg
ld c,12 ; BDOS: RETURN VERSION NUMBER
call bdos
ld (vers),hl
ld a,h
cp 00h ; check for CP/M
jp nz,badvers
;
ld a,l
cp 22h
jp z,goodvers
;
ld a,l
cp 31h
jp z,goodvers
page
; ================= ;
; various utilities ;
; ================= ;
; -------------- ;
; Error routines ;
; -------------- ;
BADSEL:
ld de,selmsg
ld c,9 ;BDOS: PRINT STRING
call bdos
ld c,0 ;BDOS: SYSTEM RESET
jp bdos ; and crash out
dseg
selmsg: db 'FATAL ERROR - Unable to select drive','$'
cseg
badvers:
ld de,vermsg
ld c,9 ;BDOS: PRINT STRING
jp bdos ; & RETURN
dseg
vermsg: db 'MUST USE CP/M 2.2 OR CP/M 3.1','$'
cseg
; --------------------------- ;
; Direct calls to CP/M 2 BIOS ;
; --------------------------- ;
BIOS:
push de ; must save DE as sometimes passed to BIOS
ex de,hl
ld hl,(1) ; pointer to BIOS WARM BOOT
ld a,(hl)
cp jump ; check actually pointing to BIOS (not XSUB)
jp nz,badbios
add hl,de ; DE = offset from WARM BOOT to BIOS function
pop de
ld a,(hl)
cp jump ; check actually pointing to BIOS (not XSUB)
jp nz,badbios
jp (hl)
badbios: ; (NOTE DE may be on stack)
ld de,jmpmsg
ld c,9 ;BDOS: PRINT STRING
call bdos
ld c,0 ;BDOS: SYSTEM RESET
jp bdos ; and crash out
dseg
jmpmsg: db 'FATAL ERROR - Unable to find BIOS','$'
cseg
; --------------------------- ;
; Direct calls to CP/M 3 BIOS ;
; --------------------------- ;
dseg
BIOSPB:
BIOS.FUNC: ds 1 ; BIOS function number (WARM BOOT = 1)
BIOS.AREG: ds 1 ; A register contents
BIOS.BCREG: ds 2 ; BC register contents
BIOS.DEREG: ds 2 ; DE register contents
BIOS.HLREG: ds 2 ; HL register contents
cseg
page
; ------------------------------ ;
; Conversion into HEX characters ;
; ------------------------------ ;
;-----------------------------------------------------------------------;
; HEXBYT ;
; Input: <B> = Count of bytes to be converted ;
; <HL> -> first byte to be translated ;
; POSN = pointer to text field ;
; Destroys: All registers ;
; Function: Converts <B> bytes starting at <HL> into 2 digit ;
; hexadecimal characters which are added to next ;
; hexadecimal field in the text string. POSN is updated ;
; to point to the end of this hexadecimal field. ;
;-----------------------------------------------------------------------;
;-----;
hexbyt:
;-----;
push hl
push bc
ld a,(hl)
call bythex
pop bc
pop hl
inc hl
djnz hexbyt
ret
;-----------------------------------------------------------------------;
; HEXTBL ;
; Input: <B> = Count of bytes to be converted ;
; <HL> -> start of array of <B> byte to be translated ;
; <DE> -> start of table of conversion formats ;
; 1 = single byte ;
; 2 = pair of bytes to be combined as one word ;
; 3 = pair of bytes to reversed in text fields ;
; POSN = pointer to text field ;
; Destroys: All registers ;
; Function: Converts <B> bytes starting at <HL> according to ;
; format type in table pointed at by <DE>. Each entry ;
; in the table <DE> corresponds to field positions. ;
;-----------------------------------------------------------------------;
;-----;
hextbl:
;-----;
ld a,(de)
push de
cp 2
jp z,hextbl2
cp 3
jp z,hextbl3
; byte
ld a,(hl)
push bc
push hl
call bythex
jp nxttbl
; word
hextbl2:
dec b ; decrement <B> as using two bytes
push bc
ld e,(hl)
inc hl
ld d,(hl)
push hl
ex de,hl
call wrdhex ; <HL> -> text
jp nxttbl
; double byte
hextbl3:
dec b ; decrement <B> as using two bytes
push bc
inc hl
ld a,(hl) ; display 2nd byte first
dec hl
push hl
call bythex
pop hl
ld a,(hl) ; display 1st byte next
inc hl
push hl
call bythex
nxttbl: pop hl
pop bc
pop de
inc de
inc hl
djnz hextbl
ret
;-----------------------------------------------------------------------;
; WRDHEX ;
; Input: <HL> = word to converted into hexadecimal text ;
; POSN = pointer to text field ;
; Destroys: All registers ;
; Function: Converts word in <HL> into four hexadecimal characters ;
; which are added to next hexadecimal field in the ;
; text string. POSN is updated to point to the end ;
; of this hexadecimal field. ;
;-----------------------------------------------------------------------;
;-----;
wrdhex: ; display hex word in <HL> into text
;-----;
push hl ; must preserve HL
call nexthex ; returns DE -> 'h'
dec de
dec de
dec de
dec de
pop hl
push hl
ld a,h
call outnbl
pop hl
ld a,l
call outnbl
ret
;-----------------------------------------------------------------------;
; DBLHEX ;
; Input: <HL> = word to converted into hexadecimal text ;
; POSN = pointer to text field ;
; Destroys: All registers ;
; Function: Converts word in <HL> into two pairs of hexadecimal ;
; characters with the high byte displayed first. Each is ;
; added to the next hexadecimal field in the text string. ;
; POSN is updated to point to the end of the second ;
; is hexadecimal field. ;
;-----------------------------------------------------------------------;
;-----;
dblhex: ; display high hex byte into text
;-----;
ld a,h
push hl
call bythex
pop hl
; display high hex byte into text
ld a,l
jp bythex
;-----------------------------------------------------------------------;
; BYTHEX ;
; Input: <A> = byte to converted into hexadecimal text ;
; POSN = pointer to text field ;
; Destroys: All registers ;
; Function: Converts byte in <A> into two hexadecimal characters ;
; which are added to next hexadecimal field in the ;
; text string. POSN is updated to point to the end ;
; of this hexadecimal field. ;
;-----------------------------------------------------------------------;
;-----;
bythex: ; converts byte in <A> into hexadecimal text
;-----;
push af
call nexthex ; returns DE -> 'h'
dec de
dec de
pop af
call outnbl
ret
;-----;
outnbl: ; convert byte in <A> into two hex chars at <DE>
;-----;
push af
rrca
rrca
rrca
rrca
call nblhex
pop af
;-----;
nblhex: ; convert nibble in A into hex char in (DE)
;-----;
and 0fh
ld c,a
ld b,0
ld hl,hextxt
add hl,bc
ld a,(hl)
ld (de),a
inc de
ret
;-----------------------------------------------------------------------;
; NEXTHEX ;
; Input: POSN = pointer to text field ;
; Returns: <DE> -> to end of hexadecimal filed ;
; Destroys: <A>, <BC>, <HL> ;
; Function: Starting at location (POSN), scans text for hexadecimal ;
; field of the form ??h or ????h where ? is any valid ;
; hexadecimal character (0123456789ABCDEF). POSN is ;
; updated to point to the end of this hexadecimal field. ;
;-----------------------------------------------------------------------;
testhex:
cp cr ; check if end of line, as must not pass this
ret z ; even if this means overwriting text.
;------;
nexthex: ; find next hex location in text
;------;
call hexchr ; find first hex character
jp nz,testhex
call hexchr ; find second hex character
jp nz,testhex
inc de
ld a,(de)
cp 'h'
jp nz,testhex
ret
hexchr: ld hl,(posn)
inc hl
ld a,(hl)
ld d,h
ld e,l
cp cr ; test for end of line
ret z
ld (posn),hl ; update POSN
ld hl,hextxt
ld b,16
nxt1: cp (hl)
ret z
inc hl
djnz nxt1
or -1
ret
dseg
hextxt: db '0123456789ABCDEF'
cseg
page
; ================= ;
; various functions ;
; ================= ;
; ------------------------------ ;
; Wait for <RETURN> for keyboard ;
; ------------------------------ ;
waitcr:
ld de,crmsg
ld c,9 ;BDOS: PRINT STRING
call bdos
ld c,10 ; DIRECT CONSOLE BUFFER
ld de,waitbuff
call bdos
ld a,(waitlen)
or a
ret z
jp waitcr
dseg
crmsg: db cr,lf,'Hit <RETURN> to continue ','$'
waitbuff:
db 1
waitlen:
ds 1
ds 1
cseg
; ---------------------------- ;
; Fetch DPH and DPB for device ;
; ---------------------------- ;
fetchdp:
call getdpb
ld a,(vers.rel)
cp 22h
call z,getdph2
ld a,(vers.rel)
cp 31h
call z,getdph3
ret
; ---------------- ;
; Fetch CP/M 2 DPH ;
; ---------------- ;
getdph2:
ld a,(def.dsk) ; Current selected disk
ld c,a ; BIOS: Disk drive to select
ld e,-1 ; Not first time login
ld hl,001bh-0003h ; offset from WARM BOOT to select function
call BIOS
ld a,l
or h
jp z,badsel
ld (dph.ptr),hl ; save address of DPH
ld de,dph2
ld bc,len.dph2
ldir
ret
; ---------------- ;
; Fetch CP/M + DPH ;
; ---------------- ;
getdph3:
ld a,(def.dsk) ; Current selected disk
ld (BIOS.BCREG),a ; save in BIOSPB
ld hl,-1 ; Not first time login
ld (BIOS.DEREG),hl ; save in BIOSPB
ld a,9 ; BIOS: select the sepcified disk drive
ld (BIOS.FUNC),a ; save in BIOSPB
ld c,50 ;BDOS: DIRECT BIOS CALL
ld de,BIOSPB ; BIOS parameter block
call bdos ; IMPORTANT: dont trace this as BDOS
; copies DPH into keyboard character buffer
ld a,l ; BDOS returns address of its copy of DPH
or h
jp z,badsel
ld (dph.ptr),hl ; save address of DPH but this is of no value
ld de,dph3
ld bc,len.dph3
ldir
ret
; --------- ;
; Fetch DPB ;
; --------- ;
getdpb:
ld c,31 ;BDOS: GET ADDR (DPB PARMS)
call bdos
ld (dpb.ptr),hl ; save address of DPB
ld de,dpb
ld bc,len.dpb3 ; copy maximum length regardless
ldir
ret
;--------;
clearscrn: ; clear screen
;--------;
ld de,csnmsg
ld c,9 ;BDOS: PRINT STRING
jp bdos ; & RETURN
dseg
csnmsg: db cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf
db cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf
db cr,lf,lf,lf,lf,lf,'$' ; 25 line feeds
cseg
;------;
screen1: ; display menu
;------;
ld a,(def.dsk)
add a,'A'
ld (s1dsk),a
ld de,s1msg
ld c,9 ;BDOS: PRINT STRING
jp bdos ; & RETURN
dseg
s1msg: db cr,'MML:DISKSTAT DRIVE '
s1dsk: db 'A: CHARACTERISTICS '
db cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf ; 10 line feeds
db cr,lf,' 1 Display DPB statistics '
db cr,lf,' 2 Display DPH statistics '
db cr,lf,' 3 Display disk ALLOCATION '
db cr,lf;later,' 4 Display file ALLOCATION '
db cr,lf;later,' 5 Display directory ALLOCATION '
db cr,lf,' 9 Select new disk '
db cr,lf,lf,lf,lf,'$' ; 5 line feeds
cseg
;-----;
option: ; request option
;-----;
ld de,optmsg
ld c,9 ;BDOS: PRINT STRING
call bdos
ld de,optbuf
ld c,10 ;BDOS: READ CONSOLE BUFFER
call bdos
ld a,(optlen)
cp 0
jp z,optquit
cp 1
jp nz,option
ld a,(optchr)
cp '1'
jp c,option
cp '9'+1
jp nc,option ; value in range 1 to 9
sub '0'
ret
optquit:
or -1
ret
dseg
optmsg: db cr,' Enter your choice, or <RETURN> ',bs,bs,'$'
optbuf: db 2 ; maximum length of buffer
optlen: ds 1 ; number of characters returned
optchr: ds 2 ; space for up to 2 characters
cseg
;------;
makehex: ; module in showblk
;------;
; ' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 '
;sdbbyt ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h'
; ' SPT BSH BLM EXM DSM DRM AL0-AL1 CKS OFF PSH PHM'
;sdbhex ' 0000h 00h 00h 00h 0000h 0000h 00h 00h 0000h 0000h 00h 00h'
ld hl,sdbbyt
ld (posn),hl
ld a,(vers.rel)
cp 31h
jp z,makeh3
xor a ; CP/M 2 does not have PSH & PHM
ld (dpb.psh),a ; - set to zero
ld (dpb.phm),a
makeh3:
ld hl,dpb
ld b,17
call hexbyt
ld hl,sdbhex
ld (posn),hl
ld hl,dpb
ld b,17
ld de,hbtype
call hextbl
ret
dseg
hbtype: db 2,1,1,1,2,2,1,1,2,2,1,1
cseg
;------;
makedec: ; module in showblk
;------;
ld hl,sdbdec
ld (posn),hl
ld hl,(dpb.spt)
call wrddec ; <HL> -> text
ld a,(dpb.bsh)
call bytdec ; <A> -> text
ld a,(dpb.blm)
call bytdec ; <A> -> text
ld a,(dpb.exm)
call bytdec ; <A> -> text
ld hl,(dpb.dsm)
call wrddec ; <HL> -> text
ld hl,(dpb.drm)
call wrddec ; <HL> -> text
ld a,(dpb.al0)
call bytdec ; <A> -> text
ld a,(dpb.al1)
call bytdec ; <A> -> text
ld hl,(dpb.cks)
call wrddec ; <HL> -> text
ld hl,(dpb.off)
call wrddec ; <HL> -> text
ld a,(vers.rel)
cp 31h
jp nz,dec2
ld a,(dpb.psh)
call bytdec ; <A> -> text
ld a,(dpb.phm)
call bytdec ; <A> -> text
ret
dec2: xor a
call bytdec ; <A> -> text
xor a
call bytdec ; <A> -> text
ret
errdec: ; fill display with 3 asterisks as error
call nextdec ; <DE> -> leftmost digit
ld a,'*' ; set 1st 3 digits to '*'
ld (de),a
dec de
ld (de),a
dec de
ld (de),a
ret
bytdec: ; display byte in A as decimal characters
ld h,0
ld l,a
wrddec: ; display word in HL as decimal characters
ld bc,0
jp txtdec
megdec: ; display byte,word in C & HL as decimal characters
ld b,0
gigdec: ; display double word in BC & HL as decimal characters
txtdec:
ex de,hl
push de ; save 4 bytes of binary number
push bc
call nextdec ; <DE> -> leftmost digit
pop bc
pop de
call tobcd ; converts <B>, <C>, <D>, <E> into bcd at BCD
ld hl,(posn)
ex de,hl ; recover <DE> -> leftmost digit
ld a,'0' ; initialise 1st digit to a zero
ld (de),a ; (just to make sure )
ld hl,bcdlsb ; start with least significent digit
txtdec1:
call txtbcd
ret z
dec hl
jp txtdec1 ; continue till all 10 digits done
txtbcd: ; HL -> bcd digit, <DE> -> txt postion
call zrobcd ; zero when no more BCD digits (destroys <A>, <BC>)
ret z
ld a,(hl)
add a,'0'
ld (de),a
dec de
xor a
ld (hl),a ; zero BCD byte ESSENTIAL to exit when done
or -1
ret
zrobcd: ; test for all bytes of BCD being zero
; this is important as eventually all bytes
; will be set to zero during transfer to text
push hl
ld hl,bcd
xor a
ld b,10
nxtzro: or (hl)
inc hl
djnz nxtzro
pop hl
ret
;----;
tobcd: ; print binary number 0-65535 from <HL>
;----;
ld hl,binary
ld (hl),e ; least significant digit
inc hl
ld (hl),d
inc hl
ld (hl),c
inc hl
ld (hl),b ; most significent digit
push bc
ld hl,bcd
ld b,10
xor a
setbcd: ld (hl),a
inc hl
djnz setbcd ; first zero all digits
pop bc
ld a,b
or a
jp nz,upgig
ld a,c
or a
jp nz,upmeg
ld a,d
or a
jp nz,upwrd
ld a,e
or a
jp nz,upbyt
ret ; number is zero so return
upbyt: ld bc,bcdbyt ; start of BCD pointer
ld hl,byt10
jp upnxt
upwrd: ld bc,bcdwrd ; start of BCD pointer
ld hl,wrd10
jp upnxt
upmeg: ld bc,bcdmeg ; start of BCD pointer
ld hl,meg10
jp upnxt
upgig: ld bc,bcdgig ; start of BCD pointer
ld hl,gig10
;
upnxt: ld de,binary ; binary number to be converted
push bc ; save BCD pointer
ld c,-1
pdecl: push hl
push de
inc c
xor a
ld b,4
ndecl: ld a,(de)
adc a,(hl)
ld (de),a ; and reduce count
inc de
inc hl
djnz ndecl ; this doesnt effect any flags
pop de
pop hl
jp c,pdecl ; repeatedly subtract amount till carry set
push hl
push de
xor a
ld b,4
nincl: ld a,(de)
sbc a,(hl)
ld (de),a ; and increase
inc de
inc hl
djnz nincl ; this doesnt effect any flags
pop de
inc sp
inc sp ; loose <HL> (digits) saved on stack
ld a,c
pop bc ; pointer to BCD
ld (bc),a
inc bc
ld a,(hl)
or a
jp nz,upnxt
ret
dseg
bcd: ; 10 bytes, 10 digits of BCD text
bcdgig: ; max number is 4294967295
bcd.0: db 4
bcd.1: db 2
bcdmeg: ; max number is 16777215
bcd.2: db 9
bcd.3: db 4
bcd.4: db 9
bcdwrd: ; max number is 65535
bcd.5: db 6
bcd.6: db 7
bcdbyt: ; max number is 255
bcd.7: db 2
bcd.8: db 9
bcdlsb:
bcd.9: db 5
gig10: dw 13824,-15259 ; -1000000000 (C465 3600H)
dw 7936, -1526 ; -100000000 (FA0A 1F00H)
meg10: dw 27008, -153 ; -10000000 (FF67 6980H)
dw -16960, -16 ; -1000000 (FFF0 BDC0H)
dw 31072, -2 ; -100000 (FFFE 7960H)
wrd10: dw -10000, -1 ; -10000 (FFFF D8F0H)
dw -1000, -1 ; -1000 (FFFF FC18H)
byt10: dw -100, -1 ; -100 (FFFF FF9CH)
dw -10, -1 ; -10 (FFFF FFF6H)
dw -1, -1 ; -1 (FFFF FFFFH)
dw 0, 0 ; 0 (0000 0000H) this terminates all
binary: db 0,0,0,0 ; binary number filled from E, D, C, & B
cseg
testdec:
cp cr
ret z
nextdec: ; find next dec location in text and convert to space
; and return DE -> to end of 00h string
call decchr ; find first dec character
jp nz,testdec
nxt3: ld a,' ' ; erase each digit as we go
ld (de),a
call decchr ; scan subsequent dec characters
jp z,nxt3
dec de
ld a,'0'
ld (de),a ; initialise 1st digit to a zero
ex de,hl
ld (posn),hl
ret
decchr: ld hl,(posn)
inc hl
ld a,(hl)
ld d,h
ld e,l
cp cr
ret z
ld (posn),hl
ld hl,dectxt
ld b,11
nxt2: cp (hl)
ret z
inc hl
djnz nxt2
or -1
ret
dseg
dectxt: db '0123456789+*' ; + used for bit flag, * used for errors
cseg
;------;
makemax: ; module in showblk
;------;
;' BLOCK EXTENT MAX DISK DIRECTORY CHECK SUM SECTOR'
;' SIZE (K) FOLDS SIZE (K) ENTRIES ENTRIES SIZE'
;'DPB(DEC): 16K 15 1048576 65536 65536 32768'
ld hl,sdbmax
ld (posn),hl
ld a,(dpb.bsh)
ld hl,128
or a
jp z,makem2
makem1: add hl,hl
dec a
jp nz,makem1
makem2: ld a,h ; /256
rrca ; /512
rrca ; /1024
push af
ld a,(dpb.blm)
ld bc,-128
or a
jp z,makem4
makem3: add hl,bc
dec a
jp nz,makem3
makem4: add hl,bc
pop af ; recover K
ld b,a ; and save
ld a,h
or l
ld a,b
push af
call nz,errdec
pop af
call z,bytdec ; <A> -> text
ld a,(dpb.blm)
add a,1 ;+1
rra
rra
rra ;/8
ld b,a ; save EXM+1
ld hl,(dpb.dsm)
xor a ; (there must be an easier way)
sub h
dec a
ccf
adc a,h ; a = 0 if H = 0, else a = -1
and b
add a,b
add a,-1 ;-1 (convert into EXM)
ld b,a ; and save
ld a,(dpb.exm)
cp b
push af
call nz,errdec
pop af
call z,bytdec ; <A> -> text
xor a
ld hl,(dpb.dsm)
ld bc,1
add hl,bc ; increment dsm by 1
adc a,0
ld c,a ; and save in C
ld a,(dpb.bsh)
add a,-3
ld b,a
or a
ld a,c ; giga byte
jp z,makem6
makem5: add hl,hl
adc a,0
djnz makem5
makem6: ld c,a
call megdec ; <C> & <HL> -> text
xor a
ld hl,(dpb.drm)
ld bc,1
add hl,bc ; increment drm by 1
adc a,0
ld c,a
call megdec ; <C> & <HL> -> text
ld hl,(dpb.drm)
ld a,h
and a
rra
ld h,a
ld a,l
rra
ld l,a ; /2
ld a,h
and a
rra
ld h,a
ld a,l
rra
ld l,a ; /4
ld d,h
ld e,l
inc de ; DE=HL+1
ld hl,(dpb.cks)
ld a,h
or l
jp z,makem8 ; no check sum
ld a,h
and 7fh
or l
jp z,makem7 ; bit 15 set for non removable
sbc hl,de
ex de,hl
jp z,makem8
call errdec
jp makem9
makem8: ld c,0
call mmegx4 ; <C>, <HL> * 4
call megdec ; <C> & <HL> -> text
jp makem9
makem7: xor a
call nextdec
dec de
ld a,'+'
ld (de),a
inc de
inc de
makem9:
ld a,(vers.rel)
cp 31h
jp nz,makem0
ld a,(dpb.psh)
ld hl,128
or a
jp z,make02
make01: add hl,hl
dec a
jp nz,make01
make02: push hl
ld a,(dpb.phm)
ld bc,-128
or a
jp z,make04
make03: add hl,bc
dec a
jp nz,make03
make04: add hl,bc
ld a,h
or l
pop hl
push af
call nz,errdec
pop af
call z,wrddec ; <HL> -> text
ret
makem0: ld hl,128 ; CP/M 2 sector size
call wrddec ; <HL> -> text
ret
;--------;
makedir: ; module in showblk
;--------;
;' Data 1K 128 byte '
;' Blocks Blocks Records Capacity'
;' Directory 65535 16777215 16777215 16777215 Entries'
;' Data 65535 16777215 16777215 4294967296 Bytes'
;' 65000 16777215 16777215'
dseg
dirdb: db 0 ; save number of director blocks
dbsize: db 0 ; save data block size in K
cseg
ld hl,sdbdir
ld (posn),hl
ld hl,(dpb.al0)
xor a
ld b,16
maked0: add hl,hl
adc a,0
djnz maked0 ; number of directory data blocks
ld (dirdb),a
call bytdec ; <A> -> text
ld a,(dpb.bsh)
ld hl,128
or a
jp z,maked2
maked1: add hl,hl
dec a
jp nz,maked1
maked2: ld a,h ; /256
rrca ; /512
rrca ; /1024
ld (dbsize),a ; save data block size in K
ld c,a
ld b,0
ld a,(dirdb)
ld hl,0
or a
jp z,maked4
maked3: add hl,bc
dec a
jp nz,maked3
maked4: push hl
call wrddec ; <HL> -> text
pop hl
ld c,0
call mmegx8 ; multiply by 8
push hl
push bc
call megdec ; number of records (<C> & <HL> -> text)
pop bc
pop hl
call mmegX4 ; multiply by 4
call megdec ; number of entries (<C> & <HL> -> text)
ret
;--------;
makedat: ; module in showblk
;--------;
;' Data 1K 128 byte '
;' Blocks Blocks Records Capacity'
;' Directory 65535 16777215 16777215 16777215 Entries'
;' Data 65535 16777215 16777215 4294967296 Bytes'
;' 65000 16777215 16777215'
ld hl,sdbdat
ld (posn),hl
ld hl,(dpb.dsm) ; total disk blocks
ld a,(dirdb) ; blocks reserved for directory
dec a
ld c,a
ld b,0
sbc hl,bc ; leaving number of data blocks
push hl
call wrddec ; <HL> -> text
pop hl
xor a
ld b,a
ld c,a ; BC = 0
ld a,(dpb.blm)
inc a
rrca
rrca
rrca ; /8
dec a
or a
jp z,maked6
maked5: push af
call mgigx2
pop af
dec a
jp nz,maked5
maked6: push bc
push hl
call gigdec ; 1K blocks (<BC> & <HL> -> text)
pop hl
pop bc
call mgigx8 ; multiply B,C,H,& L by 8
push hl
push bc
call gigdec ; number of records (<BC> & <HL> -> text)
pop bc
pop hl
call mgigx128 ; multiply B,C,H,& L by 128
call gigdec ; number of bytes (<BC> & <HL> -> text)
ret
;--------;
maketot: ; module in showblk
;--------;
;' Data 1K 128 byte '
;' Blocks Blocks Records Capacity'
;' Directory 65535 16777215 16777215 16777215 Entries'
;' Data 65535 16777215 16777215 4294967296 Bytes'
;' 65000 16777215 16777215'
ld hl,sdbtot
ld (posn),hl
xor a
ld bc,1
ld hl,(dpb.dsm) ; total disk blocks
add hl,bc
adc a,a
ld c,a
push bc
push hl
call wrddec ; <HL> -> text
pop hl
pop bc
ld a,(dpb.blm)
inc a
rrca
rrca
rrca ; /8
dec a
or a
jp z,maked8
maked7: push af
call mgigx2
pop af
dec a
jp nz,maked7
maked8: push bc
push hl
call gigdec ; 1K blocks (<BC> & <HL> -> text)
pop hl
pop bc
call mgigx8 ; multiply B,C,H,& L by 8
call gigdec ; number of records (<BC> & <HL> -> text)
ret
mmegx8: call mmegx2 ; multiply C,H,& L by 8
mmegx4: call mmegx2 ; multiply C,H,& L by 4
mmegx2: ld a,l ; multiply C,H,& L by 2
add a,a
ld l,a
ld a,h
adc a,a
ld h,a
ld a,c
adc a,a
ld c,a
ret
mgigx8: call mgigx2 ; multiply B,C,H,& L by 8
mgigx4: call mgigx2 ; multiply B,C,H,& L by 4
mgigx2: ld a,l ; multiply B,C,H,& L by 2
add a,a
ld l,a
ld a,h
adc a,a
ld h,a
ld a,c
adc a,a
ld c,a
ld a,b
adc a,a
ld b,a
ret
mgigx128: ; multipy B,C,H,& L by 128
ld a,b
and a
rra ; we can only use lowest bit
ld a,c
rra
ld b,a
ld a,h
rra
ld c,a
ld a,l
rra
ld h,a
ld a,0
rra
ld l,a
ret
;------;
showblk: ; menu 1 option 1 Display DPB statistics
;------;
ld a,(def.dsk)
add a,'A'
ld (sdbdsk),a
call makehex
call makedec
call makemax
call makedir
call makedat
call maketot
ld de,sdbmsg
ld c,9 ;BDOS: PRINT STRING
call bdos
call waitcr
ret
dseg
sdbmsg:
db cr, ' DRIVE '
sdbdsk: db 'A: DISC PARAMETER BLOCK'
db cr,lf
db cr,lf,' '
db ' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 '
db cr,lf,'DPB: '
sdbbyt: db ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h'
db cr,lf
db cr,lf,' '
db ' SPT BSH BLM EXM DSM DRM AL0-AL1 CKS OFF PSH PHM'
db cr,lf,'DPB(HEX):'
sdbhex: db ' 0000h 00h 00h 00h 0000h 0000h 00h 00h 0000h 0000h 00h 00h'
db cr,lf,'DPB(DEC):'
sdbdec: db ' 65535 255 255 255 65535 65535 255 255 65535 65535 255 255'
db cr,lf
db cr,lf,' BLOCK EXTENT MAX DISK DIRECTORY CHECK SUM SECTOR'
db cr,lf,' '
db 'SIZE (K) FOLDS SIZE (K) ENTRIES ENTRIES SIZE'
db cr,lf,'DPB(DEC): '
sdbmax: db ' 16K 15 1048576 65536 65536 32768'
sdberr: db cr,lf,' '
db cr,lf
db cr,lf,'ALLOCATION OF DISK BLOCKS'
db cr,lf,' Data 1K 128 byte '
db cr,lf,' Blocks Blocks Records Capacity'
db lf
sdbdir: db cr,lf,' Directory 65535 16777215 16777215 16777215 Entries'
sdbdat: db cr,lf,' Data 65535 16777215 16777215 4294967296 Bytes'
db cr,lf,' -------- -------- --------'
sdbtot: db cr,lf,' 65000 16777215 16777215'
db lf
db '$'
cseg
;------;
makedph3: ; menu 1 option 2 Display DPH statistics
;------;
; ' 0 1 2 3 4 5 6 7 8 9 10 11 '
;s3byt1 ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
; ' 12 13 14 15 16 17 18 19 20 21 22 23 24 '
;s3byt2 ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
; ' XLT -0- -0- -0- -0- -0- -0- -0- -0- -0- MF '
;s3hex1 ' 0000h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
; ' DPB CSV ALV DIRBCB DTABCB HASH HBANK'
;s3hex2 ' 0000h 0000h 0000h 0000h 0000h 0000h 00h '
ld hl,s3byt1
ld (posn),hl
ld hl,dph3
ld b,12
call hexbyt
push hl
ld hl,s3byt2
ld (posn),hl
pop hl
ld b,13
call hexbyt
ld hl,s3hex1
ld (posn),hl
ld hl,dph3
ld de,h3type
ld b,12
call hextbl
push hl
ld hl,s3hex2
ld (posn),hl
pop hl
ld b,13
call hextbl
ret
dseg
h3type: db 2,1,1,1,1,1,1,1,1,1,1
db 2,2,2,2,2,2,1
cseg
;------;
makedph2: ; menu 1 option 2 Display DPH statistics
;------;
; ' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 '
;s2byt ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
; ' XLT -0- -0- -0- -0- -0- -0- DIRBCB DPB CSV ALV '
;s2hex ' 0000h 00h 00h 00h 00h 00h 00h 0000h 0000h 0000h 0000h '
ld hl,s2byt
ld (posn),hl
ld hl,dph2
ld b,16
call hexbyt
ld hl,s2hex
ld (posn),hl
ld hl,dph2
ld de,h2type
ld b,16
call hextbl
ret
dseg
h2type: db 2,1,1,1,1,1,1,2,2,2,2 ; 11 fields
cseg
ret
;------;
showhdr: ; menu 1 option 2 Display DPH statistics
;------;
ld a,(vers.rel)
cp 31h
call z,outdph3
ld a,(vers.rel)
cp 22h
call z,outdph2
ret
;------;
outdph3: ; menu 1 option 2 Display DPH statistics
;------;
ld a,(def.dsk)
add a,'A'
ld (sh3dsk),a
call makedph3
ld de,sh3msg
ld c,9 ;BDOS: PRINT STRING
call bdos
call waitcr
ret
dseg
sh3msg: db cr,' DRIVE '
sh3dsk: db 'A: DISK PARAMETER HEADER'
db cr,lf
db cr,lf,' '
db ' 0 1 2 3 4 5 6 7 8 9 10 11 '
db cr,lf,'DPH(HEX):'
s3byt1: db ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
db cr,lf
db cr,lf,' '
db ' 12 13 14 15 16 17 18 19 20 21 22 23 24 '
db cr,lf,'DPH(HEX):'
s3byt2: db ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
db cr,lf
db cr,lf,' '
db ' XLT -0- -0- -0- -0- -0- -0- -0- -0- -0- MF '
db cr,lf,'DPH(HEX):'
s3hex1: db ' 0000h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
db cr,lf
db cr,lf,' '
db ' DPB CSV ALV DIRBCB DTABCB HASH HBANK'
db cr,lf,'DPH(HEX):'
s3hex2: db ' 0000h 0000h 0000h 0000h 0000h 0000h 00h '
db cr,lf
db lf,lf,lf,lf,lf,lf,lf,lf
db '$'
cseg
;------;
outdph2: ; menu 1 option 2 Display DPH statistics
;------;
ld a,(def.dsk)
add a,'A'
ld (sh2dsk),a
call makedph2
ld de,sh2msg
ld c,9 ;BDOS: PRINT STRING
call bdos
call waitcr
ret
dseg
sh2msg: db cr,' DRIVE '
sh2dsk: db 'A: DISK PARAMETER HEADER'
db cr,lf
db cr,lf,' '
db ' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 '
db cr,lf,'DPH(HEX):'
s2byt: db ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
db cr,lf
db cr,lf,' '
db ' XLT -0- -0- -0- -0- -0- -0- DIRBCB DPB CSV ALV '
db cr,lf,'DPH(HEX):'
s2hex: db ' 0000h 00h 00h 00h 00h 00h 00h 0000h 0000h 0000h 0000h '
db cr,lf,lf,lf,lf,lf,lf,lf
db lf,lf,lf,lf,lf,lf,lf,lf
db '$'
cseg
page
; -------------------------------------------- ;
; utilities used in allocation vector analysis ;
; -------------------------------------------- ;
dseg
lenalv: ds 2 ; length of allocation vector in bytes
alvdir: ds 2 ; datablocks allocated to directory
alvdat: ds 2 ; datablocks allocated to data
alvzro: ds 2 ; datablocks not allocated
alvera: ds 2 ; datablocks allocated to erased data
alvlst: ds 2 ; datablocks allocated to overwritten data
alvbad: ds 2 ; datablocks with duplicated data access
alvrng: ds 2 ; datablocks outside maximum number
alvlen equ $-lenalv
user: db 0 ; save user number
cseg
;--;
alv: ; return <HL> = <HL>/8, & <C> = <HL> mod 7
;--;
ld c,0
call alv1 ; /2
call alv1 ; /4
call alv1 ; /8
ld a,c
rlca
rlca
rlca
ld c,a
ret
alv1: ld a,h
and a
rra
ld h,a
ld a,l
rra
ld l,a ; <HL> = <HL> / 2
ld a,c
rra
ld c,a ; C contains lost bits
ret
tstbit: ; tst bit number <C> at offset <HL> from ALLOC
; return CF=NZ if bit already set
push bc
push hl
ld hl,bitmap
ld b,0
add hl,bc
ld a,(hl) ; bit to set
ld bc,alloc
pop hl
push hl
add hl,bc
ld b,a ; save bit to set
ld a,(hl)
and b ; test if bit set
pop hl
pop bc
ret ; 0 = if not set, > 0 if set
setbit: ; set bit number <C> at offset <HL> from ALLOC
; return CF=NZ if bit already set
push bc
push hl
ld hl,bitmap
ld b,0
add hl,bc
ld a,(hl) ; bit to set
ld bc,alloc
pop hl
push hl
add hl,bc
ld b,a ; save bit to set
ld a,(hl)
ld c,a ; save byte before setting bit
or b
ld (hl),a ; set bit
ld a,c
and b ; test if bit set
pop hl
pop bc
ret ; 0 = if not set, > 0 if set
bitmap: db 10000000b ;0
db 01000000b ;1
db 00100000b ;2
db 00010000b ;3
db 00001000b ;4
db 00000100b ;5
db 00000010b ;6
db 00000001b ;7
updat:
jp nz,errbit ; bit already set
push hl
ld hl,(alvdat)
inc hl
ld (alvdat),hl ; increment count of data
pop hl
ret
errbit: ; flag bit already set
push hl
ld hl,(alvbad)
inc hl
ld (alvbad),hl ; increment count of duplicate data
pop hl
ret
upera:
jp nz,lstbit ; bit already set
push hl
ld hl,(alvera)
inc hl
ld (alvera),hl ; increment count of erased data
pop hl
ret
lstbit:
push hl
ld hl,(alvlst)
inc hl
ld (alvlst),hl ; increment count of overwritten data
pop hl
ret
uprng:
push hl
ld hl,(alvrng)
inc hl
ld (alvrng),hl ; increment count of blocks outside range
pop hl
ret
;------;
showalv: ; menu 1 option 3 Display disk ALLOCATION
;------;
ld a,(def.dsk)
add a,'A'
ld (saldsk),a
ld hl,lenalv ; start of datablock counts
ld d,h
ld e,l
inc de
ld bc,alvlen-1 ; length of datablock counts
ld (hl),0
ldir ; and zero all
ld hl,(dpb.dsm) ; number of data blocks less 1
call alv ; return <HL> = <HL>/8, & <C> = <HL> mod 7
inc hl
ld (lenalv),hl ; length of ALV in bytes
ld de,alloc ; start of ALV
add hl,de ; end of ALV
ex de,hl
ld hl,(BDOS+1) ; base of BDOS
dec hl
and a
sbc hl,de ; <HL> = top of TPA - top of ALLOC
jp nc,alvok
ld de,alverr
ld c,9 ;BDOS: PRINT STRING
call bdos
jp waitcr ; wait for <RETURN> then return
dseg
alverr: db cr,lf,'TPA too small for allocation vector','$'
cseg
; ---------------------------- ;
; initialise allocation vector ;
; ---------------------------- ;
alvok: ld hl,(lenalv)
ld b,h
ld c,l
ld hl,alloc
ld d,h
ld e,l
inc de
dec bc
ld (hl),0
ldir ; set allocation vector to 0
ld hl,(dpb.al0) ; directory ALV0 and ALV1
ld (alloc),hl ; and fill alloc bits with these
; ----------------------- ;
; count directory entries ;
; ----------------------- ;
ld b,16
ld de,0
cntalv: add hl,hl
jp nc,nocnt
inc de
nocnt: djnz cntalv
ex de,hl
ld (alvdir),hl ; number of directory entries
; -------------- ;
; scan directory ;
; -------------- ;
ld de,deffcb
ld a,'?'
ld (de),a
ld c,17 ;BDOS: SEARCH FOR FIRST
call bdos
nextdir:
cp -1
jp z,doera
ld l,a
ld h,0
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
ld de,defdma
add hl,de
ld a,(hl)
and not 00011111b ; test for high bits set
jp nz,nxtdcb
ld de,16
add hl,de
ex de,hl ; <DE> -> first data block allocation
ld hl,(dpb.dsm)
ld a,h
or a
jp nz,wrdalv
; test 16 file data block bytes
ld b,16 ; byte wide data blocks
nxtdb: push hl
ld a,(de)
or a
jp z,nuldb
cp l ; check range
jp z,updb
jp nc,errdb
updb: ld l,a
ld h,0
call alv ; return <HL> = <HL>/8, <C>=MOD(<HL>,7)
call setbit ; returns CF=NZ if bit already set
call updat
jp nuldb
errdb: call uprng ; data block outside range
nuldb: pop hl ; recover DSM
inc de ; increment to next data block allocation
djnz nxtdb
jp nxtdcb
; test 8 file data block words
wrdalv:
ex de,hl ; move back to HL
ld b,8
nxtdw: push hl
ld e,(hl)
inc hl
ld d,(hl)
ld a,e
or d
jp z,nuldw
ld hl,(dpb.dsm)
xor a
sbc hl,de
jp c,errdw
ex de,hl
call alv ; return <HL> = <HL>/8, <C>=MOD(<HL>,7)
call setbit ; returns CF=NZ if bit already set
call updat
jp nuldw
errdw: call uprng ; data block outside range
nuldw: pop hl ; recover data block pointer
inc hl
inc hl ; increment to next data block allocation
djnz nxtdw
jp nxtdcb
nxtdcb:
ld de,deffcb
xor a
ld (de),a ; set default drive
ld c,18 ;BDOS: SEARCH FOR NEXT
call bdos
jp nextdir
; -------------- ;
; scan era files ;
; -------------- ;
erabyt equ 0e5h ; CP/M byte for erased file
doera:
ld e,-1 ; to fetch user code
ld c,32 ; BDOS: SET/GET USER CODE
call bdos
ld (user),a ; save user number
ld e,5 ; set user = 5
ld c,32 ; BDOS: SET/GET USER CODE
call bdos
ld de,deffcb
ld a,'?'
ld (de),a
ld c,17 ;BDOS: SEARCH FOR FIRST
call bdos
nextera:
cp -1
jp z,erased
ld l,a
ld h,0
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
ld de,defdma
add hl,de
ld a,(hl)
and not 00011111b ; test for high bits set
jp z,nxtera
ld a,(hl)
cp erabyt
jp nz,nxtera
push hl
ld b,32
tstera: ld a,(hl)
cp erabyt
jp nz,notera
inc hl
djnz tstera ;(doesnt change flags)
notera: pop hl
jp z,erased ; as all 0e5's must be at end
ld de,16
add hl,de
ex de,hl ; <DE> -> first data block allocation
ld hl,(dpb.dsm)
ld a,h
or a
jp nz,wrdera
; test 16 erased file data block bytes
ld b,16
nxtedb: push hl ; save DSM
ld a,(de)
or a
jp z,nuledb
cp l ; check range
jp z,upedb
jp nc,erredb
upedb: ld l,a
ld h,0
call alv ; return <HL> = <HL>/8, <C>=MOD(<HL>,7)
call setbit ; returns CF=NZ if bit already set
call upera
jp nuledb
erredb: call uprng ; data block outside range
nuledb: pop hl ; recover DSM
inc de ; increment to next data block byte
djnz nxtedb
jp nxtera
; test 8 erased file data block words
wrdera:
ex de,hl ; move back to HL
ld b,8
nxtedw: push hl
ld e,(hl)
inc hl
ld d,(hl)
ld a,e
or d
jp z,nuledw
ld hl,(dpb.dsm)
xor a
sbc hl,de
jp c,erredw
ex de,hl
call alv ; return <HL> = <HL>/8, <C>=MOD(<HL>,7)
call setbit ; returns CF=NZ if bit already set
call upera
jp nuledw
erredw: call uprng ; data block outside range
nuledw: pop hl ; recover data block pointer
inc hl
inc hl ; increment to next data block word
djnz nxtedw
nxtera:
ld de,deffcb
ld a,erabyt and 11100000b ; ignore water mark,
ld (de),a ; (only works when user=5)
ld c,18 ;BDOS: SEARCH FOR NEXT
call bdos
jp nextera
erased: ; reached end of file
ld a,(user) ; recover user number
ld e,a
ld c,32 ; BDOS: SET/GET USER CODE
call bdos
; --------------------------- ;
; calculate unused datablocks ;
; --------------------------- ;
ld hl,(lenalv)
ld b,h
ld c,l
ld hl,(dpb.dsm)
ld de,alloc
nxtcnt: push bc
ld a,(de)
ld b,8
next8: add a,a
jp nc,notalc
dec hl ; reduce count by 1
notalc: djnz next8
inc de
pop bc
dec bc
ld a,b
or c
jp nz,nxtcnt
inc hl ; as started with dsm, not dsm+1
ld (alvzro),hl
; ---------------------- ;
; fill text with results ;
; ---------------------- ;
ld hl,alv01
ld (posn),hl
xor a
ld hl,(dpb.dsm)
ld de,1
add hl,de
adc a,0
ld c,0
call megdec ; write total number of datablocks
ld hl,alv02
ld (posn),hl
ld hl,(alvdir) ; datablocks allocated to directory
call wrddec
ld hl,alv03
ld (posn),hl
ld hl,(alvdat) ; datablocks allocated to data
call wrddec
ld hl,alv04
ld (posn),hl
ld hl,(alvera) ; datablocks allocated to erased data
call wrddec
ld hl,alv05
ld (posn),hl
ld hl,(alvlst) ; datablocks allocated to overwritten data
call wrddec
ld hl,alv06
ld (posn),hl
ld hl,(alvbad) ; datablocks with duplicated data access
call wrddec
ld hl,alv07
ld (posn),hl
ld hl,(alvzro) ; datablocks not allocated
call wrddec
ld hl,alv08
ld (posn),hl
ld hl,(alvdir)
xor a
ld c,a
ex de,hl
ld hl,(alvdat)
add hl,de
adc a,c
ex de,hl
ld hl,(alvera)
add hl,de
adc a,c
ex de,hl
ld hl,(alvzro)
add hl,de
adc a,c
ld c,a
call megdec
ld hl,alv09
ld (posn),hl
ld hl,(alvrng) ; datablocks with duplicated data access
call wrddec
; ------------ ;
; display text ;
; ------------ ;
ld de,salmsg
ld c,9 ;BDOS: PRINT STRING
call bdos
jp waitcr ; wait for <RETURN> then return
dseg
salmsg: db cr,' DRIVE '
saldsk: db 'A: DISK ALLOCATION'
db cr,lf
db cr,lf,' DATA BLOCKS '
db cr,lf
db cr,lf,' TOTAL (DRM+1) '
alv01: db ' 65536 '
db cr,lf
db cr,lf,' Directory '
alv02: db ' 16 '
db cr,lf,' Data '
alv03: db ' 65535 '
db cr,lf,' Erased and recoverable '
alv04: db ' 65535 '
db cr,lf,' Unused '
alv07: db ' 65535 '
db cr,lf,' '
db ' ----- '
db cr,lf,' '
alv08: db ' 65536 '
db cr,lf
db cr,lf,' Erased and reused '
alv05: db ' 65535 '
db cr,lf,' Duplicated data '
alv06: db ' 65535 '
db cr,lf,' Blocks outside range '
alv09: db ' 65535 '
db cr,lf,lf,lf,lf,lf,lf,lf
db '$'
cseg
;------;
showfil: ; menu 1 option 4 Display file ALLOCATION
;------;
ld a,(def.dsk)
add a,'A'
ld (sfldsk),a
ld de,sflmsg
ld c,9 ;BDOS: PRINT STRING
jp bdos ; & RETURN
dseg
sflmsg: db cr,' DRIVE '
sfldsk: db 'A: FILE ALLOCATION'
db lf
db cr,lf,lf,lf,lf,lf,'$' ; 10 line feeds
cseg
;------;
showdir: ; menu 1 option 5 Display directory ALLOCATION
;------;
ld a,(def.dsk)
add a,'A'
ld (sdrdsk),a
ld de,sdrmsg
ld c,9 ;BDOS: PRINT STRING
jp bdos ; & RETURN
dseg
sdrmsg: db cr,' DRIVE '
sdrdsk: db 'A: DIRECTORY ALLOCATION'
db lf
db cr,lf,lf,lf,lf,lf,'$' ; 10 line feeds
cseg
page
;-----;
select: ; menu 1 option 9 Select new disk
;-----;
ld a,(def.dsk)
ld (olddsk),a ; save in case of error
ld de,sldmsg
ld c,9 ;BDOS: PRINT STRING
call bdos
; ---------------------- ;
; Request new drive name ;
; ---------------------- ;
sel0:
ld de,logmsg
ld c,9 ;BDOS: PRINT STRING
call bdos
ld de,selbuff
ld c,10 ;BDOS: DIRECT CONSOLE BUFFER
call bdos
ld a,(sellen)
or a
ret z ; nothing selected
cp 1
jp z,sel1
cp 2
jp nz,sel0
ld a,(seldb2)
cp ':'
jp nz,sel0
sel1: ld a,(seldb1)
cp 'a'
jp c,sel2
cp 'z'+1
jp nc,sel0
add a,'A'-'a' ; convert to lower case
sel2: sub 'A'
cp 15+1
jp nc,sel0 ; outside range 0-15
ld (def.dsk),a ; Current selected disk
ld c,13 ;BDOS: RESET DISK SYSTEM
call bdos
ld a,(def.dsk)
ld e,a
ld c,14 ;BDOS: SELECT DISK
call bdos
or a
jp nz,selerr
call fetchdp ; fetch dpb and dph for drive
ret
selerr: ld a,(olddsk) ; recover previously selecte disk
ld (def.dsk),a
ld e,a
ld c,14 ;BDOS: SELECT DISK
call bdos
or a
jp nz,badsel
call fetchdp ; fetch dpb and dph for drive
ld de,oldmsg
ld c,9 ;BDOS: PRINT STRING
call bdos
call waitcr
ret
dseg
sldmsg: db cr,lf,lf,lf,lf,lf ; 5 line feeds
db cr,lf,lf,lf,lf,lf ; 5 line feeds
db cr,lf,lf,lf,lf,lf ; 5 line feeds
db cr,lf,lf,lf,lf,lf ; 5 line feeds
db cr,' SELECT NEW DISK'
db lf
db cr,lf,lf,lf,lf,lf,'$' ; 5 line feeds
olddsk: db 0
logmsg: db cr,'Enter drive name (A:, B:, etc ) ? ',bs,bs,bs,'$'
selbuff:
db 3
sellen:
ds 1
seldb1: ds 1
seldb2: ds 2
oldmsg: db cr,lf,'--- Unable to select new disk ---'
db cr,lf,lf,lf,lf,lf,'$' ; 5 line feeds
cseg
page
;-------;
goodvers:
;-------;
ld a,(deffcb)
dec a
cp -1
jp nz,useccp ; use ccp disk
ld c,25 ;BDOS: RETURN CURRENT DISK
call bdos
useccp: ld (def.dsk),a ; Current selected disk
ld c,13 ;BDOS: RESET DISK SYSTEM
call bdos
ld a,(def.dsk)
ld e,a
ld c,14 ;BDOS: SELECT DISK
call bdos
or a
jp nz,badsel
ld (savesp),sp ; must use local stack as BIOS may be hungry
ld sp,savesp
call fetchdp ; fetch dpb and dph for drive
call main ; now display as requested
ld sp,(savesp)
ld c,0 ;BDOS: SYSTEM RESET
jp bdos ; & exit
;---;
main:
;---;
call clearscrn ; clear screen
call screen1 ; display menu
call option ; request option
cp -1
ret z
call task1
jp main
;----;
task1:
;----;
ld c,a
ld b,0
dec bc
ld hl,table1
add hl,bc
add hl,bc
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
jp (hl)
table1: dw showblk ; menu 1 option 1 Display DPB statistics
dw showhdr ; menu 1 option 2 Display DPH statistics
dw showalv ; menu 1 option 3 Display disk ALLOCATION
dw showfil ; menu 1 option 4 Display file ALLOCATION
dw showdir ; menu 1 option 5 Display directory ALLOCATION
dw return
dw return
dw return
dw select ; menu 1 option 9 Select new disk
return: ret
dseg
alloc equ $ ; allocation vector placed at end of program
end