home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / dskutl / diskstat.mac < prev    next >
Text File  |  1994-07-13  |  47KB  |  2,433 lines

  1.     .z80
  2.     title    DISKSTAT Disk statistics
  3.  
  4.     name    ('DISKST')
  5.  
  6. ;------------------------------------------------------------------
  7. ; Utility to display disc characteristics and file allocation
  8. ;
  9. ; Copyright 1983 D. Powys-Lybbe
  10. ; Author: D. Powys-Lybbe, MML Systems Ltd., London
  11. ; Date: 20th June 1983
  12. ;
  13. ;------------------------------------------------------------------
  14. ; Revisions
  15. ; =========
  16. ;
  17. ;------------------------------------------------------------------
  18.  
  19. ;------------------------------------------------------------------------
  20.     page
  21.  
  22.  
  23.     public    def.dsk,dpb,dph2,dph3,dpb.ptr,dph.ptr,vers,vers.rel,vers.os
  24.     public    savesp
  25.     public    BADSEL,selmsg,badvers,vermsg,BIOS,badbios,jmpmsg
  26.     public    BIOSPB,BIOS.FUNC,BIOS.AREG,BIOS.BCREG,BIOS.DEREG,BIOS.HLREG
  27.     public    waitcr,waitbuff,waitlen,fetchdp
  28.     public    clearscrn,csnmsg,screen1,s1msg,s1dsk
  29.     public    option,optquit,optmsg,optbuf,optlen,optchr
  30.     public    makehex,wrdhex,dblhex,bythex,nblhex,testhex,nexthex
  31.     public        hexchr,hextxt
  32.     public    makedec,dec2,errdec,gigdec,megdec,wrddec,bytdec,txtdec,zrobcd
  33.     public    tobcd,bcd,testdec,nextdec,decchr,dectxt
  34.     public    makemax,makem1,makem2,makem3,makem4,makem5,makem6,makem8
  35.     public    makem7,makem9,make01,make02,make03,make04,makem0
  36.     public    makedir,dirdb,dbsize,maked0,maked1,maked2,maked3,maked4
  37.     public    makedat,maked5,maked6
  38.     public    maketot,maked7,maked8
  39.     public    mmegx8,mmegx4,mmegx2,mgigx8,mgigx4,mgigx2,mgigx128
  40.     public    showblk,posn,sdbmsg,sdbdsk,sdbhex,sdbdec,sdbmax
  41.     public    sdbdir,sdbdat,sdbtot
  42.     public    showhdr
  43.     public    showalv,salmsg,saldsk
  44.     public    showfil,sflmsg,sfldsk
  45.     public    showdir,sdrmsg,sdrdsk
  46.     public    goodvers,useccp,main,task1,table1,return
  47.  
  48.  
  49. ;------------------------------------------------------------------------
  50.     page
  51.  
  52. ;        ===============
  53. ;        DISC DATA AREAS
  54. ;        ===============
  55.  
  56. ;--------------------------------------------------------------
  57. ;
  58. ; CP/M disc parameters
  59. ;
  60. ;--------------------------------------------------------------
  61.  
  62.     dseg
  63. def.dsk:    db    0        ; Selected disc
  64.  
  65. dpb:                ; Drive disk parameter block
  66. dpb.spt:    ds    2
  67. dpb.bsh:    ds    1
  68. dpb.blm:    ds    1
  69. dpb.exm:    ds    1
  70. dpb.dsm:    ds    2
  71. dpb.drm:    ds    2
  72. dpb.al0:    ds    1
  73. dpb.al1:    ds    1
  74. dpb.cks:    ds    2
  75. dpb.off:    ds    2
  76. len.dpb2    equ    $-dpb    ; length of CP/M 2 dpb
  77. dpb.psh:    ds    1
  78. dpb.phm:    ds    1
  79. len.dpb3    equ    $-dpb    ; length of CP/M + dpb
  80.  
  81. dph2:                ; CP/M 2 disk parameter header
  82. dph2.xlt:    ds    2
  83. dph2.zro:    ds    6
  84. dph2.dir:    ds    2
  85. dph2.dpb:    ds    2
  86. dph2.csv:    ds    2
  87. dph2.alv:    ds    2
  88. len.dph2    equ    $-dph2    ; length of CP/M 2 dph
  89.  
  90. dph3:                ; CP/M + disk parameter header
  91. dph3.xlt:    ds    2
  92. dph3.zro:    ds    9
  93. dph3.mf:    ds    1
  94. dph3.dpb:    ds    2
  95. dph3.csv:    ds    2
  96. dph3.alv:    ds    2
  97. dph3.dir:    ds    2
  98. dph3.dat:    ds    2
  99. dph3.hsh:    ds    2
  100. dph3.bnk:    ds    1
  101. len.dph3    equ    $-dph3    ; length of CP/M + dph
  102.  
  103. dpb.ptr:    dw    0    ; address of dpb
  104. dph.ptr:    dw    0    ; address of dph
  105.  
  106. vers:                ; O.S. Version number
  107. vers.rel:    ds    1    ; O.S. Version/Release number
  108. vers.os:    ds    1    ; O.S. number
  109.  
  110. posn:    dw    0    ; pointer to text string
  111.  
  112. ; ------;
  113. ; stack ;
  114. ; ------;
  115.     ds    64        ; dont know how much stack BIOS requires
  116. savesp:    dw    0
  117.  
  118. ; ----------------;
  119. ; address equates ;
  120. ; ----------------;
  121.  
  122. bdos    equ    5        ; BDOS entry point
  123. deffcb    equ    5ch        ; CCP puts default FCB here
  124. defdma    equ    80h        ; CCP sets default DMA here
  125.  
  126. ; -----------------;
  127. ; constant equates ;
  128. ; -----------------;
  129.  
  130. bs    equ    08h        ; <BACK SPACE>
  131. cr    equ    0dh        ; <RETURN>
  132. lf    equ    0ah        ; <LINE FEED>
  133. jump    equ    0c3h        ; JP instruction
  134.  
  135.     cseg
  136.  
  137. ;-------------------------------------------------------------------------;
  138.     page
  139.  
  140.  
  141. ;-------;
  142. ; start ;
  143. ;-------;
  144.     cseg
  145.  
  146.  
  147.     ld    c,12        ; BDOS: RETURN VERSION NUMBER
  148.     call    bdos
  149.     ld    (vers),hl
  150.     ld    a,h
  151.     cp    00h    ; check for CP/M
  152.     jp    nz,badvers
  153. ;
  154.     ld    a,l
  155.     cp    22h
  156.     jp    z,goodvers
  157. ;
  158.     ld    a,l
  159.     cp    31h
  160.     jp    z,goodvers
  161.  
  162.     page
  163.             ; ================= ;
  164.             ; various utilities ;
  165.             ; ================= ;
  166.  
  167. ; -------------- ;
  168. ; Error routines ;
  169. ; -------------- ;
  170.  
  171. BADSEL:
  172.     ld    de,selmsg
  173.     ld    c,9        ;BDOS: PRINT STRING
  174.     call    bdos
  175.  
  176.     ld    c,0        ;BDOS: SYSTEM RESET
  177.     jp    bdos        ; and crash out
  178.  
  179.     dseg
  180. selmsg:    db    'FATAL ERROR - Unable to select drive','$'    
  181.     cseg
  182.  
  183. badvers:
  184.     ld    de,vermsg
  185.     ld    c,9        ;BDOS: PRINT STRING
  186.     jp    bdos        ; & RETURN
  187.     dseg
  188. vermsg:    db    'MUST USE CP/M 2.2 OR CP/M 3.1','$'    
  189.     cseg
  190.  
  191. ; --------------------------- ;
  192. ; Direct calls to CP/M 2 BIOS ;
  193. ; --------------------------- ;
  194.  
  195. BIOS:
  196.     push    de        ; must save DE as sometimes passed to BIOS
  197.     ex    de,hl
  198.     ld    hl,(1)        ; pointer to BIOS WARM BOOT
  199.     ld    a,(hl)
  200.     cp    jump        ; check actually pointing to BIOS (not XSUB)
  201.     jp    nz,badbios
  202.     add    hl,de        ; DE = offset from WARM BOOT to BIOS function
  203.     pop    de
  204.     ld    a,(hl)
  205.     cp    jump        ; check actually pointing to BIOS (not XSUB)
  206.     jp    nz,badbios
  207.     jp    (hl)
  208.  
  209. badbios:            ; (NOTE DE may be on stack)
  210.     ld    de,jmpmsg
  211.     ld    c,9        ;BDOS: PRINT STRING
  212.     call    bdos
  213.  
  214.     ld    c,0        ;BDOS: SYSTEM RESET
  215.     jp    bdos        ; and crash out
  216.  
  217.     dseg
  218. jmpmsg:    db    'FATAL ERROR - Unable to find BIOS','$'    
  219.     cseg
  220.  
  221.  
  222. ; --------------------------- ;
  223. ; Direct calls to CP/M 3 BIOS ;
  224. ; --------------------------- ;
  225.  
  226.     dseg
  227. BIOSPB:
  228. BIOS.FUNC:    ds    1    ; BIOS function number (WARM BOOT = 1)
  229. BIOS.AREG:    ds    1    ; A register contents
  230. BIOS.BCREG:    ds    2    ; BC register contents
  231. BIOS.DEREG:    ds    2    ; DE register contents
  232. BIOS.HLREG:    ds    2    ; HL register contents
  233.     cseg
  234.  
  235.  
  236.     page
  237.  
  238. ; ------------------------------ ;
  239. ; Conversion into HEX characters ;
  240. ; ------------------------------ ;
  241.  
  242. ;-----------------------------------------------------------------------;
  243. ; HEXBYT                                ;
  244. ; Input:    <B> = Count of bytes to be converted            ;
  245. ;        <HL> -> first byte to be translated            ;
  246. ;        POSN = pointer to text field                ;
  247. ; Destroys:    All registers                        ;
  248. ; Function:    Converts <B> bytes starting at <HL> into 2 digit    ;
  249. ;        hexadecimal characters which are added to next        ;
  250. ;        hexadecimal field in the text string. POSN is updated    ;
  251. ;        to point to the end of this hexadecimal field.        ;
  252. ;-----------------------------------------------------------------------;
  253.  
  254. ;-----;
  255. hexbyt:
  256. ;-----;
  257.     push    hl
  258.     push    bc
  259.     ld    a,(hl)
  260.     call    bythex
  261.     pop    bc
  262.     pop    hl
  263.     inc    hl
  264.     djnz    hexbyt
  265.     ret
  266.  
  267. ;-----------------------------------------------------------------------;
  268. ; HEXTBL                                ;
  269. ; Input:    <B> = Count of bytes to be converted            ;
  270. ;        <HL> -> start of array of <B> byte to be translated    ;
  271. ;        <DE> -> start of table of conversion formats        ;
  272. ;            1 = single byte                    ;
  273. ;            2 = pair of bytes to be combined as one word    ;
  274. ;            3 = pair of bytes to reversed in text fields    ;
  275. ;        POSN = pointer to text field                ;
  276. ; Destroys:    All registers                        ;
  277. ; Function:    Converts <B> bytes starting at <HL> according to    ;
  278. ;        format type in table pointed at by <DE>. Each entry    ;
  279. ;        in the table <DE> corresponds to field positions.    ;
  280. ;-----------------------------------------------------------------------;
  281.  
  282. ;-----;
  283. hextbl: 
  284. ;-----;
  285.     ld    a,(de)
  286.     push    de
  287.     cp    2
  288.     jp    z,hextbl2
  289.     cp    3
  290.     jp    z,hextbl3
  291.  
  292. ; byte
  293.     ld    a,(hl)
  294.     push    bc
  295.     push    hl
  296.     call    bythex
  297.     jp    nxttbl
  298.  
  299. ; word
  300. hextbl2:
  301.     dec    b    ; decrement <B> as using two bytes
  302.     push    bc
  303.     ld    e,(hl)
  304.     inc    hl
  305.     ld    d,(hl)
  306.     push    hl
  307.     ex    de,hl
  308.     call    wrdhex    ; <HL> -> text
  309.     jp    nxttbl
  310.  
  311. ; double byte
  312. hextbl3:
  313.     dec    b    ; decrement <B> as using two bytes
  314.     push    bc
  315.     inc    hl
  316.     ld    a,(hl)    ; display 2nd byte first
  317.     dec    hl
  318.     push    hl
  319.     call    bythex
  320.     pop    hl
  321.     ld    a,(hl)    ; display 1st byte next
  322.     inc    hl
  323.     push    hl
  324.     call    bythex
  325.  
  326. nxttbl:    pop    hl
  327.     pop    bc
  328.     pop    de
  329.     inc    de
  330.     inc    hl
  331.     djnz    hextbl
  332.     ret
  333.  
  334. ;-----------------------------------------------------------------------;
  335. ; WRDHEX                                ;
  336. ; Input:    <HL>  = word to converted into hexadecimal text        ;
  337. ;        POSN = pointer to text field                ;
  338. ; Destroys:    All registers                        ;
  339. ; Function:    Converts word in <HL> into four hexadecimal characters    ;
  340. ;        which are added to next hexadecimal field in the    ;
  341. ;        text string. POSN is updated to point to the end    ;
  342. ;        of this hexadecimal field.                ;
  343. ;-----------------------------------------------------------------------;
  344.  
  345. ;-----;
  346. wrdhex:            ; display hex word in <HL> into text
  347. ;-----;
  348.  
  349.     push    hl    ; must preserve HL
  350.     call    nexthex    ; returns DE -> 'h'
  351.     dec    de
  352.     dec    de
  353.     dec    de
  354.     dec    de
  355.     pop    hl
  356.     push    hl
  357.     ld    a,h
  358.     call    outnbl
  359.     pop    hl
  360.     ld    a,l
  361.     call    outnbl
  362.     ret
  363.  
  364. ;-----------------------------------------------------------------------;
  365. ; DBLHEX                                ;
  366. ; Input:    <HL>  = word to converted into hexadecimal text        ;
  367. ;        POSN = pointer to text field                ;
  368. ; Destroys:    All registers                        ;
  369. ; Function:    Converts word in <HL> into two pairs of hexadecimal    ;
  370. ;        characters with the high byte displayed first. Each is    ;
  371. ;        added to the next hexadecimal field in the text string.    ;
  372. ;        POSN is updated to point to the end of the second    ;
  373. ;        is hexadecimal field.                    ;
  374. ;-----------------------------------------------------------------------;
  375.  
  376. ;-----;
  377. dblhex:            ; display high hex byte into text
  378. ;-----;
  379.     ld    a,h
  380.     push    hl
  381.     call    bythex
  382.     pop    hl
  383.             ; display high hex byte into text
  384.     ld    a,l
  385.     jp    bythex
  386.  
  387. ;-----------------------------------------------------------------------;
  388. ; BYTHEX                                ;
  389. ; Input:    <A>  = byte to converted into hexadecimal text        ;
  390. ;        POSN = pointer to text field                ;
  391. ; Destroys:    All registers                        ;
  392. ; Function:    Converts byte in <A> into two hexadecimal characters    ;
  393. ;        which are added to next hexadecimal field in the    ;
  394. ;        text string. POSN is updated to point to the end    ;
  395. ;        of this hexadecimal field.                ;
  396. ;-----------------------------------------------------------------------;
  397.  
  398. ;-----;
  399. bythex:            ; converts byte in <A> into hexadecimal text
  400. ;-----;
  401.     push    af
  402.     call    nexthex    ; returns DE -> 'h'
  403.     dec    de
  404.     dec    de
  405.     pop    af
  406.     call    outnbl
  407.     ret
  408.  
  409. ;-----;
  410. outnbl:            ; convert byte in <A> into two hex chars at <DE>
  411. ;-----;
  412.     push    af
  413.     rrca
  414.     rrca
  415.     rrca
  416.     rrca
  417.     call    nblhex
  418.     pop    af
  419. ;-----;
  420. nblhex:            ; convert nibble in A into hex char in (DE)
  421. ;-----;
  422.     and    0fh
  423.     ld    c,a
  424.     ld    b,0
  425.     ld    hl,hextxt
  426.     add    hl,bc
  427.     ld    a,(hl)
  428.     ld    (de),a
  429.     inc    de
  430.     ret
  431.  
  432. ;-----------------------------------------------------------------------;
  433. ; NEXTHEX                                ;
  434. ; Input:    POSN = pointer to text field                ;
  435. ; Returns:    <DE> -> to end of hexadecimal filed            ;
  436. ; Destroys:    <A>, <BC>, <HL>                     ;
  437. ; Function:    Starting at location (POSN), scans text for hexadecimal ;
  438. ;        field of the form ??h or ????h where ? is any valid    ;
  439. ;        hexadecimal character (0123456789ABCDEF). POSN is    ;
  440. ;        updated to point to the end of this hexadecimal field.    ;
  441. ;-----------------------------------------------------------------------;
  442.  
  443.  
  444. testhex:
  445.     cp    cr    ; check if end of line, as must not pass this
  446.     ret    z    ; even if this means overwriting text.
  447.  
  448. ;------;
  449. nexthex:        ; find next hex location in text
  450. ;------;
  451.  
  452.     call    hexchr    ; find first hex character
  453.     jp    nz,testhex
  454.     call    hexchr    ; find second hex character
  455.     jp    nz,testhex
  456.     inc    de
  457.     ld    a,(de)
  458.     cp    'h'
  459.     jp    nz,testhex
  460.     ret
  461.  
  462. hexchr:    ld    hl,(posn)
  463.     inc    hl
  464.     ld    a,(hl)
  465.     ld    d,h
  466.     ld    e,l
  467.     cp    cr        ; test for end of line
  468.     ret    z    
  469.     ld    (posn),hl    ; update POSN
  470.     ld    hl,hextxt
  471.     ld    b,16
  472. nxt1:    cp    (hl)
  473.     ret    z
  474.     inc    hl
  475.     djnz    nxt1
  476.     or    -1
  477.     ret
  478.     dseg
  479. hextxt:    db    '0123456789ABCDEF'
  480.     cseg
  481.  
  482.     page
  483.             ; ================= ;
  484.             ; various functions ;
  485.             ; ================= ;
  486.  
  487.  
  488. ; ------------------------------ ;
  489. ; Wait for <RETURN> for keyboard ;
  490. ; ------------------------------ ;
  491.  
  492. waitcr:
  493.     ld    de,crmsg
  494.     ld    c,9        ;BDOS: PRINT STRING
  495.     call    bdos
  496.  
  497.     ld    c,10    ; DIRECT CONSOLE BUFFER
  498.     ld    de,waitbuff
  499.     call    bdos
  500.     ld    a,(waitlen)
  501.     or    a
  502.     ret    z
  503.     jp    waitcr
  504.  
  505.     dseg
  506. crmsg:    db    cr,lf,'Hit <RETURN> to continue ','$'
  507. waitbuff:
  508.     db    1
  509. waitlen:
  510.     ds    1
  511.     ds    1
  512.     cseg    
  513.  
  514.  
  515. ; ---------------------------- ;
  516. ; Fetch DPH and DPB for device ;
  517. ; ---------------------------- ;
  518.  
  519. fetchdp:
  520.     call    getdpb
  521.  
  522.     ld    a,(vers.rel)
  523.     cp    22h
  524.     call    z,getdph2
  525.  
  526.     ld    a,(vers.rel)
  527.     cp    31h
  528.     call    z,getdph3
  529.  
  530.     ret
  531.  
  532. ; ---------------- ;
  533. ; Fetch CP/M 2 DPH ;
  534. ; ---------------- ;
  535.  
  536. getdph2:
  537.  
  538.     ld    a,(def.dsk)    ; Current selected disk
  539.     ld    c,a        ; BIOS: Disk drive to select
  540.     ld    e,-1        ; Not first time login
  541.     ld    hl,001bh-0003h    ; offset from WARM BOOT to select function
  542.     call    BIOS
  543.     ld    a,l
  544.     or    h
  545.     jp    z,badsel
  546.  
  547.     ld    (dph.ptr),hl    ; save address of DPH
  548.     ld    de,dph2
  549.     ld    bc,len.dph2
  550.     ldir
  551.  
  552.     ret
  553.  
  554. ; ---------------- ;
  555. ; Fetch CP/M + DPH ;
  556. ; ---------------- ;
  557.  
  558. getdph3:
  559.  
  560.     ld    a,(def.dsk)    ; Current selected disk
  561.     ld    (BIOS.BCREG),a    ; save in BIOSPB
  562.  
  563.     ld    hl,-1        ; Not first time login
  564.     ld    (BIOS.DEREG),hl    ; save in BIOSPB
  565.  
  566.     ld    a,9        ; BIOS: select the sepcified disk drive
  567.     ld    (BIOS.FUNC),a    ; save in BIOSPB
  568.  
  569.     ld    c,50        ;BDOS: DIRECT BIOS CALL
  570.     ld    de,BIOSPB    ; BIOS parameter block
  571.     call    bdos        ; IMPORTANT: dont trace this as BDOS
  572.                 ; copies DPH into keyboard character buffer
  573.     ld    a,l        ; BDOS returns address of its copy of DPH
  574.     or    h
  575.     jp    z,badsel
  576.  
  577.     ld    (dph.ptr),hl    ; save address of DPH but this is of no value
  578.     ld    de,dph3
  579.     ld    bc,len.dph3
  580.     ldir
  581.  
  582.     ret
  583.  
  584. ; --------- ;
  585. ; Fetch DPB ;
  586. ; --------- ;
  587.  
  588. getdpb:
  589.  
  590.     ld    c,31        ;BDOS: GET ADDR (DPB PARMS)
  591.     call    bdos
  592.  
  593.     ld    (dpb.ptr),hl    ; save address of DPB
  594.     ld    de,dpb
  595.     ld    bc,len.dpb3    ; copy maximum length regardless
  596.     ldir 
  597.  
  598.     ret
  599.  
  600. ;--------;
  601. clearscrn:    ; clear screen
  602. ;--------;
  603.     ld    de,csnmsg
  604.     ld    c,9        ;BDOS: PRINT STRING
  605.     jp    bdos        ; & RETURN
  606.     dseg
  607. csnmsg:    db    cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf
  608.     db    cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf
  609.     db    cr,lf,lf,lf,lf,lf,'$'        ; 25 line feeds
  610.     cseg
  611.  
  612. ;------;
  613. screen1:        ; display menu
  614. ;------;
  615.     ld    a,(def.dsk)
  616.     add    a,'A'
  617.     ld    (s1dsk),a
  618.     ld    de,s1msg
  619.     ld    c,9        ;BDOS: PRINT STRING
  620.     jp    bdos        ; & RETURN
  621.     dseg
  622. s1msg:    db    cr,'MML:DISKSTAT         DRIVE '
  623. s1dsk:    db    'A: CHARACTERISTICS '
  624.     db    cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf    ; 10 line feeds
  625.     db    cr,lf,'                   1    Display DPB statistics '
  626.     db    cr,lf,'                   2    Display DPH statistics '
  627.     db    cr,lf,'                   3    Display disk ALLOCATION '
  628.     db    cr,lf;later,'                   4    Display file ALLOCATION '
  629.     db    cr,lf;later,'                   5    Display directory ALLOCATION '
  630.     db    cr,lf,'                   9    Select new disk '
  631.     db    cr,lf,lf,lf,lf,'$'        ; 5 line feeds
  632.     cseg
  633.  
  634. ;-----;
  635. option:            ; request option
  636. ;-----;
  637.  
  638.     ld    de,optmsg
  639.     ld    c,9        ;BDOS: PRINT STRING
  640.     call    bdos
  641.  
  642.     ld    de,optbuf
  643.     ld    c,10        ;BDOS: READ CONSOLE BUFFER
  644.     call    bdos
  645.  
  646.     ld    a,(optlen)
  647.     cp    0
  648.     jp    z,optquit
  649.     cp    1
  650.     jp    nz,option
  651.  
  652.     ld    a,(optchr)
  653.     cp    '1'
  654.     jp    c,option
  655.     cp    '9'+1
  656.     jp    nc,option    ; value in range 1 to 9
  657.     sub    '0'
  658.  
  659.     ret
  660.  
  661. optquit:
  662.     or    -1
  663.     ret
  664.  
  665.     dseg
  666. optmsg:    db    cr,'     Enter your choice, or <RETURN>   ',bs,bs,'$'
  667. optbuf:    db    2    ; maximum length of buffer
  668. optlen:    ds    1    ; number of characters returned
  669. optchr:    ds    2    ; space for up to 2 characters
  670.     cseg
  671.  
  672.  
  673. ;------;
  674. makehex:        ; module in showblk
  675. ;------;
  676.  
  677.  
  678. ;    '   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16 '
  679. ;sdbbyt    '  00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h'
  680. ;    '     SPT  BSH BLM EXM    DSM     DRM  AL0-AL1    CKS     OFF  PSH PHM'
  681. ;sdbhex    '    0000h 00h 00h 00h   0000h   0000h 00h 00h   0000h   0000h 00h 00h'
  682.  
  683.     ld    hl,sdbbyt
  684.     ld    (posn),hl
  685.  
  686.     ld    a,(vers.rel)
  687.     cp    31h
  688.     jp    z,makeh3
  689.  
  690.     xor    a        ; CP/M 2  does not have PSH & PHM
  691.     ld    (dpb.psh),a    ; - set to zero
  692.     ld    (dpb.phm),a
  693.  
  694. makeh3:
  695.  
  696.     ld    hl,dpb
  697.     ld    b,17
  698.     call    hexbyt
  699.  
  700.     ld    hl,sdbhex
  701.     ld    (posn),hl
  702.  
  703.     ld    hl,dpb
  704.     ld    b,17
  705.     ld    de,hbtype
  706.     call    hextbl
  707.  
  708.     ret
  709.  
  710.     dseg
  711. hbtype:    db    2,1,1,1,2,2,1,1,2,2,1,1
  712.     cseg
  713.  
  714.  
  715. ;------;
  716. makedec:        ; module in showblk
  717. ;------;
  718.  
  719.     ld    hl,sdbdec
  720.     ld    (posn),hl
  721.  
  722.     ld    hl,(dpb.spt)
  723.     call    wrddec        ; <HL> -> text
  724.  
  725.     ld    a,(dpb.bsh)
  726.     call    bytdec        ; <A> -> text
  727.     ld    a,(dpb.blm)
  728.     call    bytdec        ; <A> -> text
  729.  
  730.     ld    a,(dpb.exm)
  731.     call    bytdec        ; <A> -> text
  732.  
  733.     ld    hl,(dpb.dsm)
  734.     call    wrddec        ; <HL> -> text
  735.  
  736.     ld    hl,(dpb.drm)
  737.     call    wrddec        ; <HL> -> text
  738.  
  739.     ld    a,(dpb.al0)
  740.     call    bytdec        ; <A> -> text
  741.     ld    a,(dpb.al1)
  742.     call    bytdec        ; <A> -> text
  743.  
  744.     ld    hl,(dpb.cks)
  745.     call    wrddec        ; <HL> -> text
  746.  
  747.     ld    hl,(dpb.off)
  748.     call    wrddec        ; <HL> -> text
  749.  
  750.     ld    a,(vers.rel)
  751.     cp    31h
  752.     jp    nz,dec2
  753.  
  754.     ld    a,(dpb.psh)
  755.     call    bytdec        ; <A> -> text
  756.     ld    a,(dpb.phm)
  757.     call    bytdec        ; <A> -> text
  758.  
  759.     ret
  760.  
  761. dec2:    xor    a
  762.     call    bytdec        ; <A> -> text
  763.     xor    a
  764.     call    bytdec        ; <A> -> text
  765.     ret
  766.  
  767. errdec:            ; fill display with 3 asterisks as error
  768.     call    nextdec    ; <DE> -> leftmost digit
  769.     ld    a,'*'    ; set 1st 3 digits to '*'
  770.     ld    (de),a
  771.     dec    de
  772.     ld    (de),a
  773.     dec    de
  774.     ld    (de),a
  775.     ret
  776.  
  777.  
  778. bytdec:            ; display byte in A as decimal characters
  779.     ld    h,0
  780.     ld    l,a
  781.  
  782. wrddec:            ; display word in HL as decimal characters
  783.     ld    bc,0
  784.     jp    txtdec
  785.  
  786. megdec:            ; display byte,word in C & HL as decimal characters
  787.     ld    b,0
  788.  
  789. gigdec:            ; display double word in BC & HL as decimal characters
  790.  
  791.  
  792. txtdec:
  793.     ex    de,hl
  794.     push    de    ; save 4 bytes of binary number
  795.     push    bc
  796.     call    nextdec    ; <DE> -> leftmost digit
  797.     pop    bc
  798.     pop    de
  799.     call    tobcd    ; converts <B>, <C>, <D>, <E> into bcd at BCD
  800.     ld    hl,(posn)
  801.     ex    de,hl    ; recover <DE> -> leftmost digit
  802.     ld    a,'0'    ; initialise 1st digit to a zero
  803.     ld    (de),a    ; (just to make sure )
  804.  
  805.     ld    hl,bcdlsb    ; start with least significent digit
  806. txtdec1:
  807.     call    txtbcd
  808.     ret    z
  809.     dec    hl
  810.     jp    txtdec1    ; continue till all 10 digits done
  811.  
  812. txtbcd:            ; HL -> bcd digit, <DE> -> txt postion
  813.     call    zrobcd    ; zero when no more BCD digits (destroys <A>, <BC>)
  814.     ret    z
  815.     ld    a,(hl)
  816.     add    a,'0'
  817.     ld    (de),a
  818.     dec    de
  819.     xor    a
  820.     ld    (hl),a    ; zero BCD byte ESSENTIAL to exit when done
  821.     or    -1
  822.     ret
  823.  
  824. zrobcd:         ; test for all bytes of BCD being zero
  825.             ; this is important as eventually all bytes
  826.             ; will be set to zero during transfer to text
  827.     push    hl
  828.     ld    hl,bcd
  829.     xor    a
  830.     ld    b,10
  831. nxtzro:    or    (hl)
  832.     inc    hl
  833.     djnz    nxtzro
  834.     pop    hl
  835.     ret
  836.  
  837. ;----;
  838. tobcd:            ; print binary number 0-65535 from <HL>
  839. ;----;
  840.     ld    hl,binary
  841.     ld    (hl),e    ; least significant digit
  842.     inc    hl
  843.     ld    (hl),d
  844.     inc    hl
  845.     ld    (hl),c
  846.     inc    hl
  847.     ld    (hl),b    ; most significent digit
  848.  
  849.     push    bc
  850.     ld    hl,bcd
  851.     ld    b,10
  852.     xor    a
  853. setbcd:    ld    (hl),a
  854.     inc    hl
  855.     djnz    setbcd    ; first zero all digits
  856.     pop    bc
  857.  
  858.     ld    a,b
  859.     or    a
  860.     jp    nz,upgig
  861.  
  862.     ld    a,c
  863.     or    a
  864.     jp    nz,upmeg
  865.  
  866.     ld    a,d
  867.     or    a
  868.     jp    nz,upwrd
  869.  
  870.     ld    a,e
  871.     or    a
  872.     jp    nz,upbyt
  873.     ret            ; number is zero so return
  874.  
  875. upbyt:    ld    bc,bcdbyt    ; start of BCD pointer
  876.     ld    hl,byt10
  877.     jp    upnxt
  878.  
  879. upwrd:    ld    bc,bcdwrd    ; start of BCD pointer
  880.     ld    hl,wrd10
  881.     jp    upnxt
  882.  
  883. upmeg:    ld    bc,bcdmeg    ; start of BCD pointer
  884.     ld    hl,meg10
  885.     jp    upnxt
  886.  
  887. upgig:    ld    bc,bcdgig    ; start of BCD pointer
  888.     ld    hl,gig10
  889. ;
  890. upnxt:    ld    de,binary    ; binary number to be converted
  891.     push    bc        ; save BCD pointer
  892.     ld    c,-1
  893. pdecl:    push    hl
  894.     push    de
  895.     inc    c
  896.     xor    a
  897.     ld    b,4
  898. ndecl:    ld    a,(de)
  899.     adc    a,(hl)
  900.     ld    (de),a    ; and reduce count
  901.     inc    de
  902.     inc    hl
  903.     djnz    ndecl    ; this doesnt effect any flags
  904.     pop    de
  905.     pop    hl
  906.     jp    c,pdecl    ; repeatedly subtract amount till carry set
  907.     push    hl
  908.     push    de
  909.     xor    a
  910.     ld    b,4
  911. nincl:    ld    a,(de)
  912.     sbc    a,(hl)
  913.     ld    (de),a    ; and increase
  914.     inc    de
  915.     inc    hl
  916.     djnz    nincl    ; this doesnt effect any flags
  917.     pop    de
  918.     inc    sp
  919.     inc    sp    ; loose <HL> (digits) saved on stack
  920.     ld    a,c
  921.     pop    bc    ; pointer to BCD
  922.     ld    (bc),a
  923.     inc    bc
  924.     ld    a,(hl)
  925.     or    a
  926.     jp    nz,upnxt
  927.  
  928.     ret
  929.  
  930.     dseg
  931.  
  932. bcd:            ; 10 bytes, 10 digits of BCD text
  933. bcdgig:            ; max number is 4294967295
  934. bcd.0:    db    4
  935. bcd.1:    db    2
  936. bcdmeg:            ; max number is 16777215
  937. bcd.2:    db    9
  938. bcd.3:    db    4
  939. bcd.4:    db    9
  940. bcdwrd:            ; max number is 65535
  941. bcd.5:    db    6
  942. bcd.6:    db    7
  943. bcdbyt:            ; max number is 255
  944. bcd.7:    db    2
  945. bcd.8:    db    9
  946. bcdlsb:
  947. bcd.9:    db    5
  948.  
  949. gig10:    dw     13824,-15259    ; -1000000000 (C465 3600H)
  950.     dw      7936, -1526    ;  -100000000 (FA0A 1F00H)
  951. meg10:    dw     27008,  -153    ;   -10000000 (FF67 6980H)
  952.     dw    -16960,   -16    ;    -1000000 (FFF0 BDC0H)
  953.     dw     31072,    -2    ;     -100000 (FFFE 7960H)
  954. wrd10:    dw    -10000,    -1    ;      -10000 (FFFF D8F0H)
  955.     dw     -1000,    -1    ;       -1000 (FFFF FC18H)
  956. byt10:    dw      -100,    -1    ;        -100 (FFFF FF9CH)
  957.     dw       -10,    -1    ;         -10 (FFFF FFF6H)
  958.     dw        -1,    -1    ;          -1 (FFFF FFFFH)
  959.     dw         0,     0    ;           0 (0000 0000H) this terminates all
  960.  
  961. binary:    db    0,0,0,0    ; binary number filled from E, D, C, & B
  962.  
  963.     cseg
  964.  
  965. testdec:
  966.     cp    cr
  967.     ret    z    
  968. nextdec:        ; find next dec location in text and convert to space
  969.             ; and return DE -> to end of 00h string
  970.  
  971.     call    decchr    ; find first dec character
  972.     jp    nz,testdec
  973. nxt3:    ld    a,' '    ; erase each digit as we go
  974.     ld    (de),a
  975.     call    decchr    ; scan subsequent dec characters
  976.     jp    z,nxt3
  977.     dec    de
  978.     ld    a,'0'
  979.     ld    (de),a    ; initialise 1st digit to a zero
  980.     ex    de,hl
  981.     ld    (posn),hl
  982.     ret
  983.  
  984. decchr:    ld    hl,(posn)
  985.     inc    hl
  986.     ld    a,(hl)
  987.     ld    d,h
  988.     ld    e,l
  989.     cp    cr
  990.     ret    z    
  991.     ld    (posn),hl
  992.     ld    hl,dectxt
  993.     ld    b,11
  994. nxt2:    cp    (hl)
  995.     ret    z
  996.     inc    hl
  997.     djnz    nxt2
  998.     or    -1
  999.     ret
  1000.     dseg
  1001. dectxt:    db    '0123456789+*'    ; + used for bit flag, * used for errors
  1002.     cseg
  1003.  
  1004. ;------;
  1005. makemax:        ; module in showblk
  1006. ;------;
  1007.  
  1008. ;'          BLOCK       EXTENT      MAX DISK    DIRECTORY   CHECK SUM   SECTOR'
  1009. ;'          SIZE (K)    FOLDS       SIZE (K)    ENTRIES     ENTRIES     SIZE'
  1010. ;'DPB(DEC):  16K          15        1048576      65536       65536      32768'
  1011.  
  1012.     ld    hl,sdbmax
  1013.     ld    (posn),hl
  1014.  
  1015.     ld    a,(dpb.bsh)
  1016.     ld    hl,128
  1017.     or    a
  1018.     jp    z,makem2
  1019. makem1:    add    hl,hl
  1020.     dec    a
  1021.     jp    nz,makem1
  1022. makem2:    ld    a,h        ; /256
  1023.     rrca            ; /512
  1024.     rrca            ; /1024
  1025.     push    af
  1026.     ld    a,(dpb.blm)
  1027.     ld    bc,-128
  1028.     or    a
  1029.     jp    z,makem4
  1030. makem3:    add    hl,bc
  1031.     dec    a
  1032.     jp    nz,makem3
  1033. makem4:    add    hl,bc
  1034.     pop    af        ; recover K
  1035.     ld    b,a        ; and save
  1036.     ld    a,h
  1037.     or    l
  1038.     ld    a,b
  1039.     push    af
  1040.     call    nz,errdec
  1041.     pop    af
  1042.     call    z,bytdec    ; <A> -> text
  1043.  
  1044.     ld    a,(dpb.blm)
  1045.     add    a,1    ;+1
  1046.     rra
  1047.     rra
  1048.     rra        ;/8
  1049.     ld    b,a    ; save EXM+1
  1050.     ld    hl,(dpb.dsm)
  1051.     xor    a    ; (there must be an easier way)
  1052.     sub    h
  1053.     dec    a
  1054.     ccf
  1055.     adc    a,h    ; a = 0 if H = 0, else a = -1
  1056.     and    b
  1057.     add    a,b
  1058.     add    a,-1    ;-1  (convert into EXM)
  1059.     ld    b,a    ; and save    
  1060.  
  1061.     ld    a,(dpb.exm)
  1062.     cp    b
  1063.     push    af
  1064.     call    nz,errdec
  1065.     pop    af
  1066.     call    z,bytdec    ; <A> -> text
  1067.  
  1068.     xor    a
  1069.     ld    hl,(dpb.dsm)
  1070.     ld    bc,1
  1071.     add    hl,bc        ; increment dsm by 1
  1072.     adc    a,0
  1073.     ld    c,a        ; and save in C
  1074.     ld    a,(dpb.bsh)
  1075.     add    a,-3
  1076.     ld    b,a
  1077.     or    a
  1078.     ld    a,c        ; giga byte
  1079.     jp    z,makem6
  1080. makem5:    add    hl,hl
  1081.     adc    a,0
  1082.     djnz    makem5
  1083. makem6:    ld    c,a
  1084.     call    megdec        ; <C> & <HL> -> text
  1085.  
  1086.     xor    a
  1087.     ld    hl,(dpb.drm)
  1088.     ld    bc,1
  1089.     add    hl,bc        ; increment drm by 1
  1090.     adc    a,0
  1091.     ld    c,a
  1092.     call    megdec        ; <C> & <HL> -> text
  1093.  
  1094.     ld    hl,(dpb.drm)
  1095.     ld    a,h
  1096.     and    a
  1097.     rra
  1098.     ld    h,a
  1099.     ld    a,l
  1100.     rra
  1101.     ld    l,a    ; /2
  1102.     ld    a,h
  1103.     and    a
  1104.     rra
  1105.     ld    h,a
  1106.     ld    a,l
  1107.     rra
  1108.     ld    l,a    ; /4
  1109.     ld    d,h
  1110.     ld    e,l
  1111.     inc    de    ; DE=HL+1
  1112.  
  1113.     ld    hl,(dpb.cks)
  1114.     ld    a,h
  1115.     or    l
  1116.     jp    z,makem8    ; no check sum
  1117.     ld    a,h
  1118.     and    7fh
  1119.     or    l
  1120.     jp    z,makem7    ; bit 15 set for non removable
  1121.     sbc    hl,de
  1122.     ex    de,hl
  1123.     jp    z,makem8
  1124.     call    errdec
  1125.     jp    makem9
  1126. makem8:    ld    c,0
  1127.     call    mmegx4        ; <C>, <HL> * 4
  1128.     call    megdec        ; <C> & <HL> -> text
  1129.     jp    makem9
  1130. makem7: xor    a
  1131.     call    nextdec
  1132.     dec    de
  1133.     ld    a,'+'
  1134.     ld    (de),a
  1135.     inc    de
  1136.     inc    de
  1137. makem9:
  1138.  
  1139.     ld    a,(vers.rel)
  1140.     cp    31h
  1141.     jp    nz,makem0
  1142.  
  1143.     ld    a,(dpb.psh)
  1144.     ld    hl,128
  1145.     or    a
  1146.     jp    z,make02
  1147. make01:    add    hl,hl
  1148.     dec    a
  1149.     jp    nz,make01
  1150. make02:    push    hl
  1151.     ld    a,(dpb.phm)
  1152.     ld    bc,-128
  1153.     or    a
  1154.     jp    z,make04
  1155. make03:    add    hl,bc
  1156.     dec    a
  1157.     jp    nz,make03
  1158. make04:    add    hl,bc
  1159.     ld    a,h
  1160.     or    l
  1161.     pop    hl
  1162.     push    af
  1163.     call    nz,errdec
  1164.     pop    af
  1165.     call    z,wrddec    ; <HL> -> text
  1166.  
  1167.     ret
  1168.  
  1169. makem0:    ld    hl,128        ; CP/M 2 sector size
  1170.     call    wrddec        ; <HL> -> text
  1171.     ret
  1172.  
  1173.  
  1174. ;--------;
  1175. makedir:        ; module in showblk
  1176. ;--------;
  1177.  
  1178. ;'                             Data       1K    128 byte  '
  1179. ;'                            Blocks    Blocks   Records    Capacity'
  1180. ;'              Directory      65535  16777215  16777215    16777215 Entries'
  1181. ;'              Data           65535  16777215  16777215  4294967296 Bytes'
  1182. ;'                             65000  16777215  16777215'
  1183.  
  1184.     dseg
  1185. dirdb:    db    0    ; save number of director blocks
  1186. dbsize:    db    0    ; save data block size in K
  1187.     cseg
  1188.  
  1189.     ld    hl,sdbdir
  1190.     ld    (posn),hl
  1191.  
  1192.     ld    hl,(dpb.al0)
  1193.     xor    a
  1194.     ld    b,16
  1195. maked0:    add    hl,hl
  1196.     adc    a,0
  1197.     djnz    maked0    ; number of directory data blocks
  1198.     ld    (dirdb),a
  1199.  
  1200.     call    bytdec        ; <A> -> text
  1201.  
  1202.     ld    a,(dpb.bsh)
  1203.     ld    hl,128
  1204.     or    a
  1205.     jp    z,maked2
  1206. maked1:    add    hl,hl
  1207.     dec    a
  1208.     jp    nz,maked1
  1209. maked2:    ld    a,h        ; /256
  1210.     rrca            ; /512
  1211.     rrca            ; /1024
  1212.     ld    (dbsize),a    ; save data block size in K
  1213.  
  1214.     ld    c,a
  1215.     ld    b,0
  1216.     ld    a,(dirdb)
  1217.     ld    hl,0
  1218.     or    a
  1219.     jp    z,maked4
  1220. maked3:    add    hl,bc
  1221.     dec    a
  1222.     jp    nz,maked3
  1223. maked4:    push    hl
  1224.     call    wrddec        ; <HL> -> text
  1225.     pop    hl
  1226.  
  1227.     ld    c,0
  1228.     call    mmegx8        ; multiply by 8
  1229.  
  1230.     push    hl
  1231.     push    bc
  1232.     call    megdec    ; number of records (<C> & <HL> -> text)
  1233.     pop    bc
  1234.     pop    hl
  1235.  
  1236.     call    mmegX4    ; multiply by 4
  1237.     call    megdec    ; number of entries (<C> & <HL> -> text)
  1238.     ret
  1239.  
  1240. ;--------;
  1241. makedat:        ; module in showblk
  1242. ;--------;
  1243.  
  1244. ;'                             Data       1K    128 byte  '
  1245. ;'                            Blocks    Blocks   Records    Capacity'
  1246. ;'              Directory      65535  16777215  16777215    16777215 Entries'
  1247. ;'              Data           65535  16777215  16777215  4294967296 Bytes'
  1248. ;'                             65000  16777215  16777215'
  1249.  
  1250.     ld    hl,sdbdat
  1251.     ld    (posn),hl
  1252.  
  1253.     ld    hl,(dpb.dsm)    ; total disk blocks
  1254.     ld    a,(dirdb)    ; blocks reserved for directory
  1255.     dec    a
  1256.     ld    c,a
  1257.     ld    b,0
  1258.     sbc    hl,bc        ; leaving number of data blocks
  1259.     push    hl
  1260.     call    wrddec        ; <HL> -> text
  1261.     pop    hl
  1262.  
  1263.     xor    a
  1264.     ld    b,a
  1265.     ld    c,a    ; BC = 0
  1266.  
  1267.     ld    a,(dpb.blm)
  1268.     inc    a
  1269.     rrca
  1270.     rrca
  1271.     rrca        ; /8
  1272.     dec    a
  1273.     or    a
  1274.     jp    z,maked6
  1275. maked5:    push    af
  1276.     call    mgigx2
  1277.     pop    af
  1278.     dec    a
  1279.     jp    nz,maked5
  1280. maked6:    push    bc
  1281.     push    hl
  1282.     call    gigdec    ; 1K blocks (<BC> & <HL> -> text)
  1283.     pop    hl
  1284.     pop    bc
  1285.     call    mgigx8    ; multiply B,C,H,& L by 8
  1286.  
  1287.     push    hl
  1288.     push    bc
  1289.     call    gigdec    ; number of records (<BC> & <HL> -> text)
  1290.     pop    bc
  1291.     pop    hl
  1292.     
  1293.     call    mgigx128    ; multiply B,C,H,& L by 128
  1294.     call    gigdec    ; number of bytes (<BC> & <HL> -> text)
  1295.  
  1296.     ret
  1297.  
  1298. ;--------;
  1299. maketot:        ; module in showblk
  1300. ;--------;
  1301.  
  1302. ;'                             Data       1K    128 byte  '
  1303. ;'                            Blocks    Blocks   Records    Capacity'
  1304. ;'              Directory      65535  16777215  16777215    16777215 Entries'
  1305. ;'              Data           65535  16777215  16777215  4294967296 Bytes'
  1306. ;'                             65000  16777215  16777215'
  1307.  
  1308.     ld    hl,sdbtot
  1309.     ld    (posn),hl
  1310.  
  1311.     xor    a
  1312.     ld    bc,1
  1313.     ld    hl,(dpb.dsm)    ; total disk blocks
  1314.     add    hl,bc
  1315.     adc    a,a
  1316.     ld    c,a
  1317.  
  1318.     push    bc
  1319.     push    hl
  1320.     call    wrddec        ; <HL> -> text
  1321.     pop    hl
  1322.     pop    bc
  1323.  
  1324.     ld    a,(dpb.blm)
  1325.     inc    a
  1326.     rrca
  1327.     rrca
  1328.     rrca        ; /8
  1329.     dec    a
  1330.     or    a
  1331.     jp    z,maked8
  1332. maked7:    push    af
  1333.     call    mgigx2
  1334.     pop    af
  1335.     dec    a
  1336.     jp    nz,maked7
  1337. maked8:    push    bc
  1338.     push    hl
  1339.     call    gigdec    ; 1K blocks (<BC> & <HL> -> text)
  1340.     pop    hl
  1341.     pop    bc
  1342.  
  1343.     call    mgigx8    ; multiply B,C,H,& L by 8
  1344.     call    gigdec    ; number of records (<BC> & <HL> -> text)
  1345.     
  1346.     ret
  1347.  
  1348. mmegx8:    call    mmegx2    ; multiply C,H,& L by 8
  1349. mmegx4:    call    mmegx2    ; multiply C,H,& L by 4
  1350. mmegx2:    ld    a,l    ; multiply C,H,& L by 2
  1351.     add    a,a
  1352.     ld    l,a
  1353.     ld    a,h
  1354.     adc    a,a
  1355.     ld    h,a
  1356.     ld    a,c
  1357.     adc    a,a
  1358.     ld    c,a
  1359.     ret
  1360.  
  1361. mgigx8:    call    mgigx2    ; multiply B,C,H,& L by 8
  1362. mgigx4:    call    mgigx2    ; multiply B,C,H,& L by 4
  1363. mgigx2:    ld    a,l    ; multiply B,C,H,& L by 2
  1364.     add    a,a
  1365.     ld    l,a
  1366.     ld    a,h
  1367.     adc    a,a
  1368.     ld    h,a
  1369.     ld    a,c
  1370.     adc    a,a
  1371.     ld    c,a
  1372.     ld    a,b
  1373.     adc    a,a
  1374.     ld    b,a
  1375.     ret
  1376.  
  1377. mgigx128:        ; multipy B,C,H,& L by 128
  1378.     ld    a,b
  1379.     and    a
  1380.     rra        ; we can only use lowest bit
  1381.     ld    a,c
  1382.     rra
  1383.     ld    b,a
  1384.     ld    a,h
  1385.     rra
  1386.     ld    c,a
  1387.     ld    a,l
  1388.     rra
  1389.     ld    h,a
  1390.     ld    a,0
  1391.     rra
  1392.     ld    l,a
  1393.     ret
  1394.  
  1395.  
  1396.  
  1397. ;------;
  1398. showblk:    ; menu 1 option 1    Display DPB statistics
  1399. ;------;
  1400.     ld    a,(def.dsk)
  1401.     add    a,'A'
  1402.     ld    (sdbdsk),a
  1403.  
  1404.     call    makehex
  1405.  
  1406.     call    makedec
  1407.  
  1408.     call    makemax
  1409.  
  1410.     call    makedir
  1411.  
  1412.     call    makedat
  1413.  
  1414.     call    maketot
  1415.  
  1416.  
  1417.     ld    de,sdbmsg
  1418.     ld    c,9        ;BDOS: PRINT STRING
  1419.     call    bdos
  1420.  
  1421.     call    waitcr
  1422.  
  1423.     ret
  1424.  
  1425.     dseg
  1426. sdbmsg:
  1427.     db    cr,   '                         DRIVE '
  1428. sdbdsk:    db    'A: DISC PARAMETER BLOCK'
  1429.     db    cr,lf
  1430.     db    cr,lf,'         '
  1431.     db    '   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16 '
  1432.     db    cr,lf,'DPB:     '
  1433. sdbbyt:    db    '  00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h'
  1434.     db    cr,lf
  1435.     db    cr,lf,'         '
  1436.     db    '     SPT  BSH BLM EXM    DSM     DRM  AL0-AL1    CKS     OFF  PSH PHM'
  1437.     db    cr,lf,'DPB(HEX):'
  1438. sdbhex:    db    '    0000h 00h 00h 00h   0000h   0000h 00h 00h   0000h   0000h 00h 00h'
  1439.     db    cr,lf,'DPB(DEC):'
  1440. sdbdec:    db    '   65535  255 255 255  65535   65535  255 255  65535   65535  255 255'
  1441.     db    cr,lf
  1442.     db    cr,lf,'          BLOCK       EXTENT      MAX DISK    DIRECTORY   CHECK SUM   SECTOR'
  1443.     db    cr,lf,'          '
  1444.     db    'SIZE (K)    FOLDS       SIZE (K)    ENTRIES     ENTRIES     SIZE'
  1445.     db    cr,lf,'DPB(DEC): '
  1446. sdbmax:    db    ' 16K          15        1048576      65536       65536      32768'
  1447. sdberr:    db    cr,lf,'                                                                            '
  1448.     db    cr,lf
  1449.     db    cr,lf,'ALLOCATION OF DISK BLOCKS'
  1450.     db    cr,lf,'                             Data       1K    128 byte  '
  1451.     db    cr,lf,'                            Blocks    Blocks   Records    Capacity'
  1452.     db    lf
  1453. sdbdir:    db    cr,lf,'              Directory      65535  16777215  16777215    16777215 Entries'
  1454. sdbdat:    db    cr,lf,'              Data           65535  16777215  16777215  4294967296 Bytes'
  1455.     db    cr,lf,'                          --------  --------  --------'
  1456. sdbtot:    db    cr,lf,'                             65000  16777215  16777215'
  1457.     db    lf
  1458.     db    '$'
  1459.     cseg
  1460.  
  1461. ;------;
  1462. makedph3:    ; menu 1 option 2    Display DPH statistics
  1463. ;------;
  1464.  
  1465. ;    '   0   1   2   3   4   5   6   7   8   9  10  11  '
  1466. ;s3byt1    '  00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
  1467. ;    '  12  13  14  15  16  17  18  19  20  21  22  23  24  '
  1468. ;s3byt2    '  00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
  1469. ;    '  XLT     -0- -0- -0- -0- -0- -0- -0- -0- -0- MF  '
  1470. ;s3hex1    '  0000h   00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
  1471. ;    '  DPB     CSV     ALV     DIRBCB  DTABCB  HASH    HBANK'
  1472. ;s3hex2    '  0000h   0000h   0000h   0000h   0000h   0000h   00h '
  1473.  
  1474.     ld    hl,s3byt1
  1475.     ld    (posn),hl
  1476.  
  1477.     ld    hl,dph3
  1478.     ld    b,12
  1479.     call    hexbyt
  1480.  
  1481.     push    hl
  1482.     ld    hl,s3byt2
  1483.     ld    (posn),hl
  1484.     pop    hl
  1485.  
  1486.     ld    b,13
  1487.     call    hexbyt
  1488.  
  1489.     ld    hl,s3hex1
  1490.     ld    (posn),hl
  1491.  
  1492.     ld    hl,dph3
  1493.     ld    de,h3type
  1494.     ld    b,12
  1495.     call    hextbl
  1496.  
  1497.  
  1498.     push    hl
  1499.     ld    hl,s3hex2
  1500.     ld    (posn),hl
  1501.     pop    hl
  1502.  
  1503.     ld    b,13
  1504.     call    hextbl
  1505.  
  1506.     ret
  1507.  
  1508.  
  1509.     dseg
  1510. h3type:    db    2,1,1,1,1,1,1,1,1,1,1
  1511.     db    2,2,2,2,2,2,1
  1512.     cseg
  1513.  
  1514.  
  1515. ;------;
  1516. makedph2:    ; menu 1 option 2    Display DPH statistics
  1517. ;------;
  1518.  
  1519. ;    '   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  '
  1520. ;s2byt    '  00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
  1521. ;    '  XLT     -0- -0- -0- -0- -0- -0- DIRBCB  DPB     CSV     ALV     '
  1522. ;s2hex    '  0000h   00h 00h 00h 00h 00h 00h 0000h   0000h   0000h   0000h   '
  1523.  
  1524.     ld    hl,s2byt
  1525.     ld    (posn),hl
  1526.  
  1527.     ld    hl,dph2
  1528.     ld    b,16
  1529.     call    hexbyt
  1530.  
  1531.     ld    hl,s2hex
  1532.     ld    (posn),hl
  1533.  
  1534.     ld    hl,dph2
  1535.     ld    de,h2type
  1536.     ld    b,16
  1537.     call    hextbl
  1538.  
  1539.     ret
  1540.  
  1541.  
  1542.     dseg
  1543. h2type:    db    2,1,1,1,1,1,1,2,2,2,2    ; 11 fields
  1544.     cseg
  1545.  
  1546.  
  1547.     ret
  1548.  
  1549. ;------;
  1550. showhdr:    ; menu 1 option 2    Display DPH statistics
  1551. ;------;
  1552.  
  1553.     ld    a,(vers.rel)
  1554.     cp    31h
  1555.     call    z,outdph3
  1556.  
  1557.     ld    a,(vers.rel)
  1558.     cp    22h
  1559.     call    z,outdph2
  1560.  
  1561.     ret
  1562.  
  1563. ;------;
  1564. outdph3:    ; menu 1 option 2    Display DPH statistics
  1565. ;------;
  1566.  
  1567.     ld    a,(def.dsk)
  1568.     add    a,'A'
  1569.     ld    (sh3dsk),a
  1570.  
  1571.     call    makedph3
  1572.  
  1573.     ld    de,sh3msg
  1574.     ld    c,9        ;BDOS: PRINT STRING
  1575.     call    bdos
  1576.  
  1577.     call    waitcr
  1578.  
  1579.     ret
  1580.  
  1581.  
  1582.     dseg
  1583. sh3msg:    db    cr,'                     DRIVE '
  1584. sh3dsk:    db    'A: DISK PARAMETER HEADER'
  1585.     db    cr,lf
  1586.     db    cr,lf,'         '
  1587.     db    '   0   1   2   3   4   5   6   7   8   9  10  11  '
  1588.     db    cr,lf,'DPH(HEX):'
  1589. s3byt1:    db    '  00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
  1590.     db    cr,lf
  1591.     db    cr,lf,'         '
  1592.     db    '  12  13  14  15  16  17  18  19  20  21  22  23  24  '
  1593.     db    cr,lf,'DPH(HEX):'
  1594. s3byt2:    db    '  00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
  1595.     db    cr,lf
  1596.     db    cr,lf,'         '
  1597.     db    '  XLT     -0- -0- -0- -0- -0- -0- -0- -0- -0- MF  '
  1598.     db    cr,lf,'DPH(HEX):'
  1599. s3hex1:    db    '  0000h   00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
  1600.     db    cr,lf
  1601.     db    cr,lf,'         '
  1602.     db    '  DPB     CSV     ALV     DIRBCB  DTABCB  HASH    HBANK'
  1603.     db    cr,lf,'DPH(HEX):'
  1604. s3hex2:    db    '  0000h   0000h   0000h   0000h   0000h   0000h   00h '
  1605.     db    cr,lf
  1606.     db    lf,lf,lf,lf,lf,lf,lf,lf
  1607.     db    '$'
  1608.  
  1609.     cseg
  1610.  
  1611. ;------;
  1612. outdph2:    ; menu 1 option 2    Display DPH statistics
  1613. ;------;
  1614.  
  1615.     ld    a,(def.dsk)
  1616.     add    a,'A'
  1617.     ld    (sh2dsk),a
  1618.  
  1619.     call    makedph2
  1620.  
  1621.     ld    de,sh2msg
  1622.     ld    c,9        ;BDOS: PRINT STRING
  1623.     call    bdos
  1624.  
  1625.     call    waitcr
  1626.  
  1627.     ret
  1628.  
  1629.  
  1630.     dseg
  1631. sh2msg:    db    cr,'                     DRIVE '
  1632. sh2dsk:    db    'A: DISK PARAMETER HEADER'
  1633.     db    cr,lf
  1634.     db    cr,lf,'         '
  1635.     db    '   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  '
  1636.     db    cr,lf,'DPH(HEX):'
  1637. s2byt:    db    '  00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h '
  1638.     db    cr,lf
  1639.     db    cr,lf,'         '
  1640.     db    '  XLT     -0- -0- -0- -0- -0- -0- DIRBCB  DPB     CSV     ALV     '
  1641.     db    cr,lf,'DPH(HEX):'
  1642. s2hex:    db    '  0000h   00h 00h 00h 00h 00h 00h 0000h   0000h   0000h   0000h   '
  1643.     db    cr,lf,lf,lf,lf,lf,lf,lf
  1644.     db    lf,lf,lf,lf,lf,lf,lf,lf
  1645.     db    '$'
  1646.  
  1647.     cseg
  1648.  
  1649.     page
  1650.  
  1651. ; -------------------------------------------- ;
  1652. ; utilities used in allocation vector analysis ;
  1653. ; -------------------------------------------- ;
  1654.  
  1655.     dseg
  1656. lenalv:    ds    2    ; length of allocation vector in bytes
  1657. alvdir:    ds    2    ; datablocks allocated to directory
  1658. alvdat:    ds    2    ; datablocks allocated to data
  1659. alvzro:    ds    2    ; datablocks not allocated
  1660. alvera:    ds    2    ; datablocks allocated to erased data
  1661. alvlst:    ds    2    ; datablocks allocated to overwritten data
  1662. alvbad:    ds    2    ; datablocks with duplicated data access
  1663. alvrng:    ds    2    ; datablocks outside maximum number
  1664. alvlen    equ    $-lenalv
  1665. user:    db    0    ; save user number
  1666.     cseg
  1667.  
  1668. ;--;
  1669. alv:        ; return <HL> = <HL>/8, & <C> = <HL> mod 7
  1670. ;--;
  1671.     ld    c,0
  1672.     call    alv1        ; /2
  1673.     call    alv1        ; /4
  1674.     call    alv1        ; /8
  1675.     ld    a,c
  1676.     rlca
  1677.     rlca
  1678.     rlca
  1679.     ld    c,a
  1680.     ret
  1681.  
  1682. alv1:    ld    a,h
  1683.     and    a
  1684.     rra
  1685.     ld    h,a
  1686.     ld    a,l
  1687.     rra
  1688.     ld    l,a        ; <HL> = <HL> / 2
  1689.     ld    a,c
  1690.     rra
  1691.     ld    c,a        ; C contains lost bits
  1692.     ret
  1693.  
  1694. tstbit:            ; tst bit number <C> at offset <HL> from ALLOC
  1695.             ; return CF=NZ if bit already set
  1696.  
  1697.     push    bc
  1698.     push    hl
  1699.     ld    hl,bitmap
  1700.     ld    b,0
  1701.     add    hl,bc
  1702.     ld    a,(hl)    ; bit to set
  1703.     ld    bc,alloc
  1704.     pop    hl
  1705.     push    hl
  1706.     add    hl,bc
  1707.     ld    b,a    ; save bit to set
  1708.     ld    a,(hl)
  1709.     and    b    ; test if bit set
  1710.     pop    hl
  1711.     pop    bc
  1712.     ret        ; 0 = if not set, > 0 if set
  1713.  
  1714. setbit:            ; set bit number <C> at offset <HL> from ALLOC
  1715.             ; return CF=NZ if bit already set
  1716.  
  1717.     push    bc
  1718.     push    hl
  1719.     ld    hl,bitmap
  1720.     ld    b,0
  1721.     add    hl,bc
  1722.     ld    a,(hl)    ; bit to set
  1723.     ld    bc,alloc
  1724.     pop    hl
  1725.     push    hl
  1726.     add    hl,bc
  1727.     ld    b,a    ; save bit to set
  1728.     ld    a,(hl)
  1729.     ld    c,a    ; save byte before setting bit
  1730.     or    b
  1731.     ld    (hl),a    ; set bit
  1732.     ld    a,c
  1733.     and    b    ; test if bit set
  1734.     pop    hl
  1735.     pop    bc
  1736.     ret        ; 0 = if not set, > 0 if set
  1737.  
  1738.  
  1739.  
  1740. bitmap:    db    10000000b    ;0
  1741.     db    01000000b    ;1
  1742.     db    00100000b    ;2
  1743.     db    00010000b    ;3
  1744.     db    00001000b    ;4
  1745.     db    00000100b    ;5
  1746.     db    00000010b    ;6
  1747.     db    00000001b    ;7
  1748.  
  1749. updat:
  1750.     jp    nz,errbit    ; bit already set
  1751.     push    hl
  1752.     ld    hl,(alvdat)
  1753.     inc    hl
  1754.     ld    (alvdat),hl    ; increment count of data
  1755.     pop    hl
  1756.     ret
  1757.  
  1758.  
  1759. errbit:            ; flag bit already set
  1760.     push    hl
  1761.     ld    hl,(alvbad)
  1762.     inc    hl
  1763.     ld    (alvbad),hl    ; increment count of duplicate data
  1764.     pop    hl
  1765.     ret
  1766.  
  1767. upera:
  1768.     jp    nz,lstbit    ; bit already set
  1769.     push    hl
  1770.     ld    hl,(alvera)
  1771.     inc    hl
  1772.     ld    (alvera),hl    ; increment count of erased data
  1773.     pop    hl
  1774.     ret
  1775.  
  1776. lstbit:
  1777.     push    hl
  1778.     ld    hl,(alvlst)
  1779.     inc    hl
  1780.     ld    (alvlst),hl    ; increment count of overwritten data
  1781.     pop    hl
  1782.     ret
  1783.  
  1784. uprng:
  1785.     push    hl
  1786.     ld    hl,(alvrng)
  1787.     inc    hl
  1788.     ld    (alvrng),hl    ; increment count of blocks outside range
  1789.     pop    hl
  1790.     ret
  1791.  
  1792. ;------;
  1793. showalv:    ; menu 1 option 3    Display disk ALLOCATION
  1794. ;------;
  1795.     ld    a,(def.dsk)
  1796.     add    a,'A'
  1797.     ld    (saldsk),a
  1798.  
  1799.     ld    hl,lenalv    ; start of datablock counts
  1800.     ld    d,h
  1801.     ld    e,l
  1802.     inc    de
  1803.     ld    bc,alvlen-1    ; length of datablock counts
  1804.     ld    (hl),0
  1805.     ldir            ; and zero all
  1806.  
  1807.     ld    hl,(dpb.dsm)    ; number of data blocks less 1
  1808.     call    alv        ; return <HL> = <HL>/8, & <C> = <HL> mod 7
  1809.  
  1810.     inc    hl
  1811.     ld    (lenalv),hl    ; length of ALV in bytes
  1812.     ld    de,alloc    ; start of ALV
  1813.     add    hl,de        ; end of ALV
  1814.  
  1815.     ex    de,hl
  1816.     ld    hl,(BDOS+1)    ; base of BDOS
  1817.     dec    hl
  1818.     and    a
  1819.     sbc    hl,de        ; <HL> = top of TPA - top of ALLOC
  1820.     jp    nc,alvok
  1821.  
  1822.     ld    de,alverr
  1823.     ld    c,9        ;BDOS: PRINT STRING
  1824.     call    bdos
  1825.  
  1826.     jp    waitcr        ; wait for <RETURN> then return
  1827.  
  1828.     dseg
  1829. alverr:    db    cr,lf,'TPA too small for allocation vector','$'
  1830.     cseg
  1831.  
  1832. ; ---------------------------- ;
  1833. ; initialise allocation vector ;
  1834. ; ---------------------------- ;
  1835.  
  1836. alvok:    ld    hl,(lenalv)
  1837.     ld    b,h
  1838.     ld    c,l
  1839.     ld    hl,alloc
  1840.     ld    d,h
  1841.     ld    e,l
  1842.     inc    de
  1843.     dec    bc
  1844.     ld    (hl),0
  1845.     ldir            ; set allocation vector to 0
  1846.  
  1847.     ld    hl,(dpb.al0)    ; directory ALV0 and ALV1
  1848.     ld    (alloc),hl    ; and fill alloc bits with these
  1849.  
  1850. ; ----------------------- ;
  1851. ; count directory entries ;
  1852. ; ----------------------- ;
  1853.  
  1854.     ld    b,16
  1855.     ld    de,0
  1856. cntalv:    add    hl,hl
  1857.     jp    nc,nocnt
  1858.     inc    de
  1859. nocnt:    djnz    cntalv
  1860.     ex    de,hl
  1861.     ld    (alvdir),hl    ; number of directory entries
  1862.  
  1863. ; -------------- ;
  1864. ; scan directory ;
  1865. ; -------------- ;
  1866.  
  1867.     ld    de,deffcb
  1868.     ld    a,'?'
  1869.     ld    (de),a
  1870.     ld    c,17        ;BDOS: SEARCH FOR FIRST
  1871.     call    bdos
  1872.  
  1873. nextdir:
  1874.     cp    -1
  1875.     jp    z,doera
  1876.     ld    l,a
  1877.     ld    h,0
  1878.     add    hl,hl
  1879.     add    hl,hl
  1880.     add    hl,hl
  1881.     add    hl,hl
  1882.     add    hl,hl
  1883.     ld    de,defdma
  1884.     add    hl,de
  1885.     ld    a,(hl)
  1886.     and    not 00011111b    ; test for high bits set
  1887.     jp    nz,nxtdcb
  1888.  
  1889.     ld    de,16
  1890.     add    hl,de
  1891.     ex    de,hl        ; <DE> -> first data block allocation
  1892.     ld    hl,(dpb.dsm)
  1893.     ld    a,h
  1894.     or    a
  1895.     jp    nz,wrdalv
  1896.  
  1897. ; test 16 file data block bytes
  1898.     ld    b,16        ; byte wide data blocks
  1899. nxtdb:    push    hl
  1900.     ld    a,(de)
  1901.     or    a
  1902.     jp    z,nuldb
  1903.     cp    l        ; check range
  1904.     jp    z,updb
  1905.     jp    nc,errdb
  1906. updb:    ld    l,a
  1907.     ld    h,0
  1908.     call    alv        ; return <HL> = <HL>/8, <C>=MOD(<HL>,7)
  1909.     call    setbit        ; returns CF=NZ if bit already set
  1910.     call    updat
  1911.     jp    nuldb
  1912. errdb:    call    uprng        ; data block outside range
  1913. nuldb:    pop    hl        ; recover DSM
  1914.     inc    de        ; increment to next data block allocation
  1915.     djnz    nxtdb
  1916.     jp    nxtdcb
  1917.  
  1918. ; test 8 file data block words
  1919. wrdalv:
  1920.     ex    de,hl        ; move back to HL
  1921.     ld    b,8
  1922. nxtdw:    push    hl
  1923.     ld    e,(hl)
  1924.     inc    hl
  1925.     ld    d,(hl)
  1926.     ld    a,e
  1927.     or    d
  1928.     jp    z,nuldw
  1929.     ld    hl,(dpb.dsm)
  1930.     xor    a
  1931.     sbc    hl,de
  1932.     jp    c,errdw
  1933.     ex    de,hl
  1934.     call    alv        ; return <HL> = <HL>/8, <C>=MOD(<HL>,7)
  1935.     call    setbit        ; returns CF=NZ if bit already set
  1936.     call    updat
  1937.     jp    nuldw
  1938. errdw:    call    uprng        ; data block outside range
  1939. nuldw:    pop    hl        ; recover data block pointer
  1940.     inc    hl
  1941.     inc    hl        ; increment to next data block allocation
  1942.     djnz    nxtdw
  1943.     jp    nxtdcb
  1944.  
  1945. nxtdcb:
  1946.     ld    de,deffcb
  1947.     xor    a
  1948.     ld    (de),a        ; set default drive
  1949.     ld    c,18        ;BDOS: SEARCH FOR NEXT
  1950.     call    bdos
  1951.     jp    nextdir
  1952.  
  1953. ; -------------- ;
  1954. ; scan era files ;
  1955. ; -------------- ;
  1956.  
  1957. erabyt    equ    0e5h    ; CP/M byte for erased file
  1958.  
  1959. doera:
  1960.  
  1961.     ld    e,-1    ; to fetch user code
  1962.     ld    c,32        ; BDOS: SET/GET USER CODE
  1963.     call    bdos
  1964.     ld    (user),a    ; save user number
  1965.  
  1966.     ld    e,5        ; set user = 5
  1967.     ld    c,32        ; BDOS: SET/GET USER CODE
  1968.     call    bdos
  1969.  
  1970.     ld    de,deffcb
  1971.     ld    a,'?'
  1972.     ld    (de),a
  1973.     ld    c,17        ;BDOS: SEARCH FOR FIRST
  1974.     call    bdos
  1975.  
  1976.  
  1977. nextera:
  1978.     cp    -1
  1979.     jp    z,erased
  1980.     ld    l,a
  1981.     ld    h,0
  1982.     add    hl,hl
  1983.     add    hl,hl
  1984.     add    hl,hl
  1985.     add    hl,hl
  1986.     add    hl,hl
  1987.     ld    de,defdma
  1988.     add    hl,de
  1989.     ld    a,(hl)
  1990.     and    not 00011111b    ; test for high bits set
  1991.     jp    z,nxtera
  1992.     ld    a,(hl)
  1993.     cp    erabyt
  1994.     jp    nz,nxtera
  1995.  
  1996.     push    hl
  1997.     ld    b,32
  1998. tstera:    ld    a,(hl)
  1999.     cp    erabyt
  2000.     jp    nz,notera
  2001.     inc    hl
  2002.     djnz    tstera        ;(doesnt change flags)
  2003. notera:    pop    hl
  2004.     jp    z,erased    ; as all 0e5's must be at end
  2005.  
  2006.     ld    de,16
  2007.     add    hl,de
  2008.     ex    de,hl        ; <DE> -> first data block allocation
  2009.     ld    hl,(dpb.dsm)
  2010.     ld    a,h
  2011.     or    a
  2012.     jp    nz,wrdera
  2013.  
  2014. ; test 16 erased file data block bytes
  2015.     ld    b,16
  2016. nxtedb:    push    hl        ; save DSM
  2017.     ld    a,(de)
  2018.     or    a
  2019.     jp    z,nuledb
  2020.     cp    l        ; check range
  2021.     jp    z,upedb
  2022.     jp    nc,erredb
  2023. upedb:    ld    l,a
  2024.     ld    h,0
  2025.     call    alv        ; return <HL> = <HL>/8, <C>=MOD(<HL>,7)
  2026.     call    setbit        ; returns CF=NZ if bit already set
  2027.     call    upera
  2028.     jp    nuledb
  2029. erredb:    call    uprng        ; data block outside range
  2030. nuledb:    pop    hl        ; recover DSM
  2031.     inc    de        ; increment to next data block byte
  2032.     djnz    nxtedb
  2033.     jp    nxtera
  2034.  
  2035. ; test 8 erased file data block words
  2036. wrdera:
  2037.     ex    de,hl        ; move back to HL
  2038.     ld    b,8
  2039. nxtedw:    push    hl
  2040.     ld    e,(hl)
  2041.     inc    hl
  2042.     ld    d,(hl)
  2043.     ld    a,e
  2044.     or    d
  2045.     jp    z,nuledw
  2046.     ld    hl,(dpb.dsm)
  2047.     xor    a
  2048.     sbc    hl,de
  2049.     jp    c,erredw
  2050.     ex    de,hl
  2051.     call    alv        ; return <HL> = <HL>/8, <C>=MOD(<HL>,7)
  2052.     call    setbit        ; returns CF=NZ if bit already set
  2053.     call    upera
  2054.     jp    nuledw
  2055. erredw:    call    uprng        ; data block outside range
  2056. nuledw:    pop    hl        ; recover data block pointer
  2057.     inc    hl
  2058.     inc    hl        ; increment to next data block word
  2059.     djnz    nxtedw
  2060.  
  2061. nxtera:
  2062.     ld    de,deffcb
  2063.     ld    a,erabyt and 11100000b    ; ignore water mark,
  2064.     ld    (de),a        ; (only works when user=5)
  2065.     ld    c,18        ;BDOS: SEARCH FOR NEXT
  2066.     call    bdos
  2067.     jp    nextera
  2068.  
  2069. erased:                ; reached end of file
  2070.  
  2071.     ld    a,(user)    ; recover user number
  2072.     ld    e,a
  2073.     ld    c,32        ; BDOS: SET/GET USER CODE
  2074.     call    bdos
  2075.  
  2076. ; --------------------------- ;
  2077. ; calculate unused datablocks ;
  2078. ; --------------------------- ;
  2079.  
  2080.     ld    hl,(lenalv)
  2081.     ld    b,h
  2082.     ld    c,l
  2083.     ld    hl,(dpb.dsm)
  2084.     ld    de,alloc
  2085. nxtcnt:    push    bc
  2086.     ld    a,(de)
  2087.     ld    b,8
  2088. next8:    add    a,a
  2089.     jp    nc,notalc
  2090.     dec    hl        ; reduce count by 1
  2091. notalc:    djnz    next8
  2092.     inc    de
  2093.     pop    bc
  2094.     dec    bc
  2095.     ld    a,b
  2096.     or    c
  2097.     jp    nz,nxtcnt
  2098.  
  2099.     inc    hl        ; as started with dsm, not dsm+1
  2100.     ld    (alvzro),hl
  2101.  
  2102. ; ---------------------- ;
  2103. ; fill text with results ;
  2104. ; ---------------------- ;
  2105.  
  2106.     ld    hl,alv01
  2107.     ld    (posn),hl
  2108.     xor    a
  2109.     ld    hl,(dpb.dsm)
  2110.     ld    de,1
  2111.     add    hl,de
  2112.     adc    a,0
  2113.     ld    c,0
  2114.     call    megdec        ; write total number of datablocks
  2115.  
  2116.     ld    hl,alv02
  2117.     ld    (posn),hl
  2118.     ld    hl,(alvdir)    ; datablocks allocated to directory
  2119.     call    wrddec
  2120.  
  2121.     ld    hl,alv03
  2122.     ld    (posn),hl
  2123.     ld    hl,(alvdat)    ; datablocks allocated to data
  2124.     call    wrddec
  2125.  
  2126.     ld    hl,alv04
  2127.     ld    (posn),hl
  2128.     ld    hl,(alvera)    ; datablocks allocated to erased data
  2129.     call    wrddec
  2130.  
  2131.     ld    hl,alv05
  2132.     ld    (posn),hl
  2133.     ld    hl,(alvlst)    ; datablocks allocated to overwritten data
  2134.     call    wrddec
  2135.  
  2136.     ld    hl,alv06
  2137.     ld    (posn),hl
  2138.     ld    hl,(alvbad)    ; datablocks with duplicated data access
  2139.     call    wrddec
  2140.  
  2141.     ld    hl,alv07
  2142.     ld    (posn),hl
  2143.     ld    hl,(alvzro)    ; datablocks not allocated
  2144.     call    wrddec
  2145.  
  2146.     ld    hl,alv08
  2147.     ld    (posn),hl
  2148.     ld    hl,(alvdir)
  2149.     xor    a
  2150.     ld    c,a
  2151.     ex    de,hl
  2152.     ld    hl,(alvdat)
  2153.     add    hl,de
  2154.     adc    a,c
  2155.     ex    de,hl
  2156.     ld    hl,(alvera)
  2157.     add    hl,de
  2158.     adc    a,c
  2159.     ex    de,hl
  2160.     ld    hl,(alvzro)
  2161.     add    hl,de
  2162.     adc    a,c
  2163.     ld    c,a
  2164.     call    megdec
  2165.  
  2166.     ld    hl,alv09
  2167.     ld    (posn),hl
  2168.     ld    hl,(alvrng)    ; datablocks with duplicated data access
  2169.     call    wrddec
  2170.  
  2171. ; ------------ ;
  2172. ; display text ;
  2173. ; ------------ ;
  2174.  
  2175.     ld    de,salmsg
  2176.     ld    c,9        ;BDOS: PRINT STRING
  2177.     call    bdos
  2178.  
  2179.     jp    waitcr        ; wait for <RETURN> then return
  2180.  
  2181.     dseg
  2182. salmsg:    db    cr,'                     DRIVE '
  2183. saldsk:    db    'A: DISK ALLOCATION'
  2184.     db    cr,lf
  2185.     db    cr,lf,'                            DATA BLOCKS '
  2186.     db    cr,lf
  2187.     db    cr,lf,'       TOTAL (DRM+1)             '
  2188. alv01:    db                        ' 65536 '
  2189.     db    cr,lf
  2190.     db    cr,lf,'       Directory                 '
  2191. alv02:    db                        '    16 '
  2192.     db    cr,lf,'       Data                      '
  2193. alv03:    db                        ' 65535 '
  2194.     db    cr,lf,'       Erased and recoverable    '
  2195. alv04:    db                        ' 65535 '
  2196.     db    cr,lf,'       Unused                    '
  2197. alv07:    db                        ' 65535 '
  2198.     db    cr,lf,'                                 '
  2199.     db                        ' ----- '
  2200.     db    cr,lf,'                                 '
  2201. alv08:    db                        ' 65536 '
  2202.     db    cr,lf
  2203.     db    cr,lf,'       Erased and reused         '
  2204. alv05:    db                        ' 65535 '
  2205.     db    cr,lf,'       Duplicated data           '
  2206. alv06:    db                        ' 65535 '
  2207.     db    cr,lf,'       Blocks outside range      '
  2208. alv09:    db                        ' 65535 '
  2209.     db    cr,lf,lf,lf,lf,lf,lf,lf
  2210.     db    '$'
  2211.     cseg
  2212.  
  2213. ;------;
  2214. showfil:    ; menu 1 option 4    Display file ALLOCATION
  2215. ;------;
  2216.     ld    a,(def.dsk)
  2217.     add    a,'A'
  2218.     ld    (sfldsk),a
  2219.     ld    de,sflmsg
  2220.     ld    c,9        ;BDOS: PRINT STRING
  2221.     jp    bdos        ; & RETURN
  2222.  
  2223.     dseg
  2224. sflmsg:    db    cr,'                     DRIVE '
  2225. sfldsk:    db    'A: FILE ALLOCATION'
  2226.     db    lf
  2227.     db    cr,lf,lf,lf,lf,lf,'$'        ; 10 line feeds
  2228.     cseg
  2229.  
  2230. ;------;
  2231. showdir:    ; menu 1 option 5    Display directory ALLOCATION 
  2232. ;------;
  2233.     ld    a,(def.dsk)
  2234.     add    a,'A'
  2235.     ld    (sdrdsk),a
  2236.     ld    de,sdrmsg
  2237.     ld    c,9        ;BDOS: PRINT STRING
  2238.     jp    bdos        ; & RETURN
  2239.  
  2240.     dseg
  2241. sdrmsg:    db    cr,'                     DRIVE '
  2242. sdrdsk:    db    'A: DIRECTORY ALLOCATION'
  2243.     db    lf
  2244.     db    cr,lf,lf,lf,lf,lf,'$'        ; 10 line feeds
  2245.     cseg
  2246.  
  2247.     page
  2248.  
  2249. ;-----;
  2250. select:        ; menu 1 option 9    Select new disk
  2251. ;-----;
  2252.  
  2253.     ld    a,(def.dsk)
  2254.     ld    (olddsk),a    ; save in case of error
  2255.  
  2256.     ld    de,sldmsg
  2257.     ld    c,9        ;BDOS: PRINT STRING
  2258.     call    bdos
  2259.  
  2260. ; ---------------------- ;
  2261. ; Request new drive name ;
  2262. ; ---------------------- ;
  2263.  
  2264. sel0:
  2265.     ld    de,logmsg
  2266.     ld    c,9        ;BDOS: PRINT STRING
  2267.     call    bdos
  2268.  
  2269.     ld    de,selbuff
  2270.     ld    c,10        ;BDOS: DIRECT CONSOLE BUFFER
  2271.     call    bdos
  2272.     ld    a,(sellen)
  2273.     or    a
  2274.     ret    z        ; nothing selected
  2275.     cp    1
  2276.     jp    z,sel1
  2277.     cp    2
  2278.     jp    nz,sel0
  2279.     ld    a,(seldb2)
  2280.     cp    ':'
  2281.     jp    nz,sel0
  2282. sel1:    ld    a,(seldb1)
  2283.     cp    'a'
  2284.     jp    c,sel2
  2285.     cp    'z'+1
  2286.     jp    nc,sel0
  2287.     add    a,'A'-'a'    ; convert to lower case
  2288. sel2:    sub    'A'
  2289.     cp    15+1
  2290.     jp    nc,sel0        ; outside range 0-15
  2291.     
  2292.     ld    (def.dsk),a    ; Current selected disk
  2293.  
  2294.     ld    c,13        ;BDOS: RESET DISK SYSTEM
  2295.     call    bdos
  2296.  
  2297.     ld    a,(def.dsk)
  2298.     ld    e,a
  2299.     ld    c,14        ;BDOS: SELECT DISK
  2300.     call    bdos
  2301.     or    a
  2302.     jp    nz,selerr
  2303.  
  2304.     call    fetchdp        ; fetch dpb and dph for drive
  2305.  
  2306.     ret
  2307.  
  2308. selerr:    ld    a,(olddsk)    ; recover previously selecte disk
  2309.     ld    (def.dsk),a
  2310.     ld    e,a
  2311.     ld    c,14        ;BDOS: SELECT DISK
  2312.     call    bdos
  2313.     or    a
  2314.     jp    nz,badsel
  2315.  
  2316.     call    fetchdp        ; fetch dpb and dph for drive
  2317.  
  2318.     ld    de,oldmsg
  2319.     ld    c,9        ;BDOS: PRINT STRING
  2320.     call    bdos
  2321.  
  2322.     call    waitcr
  2323.  
  2324.     ret
  2325.  
  2326.     dseg
  2327.  
  2328. sldmsg:    db    cr,lf,lf,lf,lf,lf    ; 5 line feeds
  2329.     db    cr,lf,lf,lf,lf,lf    ; 5 line feeds
  2330.     db    cr,lf,lf,lf,lf,lf    ; 5 line feeds
  2331.     db    cr,lf,lf,lf,lf,lf    ; 5 line feeds
  2332.     db    cr,'                     SELECT NEW DISK'
  2333.     db    lf
  2334.     db    cr,lf,lf,lf,lf,lf,'$'    ; 5 line feeds
  2335.  
  2336. olddsk:    db    0
  2337.  
  2338. logmsg:    db    cr,'Enter drive name (A:, B:, etc ) ?    ',bs,bs,bs,'$'
  2339. selbuff:
  2340.     db    3
  2341. sellen:
  2342.     ds    1
  2343. seldb1:    ds    1
  2344. seldb2:    ds    2
  2345.  
  2346. oldmsg:    db    cr,lf,'--- Unable to select new disk ---'
  2347.     db    cr,lf,lf,lf,lf,lf,'$'    ; 5 line feeds
  2348.  
  2349.     cseg
  2350.  
  2351.     page
  2352.  
  2353. ;-------;
  2354. goodvers:
  2355. ;-------;
  2356.  
  2357.     ld    a,(deffcb)
  2358.     dec    a
  2359.     cp    -1
  2360.     jp    nz,useccp    ; use ccp disk
  2361.  
  2362.     ld    c,25        ;BDOS: RETURN CURRENT DISK
  2363.     call    bdos
  2364.  
  2365. useccp:    ld    (def.dsk),a    ; Current selected disk
  2366.  
  2367.     ld    c,13        ;BDOS: RESET DISK SYSTEM
  2368.     call    bdos
  2369.  
  2370.     ld    a,(def.dsk)
  2371.     ld    e,a
  2372.     ld    c,14        ;BDOS: SELECT DISK
  2373.     call    bdos
  2374.     or    a
  2375.     jp    nz,badsel
  2376.  
  2377.     ld    (savesp),sp    ; must use local stack as BIOS may be hungry
  2378.     ld    sp,savesp
  2379.  
  2380.     call    fetchdp        ; fetch dpb and dph for drive
  2381.  
  2382.     call    main        ; now display as requested
  2383.  
  2384.     ld    sp,(savesp)
  2385.  
  2386.     ld    c,0        ;BDOS: SYSTEM RESET
  2387.     jp    bdos        ; & exit
  2388.  
  2389. ;---;
  2390. main:
  2391. ;---;
  2392.  
  2393.     call    clearscrn    ; clear screen
  2394.     call    screen1        ; display menu
  2395.     call    option        ; request option
  2396.     cp    -1
  2397.     ret    z
  2398.  
  2399.     call    task1
  2400.     jp    main
  2401.  
  2402. ;----;
  2403. task1:
  2404. ;----;
  2405.  
  2406.     ld    c,a
  2407.     ld    b,0
  2408.     dec    bc
  2409.     ld    hl,table1
  2410.     add    hl,bc
  2411.     add    hl,bc
  2412.     ld    a,(hl)
  2413.     inc    hl
  2414.     ld    h,(hl)
  2415.     ld    l,a
  2416.     jp    (hl)
  2417.  
  2418. table1:    dw    showblk    ; menu 1 option 1    Display DPB statistics
  2419.     dw    showhdr    ; menu 1 option 2    Display DPH statistics
  2420.     dw    showalv    ; menu 1 option 3    Display disk ALLOCATION
  2421.     dw    showfil    ; menu 1 option 4    Display file ALLOCATION
  2422.     dw    showdir    ; menu 1 option 5    Display directory ALLOCATION 
  2423.     dw    return
  2424.     dw    return
  2425.     dw    return
  2426.     dw    select    ; menu 1 option 9    Select new disk
  2427.  
  2428. return:    ret
  2429.  
  2430.     dseg
  2431. alloc    equ    $        ; allocation vector placed at end of program
  2432.     end
  2433.