home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / cpmug / cpmug085.ark / SD-44.ASM < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  47.9 KB  |  1,842 lines

  1. *             SD.ASM Ver 4.4
  2. *              (Rev 28feb82)
  3.  
  4. *            SUPER DIRECTORY PROGRAM
  5. *               by Bruce    R. Ratoff
  6.  
  7. *        Based on 'DIRS' by Keith Petersen, W8SDZ
  8.  
  9. * Displays the directory of a CP/M disk, sorted    alphabetically,
  10. * with the file    size in    K, rounded to the nearest CP/M block size.
  11.  
  12. * This latest variation    on a common theme will automatically adjust
  13. * itself for any block size and    directory length under CP/M 1.4    or 2.x
  14. * or MP/M (any version).  Provisions are made for (1) automatic    pauses
  15. * when the screen fills    up; (2)    searching individual or    multiple drives
  16. * and/or user areas; (3) unconditional or optionally resetting the disk
  17. * system before    execution begins; (4) directing    output to a disk file
  18. * and appending    to it on subsequent runs; (5) summary line output giving
  19. * drive    and user information, #    of files matched and how much space they
  20. * consume, and the amount of free space    remaining on the disk; (6) displaying
  21. * or suppressing CP/M 2    "system" files;    (7) accepting ambiguous    filenames
  22. * with or without a drive name;    and (8)    printer    output.
  23.  
  24. * See SD.DOC for detailed instructions on configuring and running SD.ASM
  25.  
  26. * ==========================================================================
  27.  
  28. *        NOTE: If you add improvements or otherwise update
  29. *        this program, please modem a copy of the new file
  30. *        to "TECHNICAL CBBS"    in Dearborn, Michigan -    phone
  31. *        313-846-6127 (110, 300, 450    or 600 baud).  Use the
  32. *        filename SD-NEW.NEW.  (KBP)
  33.  
  34. *        As SD-41.ASM is "officially experimental", the author
  35. *        of the latest revisions would appreciate feedback on
  36. *        any bugs which may be discovered.  CC bug notes to
  37. *        me c/o Hyde Park RCP/M (phone 312-955-4493).  (DB)
  38.  
  39. * ==========================================================================
  40. * Fixes/updates    (in reverse order to minimize reading time):
  41.  
  42. * 28feb82 Ignore attribute bits in compare subrs, equate CRT leadin char.,
  43. *    add Hazeltine 1500 equates. (4.4 - W.Earnest)
  44.  
  45. * 06feb82 Modified use of BDOS error vector table for DOPT.  The previous
  46. *     arrangement would change BDOS without checking whether it really was
  47. *     pointing to the right location.  In addition, the trap vectors are 
  48. *     swapped only when called for.
  49. *    Modified RMAC/MAC options: ASEG statement added for using RMAC
  50. *    without the requirement for external defs.
  51. *    Also added dim for ADM-31 (works same as reverse video), and cleared
  52. *    high^order bit when being sent to printer. (4.3 - R.B.STRAND)
  53.  
  54. * 11-1-81 Eliminated LF after "More" message. Allows yet another
  55. *     line per more.
  56. * 10-25-81 Incorporated 10/21 updates renamed version. -CAF
  57. *     Also made display more compact by eliminating unneeded lf's
  58. *    This allows two more lines per "more"
  59.  
  60. * 10-21-81 Added conditionals for REVIDEO for reverse video
  61. *       display of tags ($SYS, etc.) -CAF
  62.  
  63. * 10/20/81 minor update to correct (1) malfunction when appending to an
  64. *       existing sd.dir file with the directory from an empty disk;
  65. *       (2) clobbering data area while closing sd.dir when last record
  66. *       appended is completely full; and (3) equate interaction error
  67. *       between fopt and aopt.  (ver 4.1 - david boruff)
  68.  
  69. * 10/19/81 MAJOR UPDATE adding new command line options for
  70. *       (1) disk system reset;  (2) page pause override;
  71. *       (3) displaying directory of a specified user    area;
  72. *       (4) searching ranges    of drives or user areas; and
  73. *       (5) printer output.    Corrected previous name error
  74. *       to avoid confusion with Keith Petersen's old SDIR.
  75.  
  76. *       Corrected obscure file output bug which occurred only
  77. *       when appending on even record or extent boundaries.
  78. *       Reset equate    of Ver 2.3 deleted as redundant    now that
  79. *       command line    reset available    as an option or    default.
  80. *       Shortened page-pause    message    to free-up program space.
  81. *       Optimized much of the existing code to compact the load
  82. *       module and gain space for new features.  Option scanner
  83. *       rewritten to    permit free form input and to simplify any
  84. *       future expansions of    the command line option    set.
  85. *       Reclaimed uninitialized data    memory to further compact
  86. *       load    module size.  By popular demand, restored code to
  87. *       display free    space remaining    when no    files are found.
  88. *       Added tables    to allow restricting directory searches
  89. *       to a    range of drives    and/or user areas.  BDOS intercept
  90. *       added to facilitate searching drives    that may not be
  91. *       on-line (more generally applicable than the FILEFIND
  92. *       method if your BIOS returns control to BDOS on fatal disk
  93. *       errors).  General cosmetic overhaul including tabular
  94. *       realignment and additional comments to enhance readability
  95. *       at the cost of a "few" extra bytes.    (Ver 4.0 - David Boruff)
  96.  
  97. * 09/23/81 MINOR UPDATE    to add equate to allow suppressing user
  98. *       numbers in the directory output. (Ver 3.1 - David Boruff)
  99.  
  100. * 09/18/81 MAJOR UPDATE    implementing new file output option allowing
  101. *       directory output to be appended to a    disk file.  Changed
  102. *       option specification    format to require a dollar sign
  103. *       preceding the option    specifiers.  Changed header format
  104. *       to display drive & user #'s for each line less than 4
  105. *       files wide.    Changed    code for no files found    to display
  106. *       error message only.    (Ver 3.0 - David Boruff)
  107.  
  108. * 09/12/81 MINOR UPDATE    deleting WIDE and NOT WIDE code    in deference
  109. *       to equating screen size.  Added Flashwriter II equate to
  110. *       allow display of file attributes in reverse video.  Changed
  111. *       tag-line to display drive and user #.  Added    equate to allow
  112. *       disk    system reset on    startup.  Other    cosmetic changes made
  113. *       to open up display format and give output a less cramped
  114. *       appearance. (Ver 2.3    - David    Boruff)
  115.  
  116. * 06/05/81 Added PGPAWZ    (page pause) conditional for remote
  117. *       CP/M    systems    where pausing may not be wanted.
  118. *       Setting PGPAWZ and REPSIZ to    FALSE will result in
  119. *       a display like DIR, but sorted and with the stat
  120. *       of space remaining.    Rearranged equates to allow
  121. *       15 lines per    page when narrow display is chosen.
  122. *       (Ver    2.2 - KBP)
  123.  
  124. * 06/01/81 Added version number, restored CTL-C    break, added
  125. *       CTL-C test to allow break at    page pause, added
  126. *       routine to gobble up    any waiting console character
  127. *       at EXIT, added conditional assembly to allow    no
  128. *       report of file sizes, added conditional assembly
  129. *       for direct console I/O for remote CP/M systems
  130. *       where phone line noise would    garbage    display.  (KBP)
  131.  
  132. * 05/06/81 Corrected double printing of    drive name in CALLB.
  133. *       Error only occurred with narrow display when    file
  134. *       wasn't found. (Tim Nicholas)
  135.  
  136. * 02/06/81 Changed sort    to have    odd gap    (KBP say its faster)
  137.  
  138. * 01/06/81 Changed sort    from bubble sort to shell sort
  139. *       for faster speed.
  140.  
  141. * 12/24/80 Changed BIOS    conout to BDOS conout to allow
  142. *       printing of directory with CTL-P.  Also added
  143. *       print of remaining space even if file not
  144. *       found. (Steve Nossen)
  145.  
  146. * 12/15/80 Added space suppression when    printing file
  147. *       totals.  (KBP)
  148.  
  149. * 12/14/80 Added logic to print    space remaining    on disk.
  150. *       Changed ^C test so that interrupting    character is
  151. *       not echoed (makes remote use    cleaner).  (BRR)
  152.  
  153. * 12/02/80 Fixed bug in    print routine which compared last file
  154. *       against garbage before printing. (BRR)
  155.  
  156. * 11/29/80 Changed to allow printing 4 file names. (Ben    Bronson
  157. *       and Keith Petersen)
  158.  
  159. * 11/22/80 Fixed bug in    handling >256 files.  Changed abort test
  160. *       in print routine to only abort on control-c.     (BRR)
  161.  
  162. * ==========================================================================
  163.  
  164. *         Set 'RMAC'    TRUE to    assemble with relocating assembler
  165. *         (requires link with PAGE 0    equates    in separate file).
  166.  
  167. * ==========================================================================
  168.  
  169. FALSE    EQU    0
  170. TRUE    EQU    NOT FALSE
  171.  
  172. ******************************
  173. *                 *
  174. * USER OPTION SPECIFICATIONS *
  175. *                 *
  176. ******************************
  177.  
  178. ALTCPM    EQU    FALSE        ;True for H8 or    TRS-80
  179. DIRCON    EQU    FALSE        ;True for direct console output
  180. OPTION    EQU    TRUE        ;True if allowing ANY command line options
  181. AOPT    EQU    TRUE        ;True to allow searching all user areas
  182. DOPT    EQU    TRUE        ;True to allow searching all drives on-line
  183. FOPT    EQU    TRUE        ;True to allow file output option
  184. NOPT    EQU    TRUE        ;True to allow disabling page pause option
  185. PGPAWZ    EQU    TRUE        ;True for pause after each page
  186. POPT    EQU    TRUE        ;True to allow printer option
  187. REPERR    EQU    TRUE         ;True to report command line option errors
  188. REPSIZ    EQU    TRUE        ;True to report file sizes
  189. REPUSR    EQU    TRUE        ;True to report user numbers
  190. RMAC    EQU    FALSE        ;True for RMAC assembly and external def link
  191. ROPT    EQU    TRUE        ;True to allow reset option
  192. SOPT    EQU    TRUE        ;True to allow system file option
  193. UOPT    EQU    TRUE        ;True to allow user number option
  194. REVIDEO    EQU    FALSE        ;Use reverse video sequences
  195. LEADIN    EQU    033Q        ;Esc. leadin for ADM-31 & Z19
  196. INTOREV    EQU    051Q        ;Seq. to enter dim mode (for ADM-31)
  197. OUTAREV    EQU    050Q        ; and to get out
  198. * INTOREV    EQU    0160Q        ;Sequence to enter reverse video (Z19)
  199. * OUTAREV    EQU    0161Q        ;And to get out
  200. * LEADIN    EQU    07EH        ;Tilda leadin for hazeltine 1500
  201. * INTOREV    EQU    19H        ;Background mode on Hazeltine 1500
  202. * OUTAREV    EQU    1FH        ;Foreground mode on Hazeltine 1500
  203. VECTOR    EQU    FALSE        ;True to display attributes on Flashwriter II
  204. VIDEO    EQU    0E009H        ;Entry to Flashwriter video driver PROM
  205.  
  206. DELIM    EQU    7CH        ;Fence (delimiter) character (vertical bar)
  207.  
  208. NPL    EQU    4        ;# of names per line (max of 3 for 64x16)
  209. *                             (max of 4 for 80x24)
  210.  
  211. LPS    EQU    23        ;# of lines per screen (max of 14 for 64x16)
  212. *                               (max of 23 for 80x24)
  213.  
  214.     IF    NOPT AND NOT PGPAWZ
  215.     ++++ NOPT OPTION REDUNDANT WITHOUT PGPAWZ ++++
  216.     ENDIF
  217.  
  218.     IF    REPERR AND NOT OPTION
  219.     ++++ REPERR EQUATE USELESS WITHOUT OPTION ++++
  220.     ENDIF
  221.  
  222. * BDOS equates
  223.  
  224. RDCHR    EQU    1        ;Read char from    console
  225. WRCHR    EQU    2        ;Write char to console
  226. CONST    EQU    11        ;Check cons stat
  227. RESET    EQU    13        ;Reset disk system
  228. SELDSK    EQU    14        ;Select    disk
  229. OPEN    EQU    15        ;0FFH=not found
  230. CLOSE    EQU    16        ;   "    "
  231. SEARCH    EQU    17        ;   "    "
  232. NEXT    EQU    18        ;   "    "
  233. READ    EQU    20        ;not 0 = EOF
  234. WRITE    EQU    21        ;not 0 = disk full
  235. MAKE    EQU    22        ;0FFH =    directory full
  236. CURDSK    EQU    25        ;Get currently logged disk name
  237. SETDMA    EQU    26        ;Set current DMA
  238. GALLOC    EQU    27        ;Get address of    allocation vector
  239. CURDPB    EQU    31        ;Get current disk parameters
  240. CURUSR    EQU    32        ;Get currently logged user number (2.x only)
  241.  
  242.     IF    ALTCPM
  243. BASE    EQU    4200H
  244. TPA    EQU    4300H
  245.     ENDIF
  246.  
  247.     IF    (NOT ALTCPM) AND (NOT RMAC)
  248. BASE    EQU    0        ;Default to 0 (or 100H with MAC    +R option)
  249. TPA    EQU    100H
  250.     ENDIF
  251.  
  252.     IF    RMAC
  253.     EXTRN    BASE,FCB,BDOS    ;Make base external
  254.     ELSE
  255. FCB    EQU    BASE+5CH
  256. BDOS    EQU    BASE+5
  257.     ASEG        ; Ignore this error if using MAC
  258.     ORG    TPA
  259.     ENDIF
  260.  
  261. FILL    MACRO    BYTES,WITH
  262.     REPT    BYTES
  263.     DB    WITH
  264.     ENDM
  265.     ENDM
  266.  
  267. $-MACRO
  268.  
  269.     PAGE    60
  270.     TITLE    'SD Version 4.4 - 28 feb 1982'
  271.  
  272. *********************************
  273. *                *
  274. * BEGIN    EXECUTABLE PROGRAM CODE    *
  275. *                *
  276. *********************************
  277.  
  278.     JMP    START
  279.  
  280.     DB    'SD 4.4 - 28feb82'
  281.  
  282. START:    LXI    H,0
  283.     DAD    SP        ;HL=old    stack
  284.     SHLD    STACK        ;Save it
  285.     LXI    SP,STACK    ;Get new stack
  286.  
  287.     MVI    C,12        ;Get and save the CP/M version #
  288.     CALL    BDOS
  289.     MOV    A,L
  290.     STA    VERFLG
  291.     CPI    20H        ;Set carry if CP/M 1.4
  292.  
  293.     MVI    E,0FFH        ;Get current user number if using CP/M 2, or
  294.     MVI    C,CURUSR    ;Fall through with A=0 if not
  295.     CNC    CPM
  296.  
  297.     STA    OLDUSR        ;Initialize startup user number
  298.     STA    NEWUSR        ;..and make new    user match it
  299.  
  300.     IF    DOPT
  301.     STA    BASUSR        ;Save extra copy for multi-disk    directories
  302.     ENDIF
  303.  
  304.     MVI    C,CURDSK
  305.     CALL    CPM        ;Get current disk nr
  306.     STA    OLDDSK        ;Save for reset    if needed
  307.  
  308.     IF    FOPT
  309.     INR    A
  310.     STA    OUTFCB        ;Set directory output file drive
  311.     ENDIF
  312.  
  313.     LXI    H,FCB
  314.     MOV    A,M        ;Get drive name    for directory search
  315.     ORA    A        ;Any specified?
  316.     JNZ    START2        ;Yes skip next routine
  317.     LDA    OLDDSK        ;Otherwise, get    default    disk
  318.     INR    A
  319. START2:    MOV    M,A        ;Put the absolute drive    code in    directory FCB
  320.  
  321. * If at    least one option is allowed, scan the command line for the
  322. * option field delimiter.  The option field delimiter is considered
  323. * valid    only if    it is preceded by at least 1 space (otherwise, it
  324. * may be part of the directory filename).  Any unrecognized options
  325. * or illegal user numbers will be flagged or ignored (see REPERR).
  326. * (We scan the command line buffer rather than the 2nd default FCB
  327. * because all 8    options    plus a 2 digit user number won't fit in
  328. * the FCB name field).
  329.  
  330.     IF    OPTION
  331.     LXI    H,80H        ;Set command line buffer pointer
  332.     MOV    B,M        ;Get length of command line buffer
  333.  
  334. * Search for the command line delimiter.  If not found, assume no options.
  335.  
  336. SCNDOL:    INX    H
  337.     DCR    B
  338.     JM    CKREST        ;Exit if command line buffer empty
  339.     MOV    A,M
  340.     CPI    '$'
  341.     JNZ    SCNDOL
  342.     DCX    H        ;'$' found - make sure space precedes it
  343.     MOV    A,M
  344.     INX    H
  345.     CPI    ' '
  346.     JNZ    SCNDOL        ;No space - ignore "$" and search again
  347.  
  348. * Valid    delimiter found.  Scan the rest    of the buffer for options.  Errors
  349. * past this point will cause an    abort if the command line error    option is
  350. * enabled.  Otherwise, the dud option will be ignored and SD will attempt
  351. * to continue stumbling    through    the rest of the    field.
  352.  
  353.     XCHG            ;Get option field pointer to DE
  354. SCNOPT:    INX    D        ;Bump to next option field character
  355.     DCR    B        ;Dock characters left in option    field
  356.     JM    CKREST        ;If option field exhausted, exit
  357. SCNAGN:    LDAX    D        ;Get the next option character
  358.     CPI    ' '        ;Do we have a space?
  359.     JZ    SCNOPT        ;Ignore    it if so
  360.     LXI    H,OTBL-1    ;Get base of option lookup table
  361.     MVI    C,OEND-OTBL+1    ;Get length of option lookup table
  362. NOMACH:    INX    H        ;Bump to next option table character
  363.     DCR    C        ;Are we    out of the table?
  364.     JZ    CK4USR        ;If so, check for user option
  365.     CMP    M        ;Compare our character with option table
  366.     JNZ    NOMACH        ;Exit if no match
  367.     MVI    M,0        ;Otherwise, activate the flag
  368.     JMP    SCNOPT        ;..and go get the next option character
  369.  
  370. * If option character doesn't match the table, see if we have a User
  371. * option.
  372.  
  373. CK4USR:    IF    UOPT        ;Check for user    number option
  374.     CPI    'U'
  375.     JNZ    CLERR        ;Last option, so bad deal if that ain't it
  376.  
  377. UAGN:    INX    D        ;Bump to user number digit
  378.     DCR    B
  379.     JM    CLERR        ;Error if nothing left
  380.     LDAX    D        ;Get decimal digit
  381.     CPI    ' '        ;Ignore    leading    spaces
  382.     JZ    UAGN
  383.     SUI    30H        ;Subtract ASCII    BIAS
  384.     JC    CLERR        ;Error if < 0
  385.     CPI    10
  386.     JNC    CLERR        ;Error if > 9
  387.     STA    NEWUSR        ;Save user number as it    may be only 1 digit
  388.  
  389.     IF    DOPT
  390.     STA    BASUSR        ;Duplicate it if multi-disk mode
  391.     ENDIF
  392.  
  393.     INX    D        ;Bump to possible 2nd digit of user number
  394.     DCR    B
  395.     JM    CKREST        ;If no more buffer, exit with complete user #
  396.     LDAX    D        ;Else, check for another digit
  397.     SUI    30H
  398.     JC    SCNAGN        ;If next char not numeric, its not part    of
  399.     CPI    10        ;..user    number so go check for another option
  400.     JNC    SCNAGN
  401.     MOV    L,A        ;Save units digit
  402.     LDA    NEWUSR        ;Get tens digit
  403.     ADD    A        ;Multiply by 10
  404.     MOV    H,A
  405.     ADD    A
  406.     ADD    A
  407.     ADD    H
  408.     ADD    L        ;Combine with units digit
  409.     STA    NEWUSR        ;Save the total    user number
  410.  
  411.     IF    DOPT
  412.     STA    BASUSR        ;Duplicate it if multi-disk mode
  413.     ENDIF
  414.  
  415.     JMP    SCNOPT        ;Continue scanning
  416.     ENDIF            ;Balance UOPT
  417.  
  418. * If command line error    option enabled,    playback the command line up
  419. * to the character that    we gagged on and exit.    If REPERR is not enabled,
  420. * then continue    as if nothing were amiss to avoid acknowledging    that
  421. * some options are available.
  422.  
  423. CLERR:    IF    REPERR
  424.     XRA    A
  425.     INX    D        ;Tag end of command line with terminator
  426.     STAX    D
  427.     CALL    CRLF
  428.     LXI    D,ERRMS2
  429.     CALL    PRINT
  430.     LXI    D,ERRTAG
  431.     CALL    PRINT
  432.     LXI    H,81H        ;Playback bad command line to error point
  433. CLELP:    MOV    A,M
  434.     ORA    A
  435.     JZ    CLEX
  436.     CALL    TYPE
  437.     INX    H
  438.     JMP    CLELP
  439.  
  440. CLEX:    MVI    A,'?'        ;Tag line with a '?' field
  441.     CALL    TYPE
  442.     CALL    CRLF        ;Space down 1 more line
  443.     JMP    EXIT        ;..and return to CP/M
  444.     ELSE
  445.  
  446.     JMP    SCNOPT        ;If not    reporting errors, ignore the dud
  447.  
  448.     ENDIF            ;Balance REPERR
  449.     ENDIF            ;Balance OPTION
  450.  
  451. * Options input or not specified.  If reset option specified, reset
  452. * the disk system now.    Its important that the reset be done OUTSIDE
  453. * the multiple drive loop if the file output option is enabled because
  454. * CP/M 1.4 clobbers the DMA buffer on reset.
  455.  
  456. CKREST: IF    ROPT
  457.     LDA    ROPFLG        ;If reset flag set, reset disk system before
  458.     ORA    A        ;..starting to update allocation vectors
  459.     MVI    C,RESET
  460.     CZ    CPM
  461.     ENDIF            ;Balance ROPT
  462.  
  463.     IF    DOPT
  464.     LDA    DOPFLG        ;If multi-disk flag set, 
  465.     ORA    A        ;..need to set error traps
  466.     CZ    SWAPEM        ;Swap BDOS error vector    tables
  467.     ENDIF
  468.  
  469. * Validate drive code and user area numbers from the drive table.
  470.  
  471. NOOPT:    LXI    D,DREMSG    ;Get the drive/user error message
  472.     PUSH    D
  473.     LDA    FCB        ;Get directory drive code
  474.     DCR    A        ;Normalize to range of 0-15
  475.     CPI    HIDRV-LODRV    ;Compare with maximum drives on-line
  476.     JNC    ERXIT        ;Take drive error exit if out of range
  477.     LXI    H,USRMSG    ;Switch    to user    # error    message
  478.     XTHL
  479.     MOV    E,A        ;Use drive code    as index into table
  480.     MVI    D,0
  481.     LXI    H,LODRV        ;Point to base of drive/user table
  482.     DAD    D
  483.     MOV    A,M        ;Get the maximum user #    for this drive
  484.     ANI    0FH        ;Make sure its in range    0 - 15
  485.     STA    MAXUSR        ;Save it for later
  486.     LXI    H,NEWUSR    ;Point to the directory    user area
  487.     CMP    M        ;Compare it with the maximum
  488.     JC    ERXIT        ;Take error exit if user number    illegal
  489.     POP    D        ;Destroy error message pointer
  490.  
  491.     LXI    H,FCB+1     ;Point to name
  492.     MOV    A,M        ;Any specified?
  493.     CPI    ' '
  494.     JNZ    GOTFCB
  495.  
  496. * No FCB - make    FCB all    '?'
  497.  
  498.     MVI    B,11        ;FN+FT count
  499.  
  500. QLOOP:    MVI    M,'?'        ;Store '?' IN FCB
  501.     INX    H
  502.     DCR    B
  503.     JNZ    QLOOP
  504.  
  505. GOTFCB:    MVI    A,'?'        ;Force wild extent
  506.     STA    FCB+12
  507.     CALL    SETSRC        ;Set DMA for BDOS media change check
  508.     LXI    H,FCB        ;Point to FCB drive code for directory
  509.     MOV    E,M        ;Get the drive code out of the FCB
  510.     DCR    E        ;Normalize drive code for SELECT
  511.     MVI    C,SELDSK    ;Select the directory drive to retrieve
  512.     CALL    CPM        ;..the proper allocation vector
  513.     CALL    CKVER        ;Check version
  514.     JC    V14        ;Pre-2.X...get params the 1.4 way
  515.  
  516.     MVI    C,CURDPB    ;It's 2.X or MP/M...request DPB
  517.     CALL    BDOS
  518.     INX    H
  519.     INX    H
  520.     MOV    A,M        ;Get block shift
  521.     STA    BLKSHF
  522.     INX    H        ;Bump to block mask
  523.     MOV    A,M
  524.     STA    BLKMSK        ;Get it
  525.     INX    H
  526.     INX    H
  527.     MOV    E,M        ;Get max block #
  528.     INX    H
  529.     MOV    D,M
  530.     XCHG
  531.     SHLD    BLKMAX        ;Save it
  532.     XCHG
  533.     INX    H
  534.     MOV    E,M        ;Get directory size
  535.     INX    H
  536.     MOV    D,M
  537.     XCHG
  538.     JMP    FREE        ;Let FREE save it and setup order table
  539.  
  540. V14:    LHLD    BDOS+1        ;Get params 1.4 style
  541.     MVI    L,3BH        ;Point to directory size
  542.     MOV    E,M        ;Get it
  543.     MVI    D,0        ;Force high order to 0
  544.     PUSH    D        ;Save for later
  545.     INX    H        ;Point to block    shift
  546.     MOV    A,M        ;Fetch
  547.     STA    BLKSHF        ;Save
  548.     INX    H        ;Point to block    mask
  549.     MOV    A,M        ;Fetch it
  550.     STA    BLKMSK        ;And save it
  551.     INX    H
  552.     MOV    E,M        ;Get max. block    no.
  553.     MVI    D,0
  554.     XCHG
  555.     SHLD    BLKMAX        ;Save it
  556.     POP    H        ;Restore directory size
  557.  
  558. * Calculate # of K free    on selected drive now so that the FREE figure
  559. * will not reflect either the creation or additions to the SD.DIR
  560. * file (which we would probably    erase or move anyway).
  561.  
  562. FREE:    SHLD    DIRMAX        ;Save max # of entries in directory
  563.     MVI    C,GALLOC    ;Get address of    allocation vector
  564.     CALL    BDOS
  565.     XCHG
  566.     LHLD    BLKMAX        ;Get its length
  567.     INX    H
  568.     LXI    B,0        ;Init block count to 0
  569.  
  570. GSPBYT:    PUSH    D        ;Save alloc address
  571.     LDAX    D
  572.     MVI    E,8        ;Set to    process    8 blocks
  573.  
  574. GSPLUP:    RAL            ;Test bit
  575.     JC    NOTFRE
  576.     INX    B
  577.  
  578. NOTFRE:    MOV    D,A        ;Save bits
  579.     DCX    H        ;Count down blocks
  580.     MOV    A,L
  581.     ORA    H
  582.     JZ    ENDALC        ;Quit if out of    blocks
  583.     MOV    A,D        ;Restore bits
  584.     DCR    E        ;Count down 8 bits
  585.     JNZ    GSPLUP        ;Do another bit
  586.     POP    D        ;Bump to next byte..
  587.     INX    D        ;..of alloc. vector
  588.     JMP    GSPBYT        ;Process it
  589.  
  590. ENDALC:    POP    D        ;Clear allocation vector pointer from stack
  591.     MOV    L,C        ;Copy blocks to    hl
  592.     MOV    H,B
  593.     LDA    BLKSHF        ;Get block shift factor
  594.     SUI    3        ;Convert from sectors to K
  595.     JZ    SAVFRE        ;Skip shifts if 1K blocks - return free in HL
  596.  
  597. FREKLP: DAD    H        ;Multiply blocks by K/BLK
  598.     DCR    A
  599.     JNZ    FREKLP
  600. SAVFRE: SHLD    FREEBY        ;Save the free space for output later
  601.  
  602. * Reenter here on subsequent passes while in the all-users mode
  603.  
  604. SETTBL:    LHLD    DIRMAX        ;Get directory maximum again
  605.     INX    H        ;Directory size    is DIRMAX+1
  606.     DAD    H        ;Double    directory size
  607.     LXI    D,ORDER        ;To get    size of    order table
  608.     DAD    D        ;Allocate order    table
  609.     SHLD    TBLOC        ;Name table begins where order table ends
  610.     SHLD    NEXTT
  611.     XCHG
  612.     LHLD    BDOS+1        ;Make sure we have room    to continue
  613.     MOV    A,E
  614.     SUB    L
  615.     MOV    A,D
  616.     SBB    H
  617.     JNC    OUTMEM
  618.  
  619.     IF    UOPT
  620.     CALL    CKVER        ;Set carry if pre-CP/M 2
  621.     LDA    NEWUSR        ;Get user area for directory
  622.     MOV    E,A
  623.     MVI    C,CURUSR    ;Get the user function
  624.     CNC    CPM        ;..and set new user number if CP/M 2
  625.     ENDIF
  626.  
  627. * Look up the FCB in the directory
  628.  
  629. SFIRST:    LXI    H,0
  630.     SHLD    COUNT        ;Initialize match counter
  631.     SHLD    TOTFIL        ;     "        total file counter
  632.     SHLD    TOTSIZ        ;     "        total size counter
  633.     CALL    SETSRC        ;Set DMA for directory search
  634.     MVI    C,SEARCH    ;Get 'search first' function
  635.     JMP    LOOK        ;..and go search for 1st match
  636.  
  637. * Read more directory entries
  638.  
  639. MORDIR:    MVI    C,NEXT        ;Search    next
  640. LOOK:    LXI    D,FCB
  641.     CALL    CPM        ;Read directory    entry
  642.     INR    A        ;Check for end (0FFH)
  643.     JZ    SPRINT        ;If no more, sort & print what we have
  644.  
  645. * Point    to directory entry
  646.  
  647. SOME:    DCR    A        ;Undo prev 'INR A'
  648.     ANI    3        ;Make modulus 4
  649.     ADD    A        ;Multiply...
  650.     ADD    A        ;..by 32 because
  651.     ADD    A        ;..each    directory
  652.     ADD    A        ;..entry is 32
  653.     ADD    A        ;..bytes long
  654.     LXI    H,BASE+81H    ;Point to buffer
  655.                 ;(skip to FN/FT)
  656.     ADD    L        ;Point to entry
  657.     ADI    9        ;Point to SYS byte
  658.     MOV    L,A        ;Save (can't carry to H)
  659.  
  660.     IF    SOPT
  661.     LDA    SOPFLG        ;Did user request SYS files?
  662.     ORA    A
  663.     JZ    SYSFOK
  664.     ENDIF
  665.  
  666.     MOV    A,M        ;Get SYS byte
  667.     ORA    A        ;Check bit 7
  668.     JM    MORDIR        ;Skip that file
  669.  
  670. SYSFOK:    MOV    A,L        ;Go back now
  671.     SUI    10        ;Back to user number (alloc flag)
  672.     MOV    L,A        ;HL points to entry now
  673.  
  674.     LDA    NEWUSR        ;Get current user
  675.     CMP    M
  676.     JNZ    MORDIR        ;Ignore    if different
  677.     INX    H
  678.  
  679. * Move entry to    table
  680.  
  681.     XCHG            ;Entry to DE
  682.     LHLD    NEXTT        ;Next table entry to HL
  683.     MVI    B,12        ;Entry length (name, type, extent)
  684.  
  685. TMOVE:    LDAX    D        ;Get entry char
  686.  
  687.     IF    NOT (VECTOR OR REVIDEO)
  688.     ANI    7FH        ;Remove    attributes
  689.     ENDIF
  690.  
  691.     MOV    M,A        ;Store in table
  692.     INX    D
  693.     INX    H
  694.     DCR    B        ;More?
  695.     JNZ    TMOVE
  696.     INX    D
  697.     INX    D        ;Point to sector count
  698.     LDAX    D        ;Get it
  699.     MOV    M,A        ;Store in table
  700.     INX    H
  701.     SHLD    NEXTT        ;Save updated table addr
  702.     XCHG
  703.     LHLD    COUNT        ;Bump the # of matches made
  704.     INX    H
  705.     SHLD    COUNT
  706.     LXI    H,13        ;Size of next entry
  707.     DAD    D
  708.     XCHG            ;Future    NEXTT is in DE
  709.     LHLD    BDOS+1        ;Pick up TPA end
  710.     MOV    A,E
  711.     SUB    L        ;Compare NEXTT-TPA end
  712.     MOV    A,D
  713.     SBB    H
  714.     JC    MORDIR        ;If TPA    END > NEXTT then loop back for more
  715.  
  716. OUTMEM:    CALL    ERXIT        ;Exit if directory too large
  717.     DB    'MEMOR','Y' OR 80H
  718.  
  719. * Sort and print
  720.  
  721. SPRINT: IF    AOPT OR FOPT OR UOPT
  722.     CALL    SETFOP        ;Return to file output DMA & user #
  723.     ENDIF
  724.  
  725.     LHLD    COUNT        ;Get file name count
  726.     MOV    A,L
  727.     ORA    H        ;Any found?
  728.     JZ    PRTOTL        ;Exit if no files found
  729.     PUSH    H        ;Save file count
  730.     STA    SUPSPC        ;Enable    leading    zero suppression
  731.  
  732. * Initialize the order table
  733.  
  734.     LHLD    TBLOC        ;Get start of name table
  735.     XCHG            ;Into DE
  736.     LXI    H,ORDER        ;Point to order    table
  737.     LXI    B,13        ;Entry length
  738.  
  739. BLDORD:    MOV    M,E        ;Save low order    address
  740.     INX    H
  741.     MOV    M,D        ;Save high order address
  742.     INX    H
  743.     XCHG            ;Table addr to HL
  744.     DAD    B        ;Point to next entry
  745.     XCHG
  746.     XTHL            ;Save tbl addr,    fetch loop counter
  747.     DCX    H        ;Count down loop
  748.     MOV    A,L
  749.     ORA    H        ;More?
  750.     XTHL            ;(restore tbl addr, save counter)
  751.     JNZ    BLDORD        ;Yes, go do another one
  752.     POP    H        ;Clean loop counter off    stack
  753.     LHLD    COUNT        ;Get count
  754.     SHLD    SCOUNT        ;Save as # to sort
  755.     DCX    H        ;Only 1    entry?
  756.     MOV    A,L
  757.     ORA    H
  758.     JZ    DONE        ;Yes, so skip sort
  759.  
  760. * This sort routine is adapted from SOFTWARE TOOLS
  761. * by Kernigan and Plaugher.
  762.  
  763. SORT:    LHLD    SCOUNT        ;Number    of entries
  764.  
  765. L0:    ORA    A        ;Clear carry
  766.     MOV    A,H        ;GAP=GAP/2
  767.     RAR
  768.     MOV    H,A
  769.     MOV    A,L
  770.     RAR
  771.     MOV    L,A
  772.     ORA    H        ;Is it zero?
  773.     JZ    DONE        ;Then none left
  774.     MOV    A,L        ;Make gap odd
  775.     ORI    01
  776.     MOV    L,A
  777.     SHLD    GAP
  778.     INX    H        ;I=GAP+1
  779.  
  780. L2:    SHLD    I
  781.     XCHG
  782.     LHLD    GAP
  783.     MOV    A,E        ;J=I-GAP
  784.     SUB    L
  785.     MOV    L,A
  786.     MOV    A,D
  787.     SBB    H
  788.     MOV    H,A
  789.  
  790. L3:    SHLD    J
  791.     XCHG
  792.     LHLD    GAP        ;JG=J+GAP
  793.     DAD    D
  794.     SHLD    JG
  795.     MVI    A,12        ;Compare 12 chars
  796.     CALL    COMPARE        ;Compare (J) and (JG)
  797.     JP    L5        ;If A(J)<=A(JG)
  798.     LHLD    J
  799.     XCHG
  800.     LHLD    JG
  801.     CALL    SWAP        ;Exchange A(J) and A(JG)
  802.     LHLD    J        ;J=J-GAP
  803.     XCHG
  804.     LHLD    GAP
  805.     MOV    A,E
  806.     SUB    L
  807.     MOV    L,A
  808.     MOV    A,D
  809.     SBB    H
  810.     MOV    H,A
  811.     JM    L5        ;If J>0    GOTO L3
  812.     ORA    L        ;Check for zero
  813.     JZ    L5
  814.     JMP    L3
  815.  
  816. L5:    LHLD    SCOUNT        ;For later
  817.     XCHG
  818.     LHLD    I        ;I=I+1
  819.     INX    H
  820.     MOV    A,E        ;IF I<=N GOTO L2
  821.     SUB    L
  822.     MOV    A,D
  823.     SBB    H
  824.     JP    L2
  825.     LHLD    GAP
  826.     JMP    L0
  827.  
  828. * Sort is all done - print entries
  829.  
  830. DONE:    IF    FOPT        ;If output option wanted, prepare file
  831.     LDA    FOPFLG
  832.     ORA    A
  833.     JNZ    NOOUT        ;If file output, fall through with A=0
  834.  
  835. * IF ALL USER OPTION ENABLED, AND WE'RE NOT ON THE FIRST PASS, THEN THE
  836. * OUTPUT FILE IS ALREADY OPEN AND POSITIONED, SO WE CAN SKIP THE OPEN.
  837.  
  838. ;    IF    AOPT
  839.     lxi    h,opnflg    ;point to output file open flag
  840.     cmp    m        ;a=0, set z if opnflg=0 also
  841.     jnz    noout        ;if opnflg not zero, skip open
  842.     dcr    m        ;else, make opnflg not zero and open
  843. ;    ENDIF            ;Balance AOPT
  844.  
  845. * First pass on file append - prepare SD.DIR to receive new or appended
  846. * output.
  847.  
  848.     LXI    D,OUTFCB    ;Does output file already exist?
  849.     MVI    C,SEARCH
  850.     CALL    CPM
  851.     INR    A
  852.     JNZ    OPENIT        ;If it does, then open it for processing
  853.     MVI    C,MAKE        ;Otherwise, create the output file
  854.     CALL    CPM
  855.     INR    A
  856.     JNZ    NOOUT        ;Continue if open successful
  857.  
  858. * If make or open fails, declare error
  859.  
  860. OPNERR:    CALL    ERXIT
  861.     DB    'OPE','N' OR 80H
  862.  
  863. WRTERR:    CALL    ERXIT
  864.     DB    'WRIT','E' OR 80H
  865.  
  866. * Output file already exists - open it and position to the last
  867. * record of the    last extent.
  868.  
  869. OPENIT: MVI    C,OPEN        ;Open 1st extent of output file
  870.     CALL    CPM
  871.     INR    A
  872.     JZ    OPNERR        ;Bad deal if 1st won't open
  873.  
  874. OPNMOR:    LDA    OUTFCB+15
  875.     CPI    128
  876.     JC    LSTEXT        ;If RC<128, this is last extent
  877.     LXI    H,OUTFCB+12
  878.     INR    M        ;Else, bump to next extent
  879.     MVI    C,OPEN        ;..and try to open it
  880.     CALL    CPM
  881.     INR    A
  882.     JNZ    OPNMOR        ;Continue opening extents til no more
  883.     DCR    M        ;Then, reopen preceding    extent
  884.     MVI    C,OPEN
  885.     CALL    CPM
  886.     LDA    OUTFCB+15    ;Get RC    for the    last extent
  887.  
  888. * At this point, OUTFCB is opened to the last extent of the file,
  889. * so read in the last record in the last extent.
  890.  
  891. LSTEXT:    ORA    A        ;Is this extent    empty?
  892.     JZ    NOOUT        ;If so, then we're starting a clean slate
  893.     DCR    A        ;Normalize record count
  894.     STA    OUTFCB+32    ;Set record number to read
  895.     MVI    C,READ        ;..and read last record    of file
  896.     CALL    CPM
  897.     ORA    A        ;Was read successful?
  898.     JZ    RDOK        ;If so,    proceed    to scan    for EOF    mark
  899. APERR:    CALL    ERXIT
  900.     DB    'APPEN','D' OR 80H
  901.  
  902. * We now have the last record in the file in our buffer.
  903. * Scan the last    record for the EOF mark, indicating where
  904. * we can start adding data.
  905.  
  906. RDOK:    LXI    H,OUTBUF    ;Point to start of output buffer
  907.     MVI    B,128        ;Get length of output buffer
  908. SCAN:    MOV    A,M
  909.     CPI    'Z'-40H        ;Have we found end of file?
  910.     JZ    RESCR        ;If so, save pointers and reset CR
  911.     INX    H
  912.     DCR    B
  913.     JNZ    SCAN        ;Otherwise, keep looking til end of buffer
  914.  
  915. * If we find an explicit EOF mark in the last buffer (or an implied EOF
  916. * if the last record is full), move the FCB record and extent pointers
  917. * back to correct for the read operation so that our first write operation
  918. * will effectively replace the last record of the SD.DIR file.
  919.  
  920. RESCR:    PUSH    H        ;Save EOF buffer pointer
  921.     PUSH    B        ;Save EOF buffer remaining
  922.     LXI    H,OUTFCB+32    ;Get current record again
  923.     DCR    M        ;Dock it
  924.     JP    SAMEXT        ;If CR >=0, we're still in same extent
  925.     LXI    H,OUTFCB+12    ;Else, move to previous    extent
  926.     DCR    M
  927.     MVI    C,OPEN        ;Then, reopen the previous extent
  928.     CALL    CPM
  929.     INR    A
  930.     JZ    APERR        ;Append position error if we can't reopen
  931.     LDA    OUTFCB+15    ;Else, position to last record of extent
  932.     DCR    A
  933.     STA    OUTFCB+32
  934. SAMEXT: POP    PSW        ;Recall where EOF is in buffer
  935.     STA    BUFCNT        ;..and set buffer counter
  936.     POP    H        ;Recall next buffer pointer
  937.     SHLD    BUFPNT        ;.. and set pointer for first addition
  938.  
  939.     ENDIF            ;Balance FOPT
  940.  
  941. NOOUT:    LXI    H,ORDER        ;Initialize order table    pointer
  942.     SHLD    NEXTT
  943.     JMP    NEWLIN        ;Start new line    and output the files
  944.  
  945. * Output the directory files we've matched.
  946.  
  947. ENTRY:    LHLD    COUNT
  948.     DCX    H        ;Dock file count
  949.     SHLD    COUNT
  950.     MOV    A,H        ;Is this the last file?
  951.     ORA    L
  952.     JZ    OKPRNT        ;If COUNT=0, last file so skip compare
  953.  
  954. * Compare each entry to    make sure that it isn't part of a multiple
  955. * extent file.    Go only    when we    have the last extent of    the file.
  956.  
  957.     PUSH    B        ;Save NPL
  958.     CALL    CKABRT        ;Check for abort code from keyboard
  959.     LHLD    NEXTT
  960.     MVI    A,11
  961.     CALL    COMPR        ;Does this entry match next one?
  962.     POP    B        ;Recall    NPL
  963.     JNZ    OKPRNT        ;No, print it
  964.     INX    H
  965.     INX    H        ;Skip since highest extent comes last in list
  966.     SHLD    NEXTT
  967.     JMP    ENTRY        ;Loop back for next lowest extent
  968.  
  969. * Valid    entry obtained - spit it out.
  970.  
  971. OKPRNT:    LHLD    NEXTT        ;Get order table pointer
  972.     MOV    E,M        ;Get low order address
  973.     INX    H
  974.     MOV    D,M        ;Get high order    address
  975.     INX    H
  976.     SHLD    NEXTT        ;Save updated table pointer
  977.     XCHG            ;Table entry to    HL
  978.  
  979.     MVI    B,8        ;File name length
  980.     CALL    TYPEIT        ;Type filename
  981.  
  982.     MVI    A,'.'        ;Period    after FN
  983.     CALL    TYPE
  984.  
  985.     MVI    B,3        ;Display 3 characters of filetype
  986.     CALL    TYPEIT
  987.  
  988. * Compute the size of the file and update our summary datum.
  989.  
  990.     MOV    E,M        ;Get extent #
  991.     MVI    D,0
  992.     INX    H
  993.     MOV    A,M        ;Get sector count of last extent
  994.     XCHG
  995.     DAD    H        ;# of extents times 16k
  996.     DAD    H
  997.     DAD    H
  998.     DAD    H
  999.     XCHG            ;Save in DE
  1000.     LXI    H,BLKMSK
  1001.     ADD    M        ;Round last extent to block size
  1002.     RRC
  1003.     RRC            ;Convert from sectors to K
  1004.     RRC
  1005.     ANI    1FH
  1006.     MOV    L,A        ;Add to    total K
  1007.     MVI    H,0
  1008.     DAD    D
  1009.     LDA    BLKMSK        ;Get SECTORS/BLK-1
  1010.     RRC
  1011.     RRC            ;Convert to K/BLK
  1012.     RRC
  1013.     ANI    1FH
  1014.     CMA            ;Use to    finish rounding
  1015.     ANA    L
  1016.     MOV    L,A
  1017.     XCHG            ;Save file size    in DE
  1018.     LHLD    TOTSIZ
  1019.     DAD    D        ;Add to    total used
  1020.     SHLD    TOTSIZ
  1021.     LHLD    TOTFIL        ;Increment file    count
  1022.     INX    H
  1023.     SHLD    TOTFIL
  1024.     XCHG            ;Get back file size
  1025.  
  1026. * If report size enabled, output the size of the individual file.
  1027.  
  1028.     IF    REPSIZ        ;If file size report wanted
  1029.     CALL    DECPRT        ;..go print it
  1030.     MVI    A,'k'        ;..and follow with K size
  1031.     CALL    TYPE
  1032.     ENDIF
  1033.  
  1034. * One file output - test to see    if we have to output another one.
  1035.  
  1036.     LHLD    COUNT        ;Get current file counter and test it
  1037.     MOV    A,H
  1038.     ORA    L
  1039.     JZ    PRTOTL        ;If no more files, exit    to summary output
  1040.  
  1041. * At least one more file to output - can we put    it on the current line?
  1042.  
  1043.     DCR    C
  1044.     PUSH    PSW
  1045.     CNZ    FENCE        ;If room left, output the fence    character
  1046.     POP    PSW
  1047.     JNZ    ENTRY        ;.. and    go output another file
  1048.  
  1049. * Current line full, start a new one.
  1050.  
  1051. NEWLIN:    MVI    C,NPL        ;Reset names per line counter
  1052.     CALL    CRLF        ;Space down to next line
  1053.  
  1054.     IF    NPL LT 4    ;If printing less than 4 wide ..
  1055.     LDA    FCB        ;.. precede new    line with drive    name
  1056.     ADI    'A'-1
  1057.     CALL    TYPE
  1058.  
  1059.     IF    REPUSR        ;If reporting user numbers and running under
  1060.     CALL    CKVER        ;..CP/M    2, output the user number too
  1061.     CNC    TYPUSR
  1062.     ENDIF            ;Balance REPUSR
  1063.  
  1064.     MVI    A,':'        ;Tag header with a colon and a space
  1065.     CALL    FPAD        ;..and exit back to ENTRY
  1066.  
  1067.     ENDIF            ;Balance NPL GT    3
  1068.  
  1069.     JMP    ENTRY        ;Go back and output another file
  1070.  
  1071. * Print    HL in decimal with leading zero    suppression
  1072.  
  1073. DECPRT:    SUB    A        ;Clear leading zero flag
  1074.     STA    LZFLG
  1075.     LXI    D,-1000        ;Print 1000's digit
  1076.     CALL    DIGIT
  1077.     LXI    D,-100        ;Etc.
  1078.     CALL    DIGIT
  1079.     LXI    D,-10
  1080.     CALL    DIGIT
  1081.     MVI    A,'0'        ;Get 1's digit
  1082.     ADD    L
  1083.     JMP    TYPE
  1084.  
  1085. DIGIT:    MVI    B,'0'        ;Start off with    ASCII 0
  1086.  
  1087. DIGLP:    PUSH    H        ;Save current remainder
  1088.     DAD    D        ;Subtract
  1089.     JNC    DIGEX        ;Quit on overflow
  1090.     POP    PSW        ;Throw away remainder
  1091.     INR    B        ;Bump digit
  1092.     JMP    DIGLP        ;Loop back
  1093.  
  1094. DIGEX:    POP    H        ;Restore pointer
  1095.     MOV    A,B
  1096.     CPI    '0'        ;Zero digit?
  1097.     JNZ    DIGNZ        ;No, type it
  1098.     LDA    LZFLG        ;Leading zero?
  1099.     ORA    A
  1100.     MVI    A,'0'
  1101.     JNZ    TYPE        ;Print digit
  1102.     LDA    SUPSPC        ;Get space suppression flag
  1103.     ORA    A        ;See if    printing file totals
  1104.     RZ            ;Yes, don't give leading spaces
  1105.     JMP    SPACE        ;Leading zero...print space
  1106.  
  1107. DIGNZ:    STA    LZFLG        ;Set leading zero flag so next zero prints
  1108.     JMP    TYPE        ;And print digit
  1109.  
  1110. * Show total space and files used
  1111.  
  1112. PRTOTL:    XRA    A        ;Get a zero to...
  1113.     STA    SUPSPC        ;Suppress leading spaces in totals
  1114.  
  1115.     LHLD    TOTFIL        ;How many files    did we match?
  1116.     MOV    A,H
  1117.     ORA    L
  1118.  
  1119.     JZ    NXTUSR        ;Skip the summary if we    didn't find any
  1120.  
  1121.     PUSH    H        ;Save TOTFIL
  1122.     STA    FNDFLG        ;Set file found flag
  1123.  
  1124.     LXI    D,TOTMS1    ;Print [CR,LF,LF]"DRIVE    "
  1125.     CALL    PRINT
  1126.     LDA    FCB
  1127.     ADI    'A'-1
  1128.     CALL    TYPE        ;Output    the drive code
  1129.  
  1130.     IF    REPUSR
  1131.     CALL    CKVER
  1132.     JC    NOUSER
  1133.     LXI    D,TOTMS2    ;Print ", USER "
  1134.     CALL    PRINT
  1135.     CALL    TYPUSR        ;Output    the user number
  1136.     ENDIF
  1137.  
  1138. NOUSER:    LXI    D,TOTMS3    ;Print " CONTAINS "
  1139.     CALL    PRINT
  1140.     LHLD    TOTSIZ        ;Print total K used by files matched
  1141.     CALL    DECPRT
  1142.     LXI    D,TOTMS4    ;PRINT "K IN "
  1143.     CALL    PRINT
  1144.     POP    H        ;Recall    TOTFIL
  1145.     CALL    DECPRT        ;Print number of files matched
  1146.     LXI    D,TOTMS5    ;Print " FILES WITH "
  1147.     CALL    PRINT
  1148.     CALL    PRTFRE        ;Output    free space remaining & " FREE."
  1149.  
  1150. * Directory for    one user area completed.  If all users option is
  1151. * selected, then go do another directory on the    next user number
  1152. * until    we exceed the maximum user # for the selected drive.
  1153.  
  1154. NXTUSR:    IF    AOPT        ;If all    users option enabled
  1155.     LDA    AOPFLG        ;If not    all users mode - skip next
  1156.     ORA    A
  1157.     JNZ    GOCLZ
  1158.     CALL    CKVER        ;Are we running CP/M 2?
  1159.     JC    GOCLZ        ;Skip user increment if not
  1160.     CALL    CKABRT        ;Check for user    abort first
  1161.     LDA    MAXUSR        ;No abort - get    maximum    user number
  1162.     LXI    H,NEWUSR    ;Bump directory    user number
  1163.     INR    M
  1164.     CMP    M        ;Does next user    # exceed maximum?
  1165.     JNC    SETTBL        ;Continue if more user areas to    go
  1166.  
  1167.     IF    DOPT        ;If multi-disk option enabled
  1168.     LDA    BASUSR        ;Reset base user number    for the
  1169.     MOV    M,A        ;..next    directory search
  1170.     ENDIF            ;Balance DOPT
  1171.  
  1172.     ENDIF            ;Balance AOPT
  1173.  
  1174. * We've finished all of our outputting.  Flush the remainder of the
  1175. * output buffer and close the file before going to exit routine.
  1176.  
  1177. GOCLZ:    IF    FOPT
  1178. ;    LDA    FOPFLG        ;Is file output mode active?
  1179. ;    ORA    A
  1180. ;    JNZ    NXTDSK        ;If not, move to next drive, otherwise ..
  1181. ;    STA    PASS1        ;Make PASS1=0 to force reopen on next drive
  1182.  
  1183.     lxi    h,opnflg    ;get file open status then reset flag to
  1184.     mov    a,m        ;..force reopen on next pass
  1185.     mvi    m,0
  1186.     ora    a
  1187.     jz    nxtdsk        ;skip closing sd.dir if it wasn't opened
  1188.  
  1189.     LXI    H,BUFCNT
  1190.     MOV    A,M        ;RETRIEVE # OF UNFLUSHED CHARACTERS IN BUFFER
  1191.     MVI    M,128        ;FORCE BUFCNT TO EMPTY STATUS FOR NEXT DRIVE
  1192.     ORA    A        ;IF BUFCNT=128, BUFFER EMPTY SO SET SIGN BIT
  1193.     jm    cloze        ;close sd.dir if buffer is empty
  1194.     jz    flush        ;write last record to sd.dir if buffer full
  1195.  
  1196.     LHLD    BUFPNT        ;OTHERWISE, PAD UNUSED BUFFER WITH CTRL-ZS
  1197. PUTAGN:    MVI    M,'Z'-40H
  1198.     INX    H
  1199.     DCR    A
  1200.     JNZ    PUTAGN        ;CONTINUE PADDING TIL BUFFER FILLED OUT
  1201. ;    MVI    A,128
  1202. ;    STA    BUFCNT        ;Force buffer to empty status
  1203.  
  1204. FLUSH:    LXI    D,OUTFCB    ;FLUSH THE LAST OUTPUT BUFFER
  1205.     MVI    C,WRITE
  1206.     CALL    CPM
  1207.     ORA    A
  1208.     JNZ    WRTERR
  1209. CLOZE:    LXI    D,OUTFCB    ;CLOSE THE OUTPUT FILE
  1210.     MVI    C,CLOSE
  1211.     CALL    CPM
  1212.     ENDIF            ;BALANCE FOPT
  1213.  
  1214. * Directory for    all user areas completed.  If the multi-disk option
  1215. * is enabled and selected, reset to the    base user area and repeat
  1216. * the directory    for next drive on-line until we    either exceed the
  1217. * drives in our    LODRV-HIDRV table, or the BDOS shuts us    down with
  1218. * a select or bad sector error,    which will be intercepted back to
  1219. * the EXIT module.
  1220.  
  1221. NXTDSK: LXI    H,FNDFLG    ;Get file found flag
  1222.     MOV    A,M
  1223.     MVI    M,0        ;Clear file found flag for next drive
  1224.     ORA    A
  1225.     JNZ    NDSK        ;Continue if at least 1 file found
  1226.  
  1227.     IF    FOPT        ;If file output enabled, disable temporarily
  1228.     LXI    H,FOPFLG
  1229.     DCR    M
  1230.     PUSH    H
  1231.     ENDIF
  1232.  
  1233.     LDA    FCB        ;Stash ASCII directory drive in NO FILE msg
  1234.     ADI    'A'-1
  1235.     STA    NOFMS2
  1236.     LXI    D,NOFMS1    ;Print "NO FILE ON ? - "
  1237.     CALL    PRINT
  1238.     CALL    PRTFRE        ;Tag with free message
  1239.  
  1240.     IF    FOPT        ;Restore original file output mode
  1241.     POP    H
  1242.     INR    M
  1243.     ENDIF
  1244.  
  1245. NDSK:    IF    DOPT        ;If multi-disk option enabled
  1246.     LDA    DOPFLG        ;If multi-disk not selected - skip next
  1247.     ORA    A
  1248.     JNZ    EXIT
  1249.     CALL    CKABRT        ;Check for user    abort first
  1250.     MVI    A,HIDRV-LODRV    ;Get maximum drive code    to search
  1251.     LXI    H,FCB        ;Bump directory    FCB drive code
  1252.     INR    M
  1253.     CMP    M        ;Does next disk    exceed maximum?
  1254.     JNC    NOOPT        ;Search    next disk if not
  1255.     ENDIF            ;Balance DOPT
  1256.  
  1257.     JMP    EXIT        ;All done - exit to CCP
  1258.  
  1259. * Print    the user number    of the directory in decimal
  1260.  
  1261. TYPUSR:    IF    REPUSR
  1262.     LDA    NEWUSR
  1263.     CPI    10        ;If user no. > 9 print leading 1
  1264.     JC    DUX
  1265.     MVI    A,'1'
  1266.     CALL    TYPE
  1267.     LDA    NEWUSR        ;Print low digit of user no.
  1268.     SUI    10
  1269. DUX:    ADI    '0'
  1270.     JMP    TYPE
  1271.     ENDIF
  1272.  
  1273. * Force    new line on video and check for    page pause
  1274.  
  1275. CRLF:    MVI    A,0DH        ;Send CR
  1276.     CALL    TYPE
  1277.     MVI    A,0AH        ;Send LF
  1278.     JMP    TYPE        ;Exit to caller    from TYPE
  1279.  
  1280. * Separate the directory output    on a line with a space,    the delimiter,
  1281. * followed by another space.
  1282.  
  1283. FENCE:    CALL    SPACE
  1284.  
  1285.     MVI    A,DELIM        ;Fence character
  1286. FPAD:    CALL    TYPE        ;Print it, fall    into space
  1287.  
  1288. SPACE:    MVI    A,' '        ;Fall through to TYPE
  1289.  
  1290. * Output character in A to console, and optionally to printer and/or
  1291. * the output file.
  1292.  
  1293. TYPE:    PUSH    B
  1294.     PUSH    D
  1295.     PUSH    H
  1296.  
  1297.     PUSH    PSW        ;Save the character to output
  1298.     CALL    TYPE1        ;Send it to console
  1299.     POP    PSW        ;Restore the output character
  1300.     ANI    7FH        ;Strip parity bit on character
  1301.  
  1302. * Test file output mode and skip to page pause test if not active.
  1303.  
  1304.     IF    FOPT
  1305.     MOV    B,A        ;Save stripped character to B
  1306.     LDA    FOPFLG        ;Is file output    active?
  1307.     ORA    A
  1308.     JNZ    NOWRIT        ;Go check for page pause if not
  1309.  
  1310. * File output mode active - make sure we have room in buffer to add
  1311. * next character.  If buffer full, write out current record first
  1312. * and then start a new record with current character.
  1313.  
  1314.     LHLD    BUFPNT        ;Get current buffer pointer
  1315.     LDA    BUFCNT        ;Get buffer capacity remaining
  1316.     ORA    A
  1317.     JNZ    PUTBUF        ;Continue if buffer not full
  1318.     LXI    D,OUTFCB    ;Otherwise, write the current buffer out
  1319.     MVI    C,WRITE
  1320.     CALL    CPM        ;(Note call must save character    in B)
  1321.     ORA    A
  1322.     JNZ    WRTERR        ;Take write error exit if disk full or R/O
  1323.     LXI    H,OUTBUF    ;Reset buffer pointer
  1324.     MVI    A,128        ;Reset buffer capacity
  1325.  
  1326. PUTBUF: MOV    M,B        ;Shove character to next buffer position
  1327.     INX    H        ;Bump buffer pointer
  1328.     SHLD    BUFPNT        ;.. and save it
  1329.     DCR    A        ;Dock count of characters left in buffer
  1330.     STA    BUFCNT        ;..and save it
  1331.  
  1332. NOWRIT:    MOV    A,B        ;Recall    stripped character
  1333.  
  1334.     ENDIF            ;Balance FOPT
  1335.  
  1336.     IF    POPT        ;If printer option
  1337.     ANI    7FH        ;Strip parity bit on character
  1338.     MOV    E,A        ;Setup list output call
  1339.     MVI    C,5
  1340.     LDA    POPFLG        ;Test printer flag
  1341.     ORA    A
  1342.     CZ    CPM        ;Print character if flag true
  1343.     MOV    A,E        ;Recall    character
  1344.     ENDIF
  1345.  
  1346.     IF    PGPAWZ
  1347.     CPI    0AH        ;Do we have a LF?
  1348.     JNZ    TYPRET        ;Exit if not
  1349.     ENDIF
  1350.  
  1351.     IF    NOPT AND PGPAWZ
  1352.     LDA    NOPFLG        ;Is the    page pause function disabled?
  1353.     ORA    A
  1354.     JZ    TYPRET        ;Exit if so
  1355.     ENDIF
  1356.  
  1357.     IF    PGPAWZ
  1358.     LDA    LINCNT        ;Get line count
  1359.     INR    A        ;Bump it
  1360.     CPI    LPS        ;Are we    at the end of the screen?
  1361.     JC    NOTEOS        ;Skip if not
  1362.     LXI    D,EOSMSG    ;Else, display pause message
  1363.     MVI    C,9        ;..without checking for    LFs
  1364.     CALL    BDOS
  1365.     CALL    CINPUT        ;Wait for character
  1366.     CPI    'C'-40H
  1367.     JZ    EXIT        ;Abort on CTRL-C
  1368.     XRA    A        ;Reset line count
  1369. NOTEOS:    STA    LINCNT        ;Save new line count
  1370.     ENDIF
  1371.  
  1372. TYPRET:    POP    H        ;Exit from TYPE
  1373.     POP    D
  1374.     POP    B
  1375.     RET
  1376.  
  1377. * Output character
  1378.  
  1379. TYPE1:    IF    VECTOR
  1380.     ORA    A        ;Set sign flag if MS bit is on
  1381.     JP    TYPE2        ;If character is ASCII,    continue
  1382.     MOV    B,A        ;Else, get character to    B
  1383.     MVI    A,5        ;Set video driver function for direct output
  1384.     JMP    VIDEO        ;Display in reverse video and exit from    VIDEO
  1385.     ENDIF
  1386.  
  1387. TYPE2:    IF    REVIDEO
  1388.     ORA    A
  1389.     JP    TYPE99
  1390.     PUSH    PSW
  1391.     MVI    A,LEADIN        ;Send ESC char first
  1392.     CALL    TYPE99
  1393.     MVI    A,INTOREV
  1394.     CALL    TYPE99
  1395.     POP    PSW        ;Retrieve character
  1396.     ANI    7FH
  1397.     CALL    TYPE99
  1398.     MVI    A,LEADIN
  1399.     CALL    TYPE99
  1400.     MVI    A,OUTAREV
  1401. TYPE99:
  1402.     ENDIF            ;Balance REVIDEO
  1403.  
  1404.     IF    DIRCON
  1405.     MOV    C,A        ;Get character into BIOS entry register
  1406.     LHLD    BASE+1        ;Get page base of BIOS
  1407.     MVI    L,12        ;Get entry vector to CONOUT
  1408.     JMP    GOHL        ;Call CONOUT direct through the BIOS
  1409.     ELSE
  1410.  
  1411.     MOV    E,A        ;Get character into BDOS entry register
  1412.     MVI    C,WRCHR
  1413.     JMP    BDOS        ;Call CONOUT via the BDOS
  1414.     ENDIF            ;Balance DIRCON
  1415.  
  1416.  
  1417. * Print    a string at HL of length B
  1418.  
  1419. TYPEIT:    MOV    A,M
  1420.     CALL    TYPE
  1421.     INX    H
  1422.     DCR    B
  1423.     JNZ    TYPEIT
  1424.     RET
  1425.  
  1426. * Print    string terminated with last byte high on console.
  1427.  
  1428. PRINT:    LDAX    D
  1429.     PUSH    PSW
  1430.     ANI    7FH
  1431.     CALL    TYPE
  1432.     POP    PSW
  1433.     ORA    A
  1434.     RM
  1435.     INX    D
  1436.     JMP    PRINT
  1437.  
  1438. * Fetch    character from console (without    echo)
  1439.  
  1440. CINPUT:    LHLD    BASE+1
  1441.     MVI    L,9
  1442.     CALL    GOHL
  1443.     ANI    7FH
  1444.     RET
  1445.  
  1446. * Check    for a CTRL-C or    CTRL-S entered from the    keyboard.  Jump    to
  1447. * exit if CTRL-C, pause    on CTRL-S.
  1448.  
  1449. CKABRT:    LHLD    BASE+1
  1450.     MVI    L,6        ;Check status of keyboard
  1451.     CALL    GOHL        ;Any key pressed?
  1452.     ORA    A
  1453.     RZ            ;No, return to caller
  1454.     CALL    CINPUT        ;Get character
  1455.     CPI    'C'-40H        ;CTRL-C?
  1456.     JZ    EXIT        ;If CTRL-C then    quit
  1457.     CPI    'S'-40H        ;CTRL-S?
  1458.     RNZ            ;No, return to caller
  1459.     CALL    CINPUT        ;Yes, wait for another char.
  1460.     CPI    'C'-40H        ;Might be CTRL-C
  1461.     JZ    EXIT        ;Exit if CTRL-C, else fall thru    and continue
  1462.     RET
  1463.  
  1464. * Kludge to allow call to address in HL
  1465.  
  1466. GOHL:    PCHL
  1467.  
  1468. * Entry    to BDOS    saving all extended registers
  1469.  
  1470. CPM:    PUSH    B
  1471.     PUSH    D
  1472.     PUSH    H
  1473.     CALL    BDOS
  1474.     POP    H
  1475.     POP    D
  1476.     POP    B
  1477.     RET
  1478.  
  1479. * For file output mode,    return to old user area    and set    DMA for
  1480. * the file output buffer.
  1481.  
  1482. SETFOP:    IF    UOPT OR    AOPT
  1483.     CALL    CKVER        ;Clear carry if    CP/M 2 or later
  1484.     LDA    OLDUSR        ;Get user number at startup
  1485.     MOV    E,A
  1486.     MVI    C,CURUSR
  1487.     CNC    CPM        ;Reset the old user number if CP/M 2
  1488.     ENDIF
  1489.  
  1490.     IF    FOPT
  1491.     LXI    D,OUTBUF    ;Move DMA from search buffer into the
  1492.     JMP    SET2        ;..output buffer
  1493.     ENDIF
  1494.     RET
  1495.  
  1496. * Move disk buffer DMA to default buffer for directory search operations
  1497. * and BDOS media change routines (necessary for pre-CP/M 2 systems while
  1498. * in file output mode with an active buffer).
  1499.  
  1500. SETSRC: LXI    D,BASE+80H
  1501. SET2:    MVI    C,SETDMA
  1502.     JMP    CPM
  1503.  
  1504. * Print    the amount of free space remaining on the selected drive
  1505.  
  1506. PRTFRE: LHLD    FREEBY        ;Get space left before adding to MASTER.DIR
  1507.     CALL    DECPRT        ;Print K free
  1508.     LXI    D,TOTMS6    ;Print " FREE."
  1509.     JMP    PRINT
  1510.  
  1511. * Compare routine for sort
  1512.  
  1513. COMPR:    PUSH    H        ;Save table addr
  1514.     MOV    E,M        ;Load low order
  1515.     INX    H
  1516.     MOV    D,M        ;Load high order
  1517.     INX    H
  1518.     MOV    C,M
  1519.     INX    H
  1520.     MOV    B,M
  1521.  
  1522. * BC, DE now point to entries to be compared
  1523.  
  1524.     XCHG
  1525.     MOV    E,A        ;Get count
  1526.  
  1527. CMPLP:    MOV    A,M
  1528.     ANI    7FH
  1529.     MOV    D,A
  1530.     LDAX    B
  1531.     ANI    7FH
  1532.     CMP    D
  1533.     INX    H
  1534.     INX    B
  1535.     JNZ    NOTEQL        ;Quit on mismatch
  1536.     DCR    E        ;Or end    of count
  1537.     JNZ    CMPLP
  1538.  
  1539. NOTEQL:    POP    H
  1540.     RET            ;Cond code tells all
  1541.  
  1542. * Swap entries in the order table
  1543.  
  1544. SWAP:    LXI    B,ORDER-2    ;Table base
  1545.     DAD    H        ;*2
  1546.     DAD    B        ;+ base
  1547.     XCHG
  1548.     DAD    H        ;*2
  1549.     DAD    B        ;+ base
  1550.     MOV    C,M
  1551.     LDAX    D
  1552.     XCHG
  1553.     MOV    M,C
  1554.     STAX    D
  1555.     INX    H
  1556.     INX    D
  1557.     MOV    C,M
  1558.     LDAX    D
  1559.     XCHG
  1560.     MOV    M,C
  1561.     STAX    D
  1562.     RET
  1563.  
  1564. * New compare routine
  1565.  
  1566. COMPARE:LXI    B,ORDER-2
  1567.     DAD    H
  1568.     DAD    B
  1569.     XCHG
  1570.     DAD    H
  1571.     DAD    B
  1572.     XCHG
  1573.     MOV    C,M
  1574.     INX    H
  1575.     MOV    B,M
  1576.     XCHG
  1577.     MOV    E,M
  1578.     INX    H
  1579.     MOV    D,M
  1580.     XCHG
  1581.     MOV    E,A        ;Count
  1582.  
  1583. CMPLPE:    MOV    A,M
  1584.     ANI    7FH
  1585.     MOV    D,A
  1586.     LDAX    B
  1587.     ANI    7FH
  1588.     CMP    D
  1589.     INX    B
  1590.     INX    H
  1591.     RNZ
  1592.     DCR    E
  1593.     JNZ    CMPLPE
  1594.     RET
  1595.  
  1596. * Error    exit
  1597.  
  1598. ERXIT:    IF    FOPT
  1599.     MVI    A,-1
  1600.     STA    FOPFLG        ;Disable file output mode on error
  1601.     ENDIF
  1602.  
  1603.     CALL    CRLF        ;Space down
  1604.     POP    D        ;Get pointer to    message    string
  1605.     CALL    PRINT        ;Print it
  1606.     LXI    D,ERRMS1    ;Print " ERROR"
  1607.     CALL    PRINT
  1608.     CALL    CRLF        ;Space down
  1609.  
  1610. * Exit - all done, restore stack
  1611.  
  1612. EXIT:    MVI    C,CONST        ;Check console status
  1613.     CALL    CPM
  1614.     ORA    A        ;Char waiting?
  1615.     MVI    C,RDCHR
  1616.     CNZ    CPM        ;Gobble    up char
  1617.  
  1618.     IF    DOPT        ;Restore BDOS intercept    vectors
  1619.     LDA    DOPFLG        ;..if they were swapped
  1620.     ORA    A
  1621.     CZ    SWAPEM
  1622.     ENDIF
  1623.  
  1624.     IF    ROPT
  1625.     LDA    ROPFLG        ;If disk system    was reset
  1626.     ORA    A
  1627.     LDA    OLDDSK        ;Get default disk at startup
  1628.     MOV    E,A
  1629.     MVI    C,SELDSK    ;Reselect it
  1630.     CZ    CPM
  1631.     ENDIF            ;Balance ROPT
  1632.  
  1633.     LHLD    STACK        ;Get old stack pointer
  1634.     SPHL            ;Move back to old stack
  1635.     RET            ;..and return to CCP
  1636.  
  1637. * Exchange BDOS    select and sector error    vectors    for our    own intercept
  1638. * vectors so we    can catch a reference to an illegal drive.
  1639.  
  1640.     IF    DOPT
  1641. SWAPEM:    LHLD    BDOS+1        ;Get pointer to    base of    BDOS
  1642.     MOV    A,L
  1643.     SUI    6        ;Check if pointing directly to BDOS
  1644.     JZ    SWAPOK        ;Continue if true
  1645.     MVI    A,'d'        ;Undo option request for multi-disk
  1646.     STA    DOPFLG
  1647. SWAPOK:    MVI    L,9        ;Point to sector error vector
  1648.     LXI    D,VECTBL    ;Exchanging with our own vector    table
  1649.     MVI    A,4        ;4 bytes to swap
  1650. SWAPLP:    MOV    B,M        ;Get byte from HL
  1651.     XCHG
  1652.     MOV    C,M        ;Get byte from DE
  1653.     MOV    M,B        ;Put byte from HL
  1654.     XCHG
  1655.     MOV    M,C        ;Put byte from DE
  1656.     INX    H        ;Bump exchange pointers
  1657.     INX    D
  1658.     DCR    A        ;Dock counter
  1659.     JNZ    SWAPLP        ;Continue swapping til done
  1660.     RET
  1661.     ENDIF
  1662.  
  1663. * Check    CP/M version number.  Return carry flag    set if pre-CP/M    2.
  1664. * If CP/M 2 or later or    MP/M (any version), return carry clear.
  1665.  
  1666. CKVER:    LDA    VERFLG
  1667.     CPI    20H
  1668.     RET
  1669.  
  1670. * Recovery point from intercepted BDOS select and bad sector errors.
  1671.  
  1672. DSKERR: IF    DOPT
  1673.     LXI    SP,STACK    ;Get out of BDOS' stack
  1674.     JMP    EXIT        ;..and exit back to CCP
  1675.     ENDIF
  1676.  
  1677. ***********************
  1678. *              *
  1679. * End of Program Code *
  1680. *              *
  1681. ***********************
  1682.  
  1683. * Initialized data area
  1684.  
  1685. DREMSG:    DB    'Driv','e' OR 80H
  1686.  
  1687.     IF    PGPAWZ
  1688. EOSMSG: DB    '[ More ]',0DH,'$'
  1689.     ENDIF
  1690.  
  1691. ERRMS1: DB    ' '
  1692. ERRMS2:    DB    'ERRO','R' OR 80H
  1693.  
  1694.     IF    REPERR
  1695. ERRTAG:    DB    ' -','>' OR 80H
  1696.     ENDIF
  1697.  
  1698. NOFMS1: DB    0DH,0AH,'NO FILE on '
  1699. NOFMS2: DB    '  -',' ' OR 80H
  1700.  
  1701. TOTMS1:    DB    0DH,0AH,'->Drive',' ' OR 80H
  1702.  
  1703.     IF    REPUSR
  1704. TOTMS2:    DB    ', user',' ' OR    80H
  1705.     ENDIF
  1706.  
  1707. TOTMS3:    DB    ' contains',' '    OR 80H
  1708. TOTMS4: DB    'K in',' ' OR 80H
  1709. TOTMS5:    DB    ' files with',' ' OR 80H
  1710. TOTMS6: DB    'K fre','e' OR 80H
  1711. USRMSG: DB    'User ','#' OR 80H
  1712.  
  1713. FNDFLG: DB    0        ;Flag whether any files matched
  1714.  
  1715.     IF    PGPAWZ
  1716. LINCNT:    DB    0        ;Count of lines    printed    on screen
  1717.     ENDIF
  1718.  
  1719. * Drive    code/user area lookup table
  1720.  
  1721. * Note that the    LODRV-HIDRV table is included here fully configured.
  1722. * For your own use, you    should change the maximum user areas as
  1723. * appropriate for each drive on    your system, and then delete any
  1724. * DBs referencing drives that don't exist.  Note also that there
  1725. * are only 16 user areas available under CP/M 2, so the highest
  1726. * legal user area you can specify is 15 (range 0-15 = 16 areas).
  1727. * The program will convert anything over 15 into mod 15.
  1728.  
  1729. LODRV    EQU    $        ;Mark beginning    of drive/user table
  1730.  
  1731.     DB    6        ;Maximum user area for Drive A
  1732.     DB    6        ;   "      "    "    "     "   B
  1733.     DB    6        ;   "      "    "    "     "   C
  1734.     DB    6        ;   "      "    "    "     "   D
  1735.     DB    6        ;   "      "    "    "     "   E
  1736.     DB    6        ;   "      "    "    "     "   F
  1737. ;    DB    15        ;   "      "    "    "     "   G
  1738. ;    DB    15        ;   "      "    "    "     "   H
  1739. ;    DB    15        ;   "      "    "    "     "   I
  1740. ;    DB    15        ;   "      "    "    "     "   J
  1741. ;    DB    15        ;   "      "    "    "     "   K
  1742. ;    DB    15        ;   "      "    "    "     "   L
  1743. ;    DB    15        ;   "      "    "    "     "   M
  1744. ;    DB    15        ;   "      "    "    "     "   N
  1745. ;    DB    15        ;   "      "    "    "     "   O
  1746. ;    DB    15        ;   "      "    "    "     "   P
  1747.  
  1748. HIDRV    EQU    $        ;Mark end of drive/user    table
  1749.  
  1750. * Option field lookup table.
  1751. * Note that you    can force any of these options as a DEFAULT by
  1752. * changing the letter for the option into a zero (assuming that
  1753. * its enabling equate is true).     Each option that you hard-wire    in
  1754. * this manner will no longer be    recognized as a    command    line OPTION,
  1755. * and if you redundantly key it in, SD will flag it as unrecognized.
  1756.  
  1757. OTBL    EQU    $        ;Mark start of option table
  1758.  
  1759.     IF    AOPT        ;All users-option flag
  1760. AOPFLG:    DB    'A'
  1761.     ENDIF
  1762.  
  1763.     IF    DOPT        ;Multi-disk-option flag
  1764. DOPFLG:    DB    'D'
  1765.     ENDIF
  1766.  
  1767.     IF    FOPT        ;File-output-option flag
  1768. FOPFLG:    DB    'F'
  1769.     ENDIF
  1770.  
  1771.     IF    NOPT AND PGPAWZ    ;No page-pause option flag
  1772. NOPFLG:    DB    'N'
  1773.     ENDIF
  1774.  
  1775.     IF    POPT        ;Printer option    flag
  1776. POPFLG:    DB    'P'
  1777.     ENDIF
  1778.  
  1779.     IF    ROPT        ;Reset option flag
  1780. ROPFLG:    DB    'R'
  1781.     ENDIF
  1782.  
  1783.     IF    SOPT        ;System    file option flag
  1784. SOPFLG:    DB    'S'
  1785.     ENDIF
  1786.  
  1787. OEND    EQU    $        ;Mark end of option table
  1788.  
  1789. * End of option    lookup table
  1790.  
  1791. ;    IF    AOPT
  1792. ;PASS1: DB    0        ;First pass flag for all user file output
  1793. ;    ENDIF
  1794.  
  1795.     IF    DOPT
  1796. VECTBL: DW    DSKERR        ;BDOS SECTOR ERROR INTERCEPT VECTOR
  1797.     DW    DSKERR        ;BDOS SELECT ERROR INTERCEPT VECTOR
  1798.     ENDIF
  1799.  
  1800.     IF    FOPT
  1801. BUFPNT: DW    OUTBUF        ;POINTER TO NEXT LOCATION IN OUTPUT BUFFER
  1802. BUFCNT: DB    128        ;NUMBER OF BYTES LEFT IN OUTPUT BUFFER
  1803. opnflg: db    0        ;file open flag for all user file output
  1804. OUTFCB:    DB    0,'SD      DIR'
  1805.     FILL    21,0        ;REST OF SD.DIR FCB
  1806. OUTBUF    DS    128        ;OUTPUT FILE BUFFER
  1807.     ENDIF
  1808.  
  1809. * Uninitialized    data area
  1810.  
  1811. BASUSR    DS    1        ;Dupe of original directory user # to search
  1812. BLKMAX    DS    2        ;Highest block # on drive
  1813. BLKMSK    DS    1        ;SEC/BLK - 1
  1814. BLKSHF    DS    1        ;# shifts to mult by SEC/BLK
  1815. COUNT    DS    2        ;Entry count
  1816. DIRMAX    DS    2        ;Highest file #    in directory
  1817. FREEBY    DS    2        ;Contains number of K left on directory    drive
  1818. GAP    DS    2        ;Sort routine storage
  1819. I    DS    2        ;Sort routine storage
  1820. J    DS    2        ;Sort routine storage
  1821. JG    DS    2        ;Sort routine storage
  1822. LZFLG    DS    1        ;0 when    printing leading zeros
  1823. MAXUSR    DS    1        ;Maximum user #    for drive from lookup table
  1824. NEWUSR    DS    1        ;Contains user number selected by "$U" option
  1825. NEXTT    DS    2        ;Next table entry
  1826. OLDDSK    DS    1        ;Holder    for currently logged-in    drive
  1827. OLDUSR    DS    1        ;Contains user number upon invocation
  1828. SCOUNT    DS    2        ;# to sort
  1829. SUPSPC    DS    1        ;Leading space flag for    decimal    routine
  1830. TBLOC    DS    2        ;Pointer to start of name table
  1831. TEMP    DS    2        ;Save dir entry
  1832. TOTFIL    DS    2        ;Total number of files
  1833. TOTSIZ    DS    2        ;Total size of all files
  1834. VERFLG    DS    1        ;CP/M version number (0=pre-CP/M 2)
  1835.  
  1836.     DS    60        ;Stack area
  1837. STACK    DS    2        ;Save old stack    pointer    here
  1838.  
  1839. ORDER    EQU    $        ;Order table starts here
  1840.  
  1841.     END
  1842.