home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol060 / sd-42.asm < prev    next >
Assembly Source File  |  1984-04-29  |  48KB  |  1,822 lines

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