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