home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol145 / sd-48b.asm < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  62.5 KB  |  2,568 lines

  1. * Date 08/10/83  18:22      HM VAN TASSELL REVISION-B
  2.  
  3. ; Made several changes to make SD more useful and friendly to me and maybe
  4. ; to others. Added HELP if // is filename or if a bad option specified.
  5. ; Changed so will always start with drive A: if D option choosen and no
  6. ; drive is specified in command line, user = 0 if A option choosen and no
  7. ; user was specified as an option,-see the new STARTZ, ZUSR & ZDRV.
  8. ; Added STSKIP & SKIPTO to skip over drives that dont exist but are in
  9. ; drive table. Useful for some of us that use M: to specify memory drive.
  10. ; To more closely conform to Digial Research notation used in CP/M PLUS,
  11. ; changed from "$" to "[]" to indicate options and eliminated need for a
  12. ; leading space and allow the use of either space or comma between options.
  13. ; Added code for 3 byte INTO/OUTA reverse video so can use esc,G,x code to
  14. ; indicate file attributes. Since directorys can be long, added a message 
  15. ; at start of each section, see STMSG equate. Added option 'T' which is
  16. ; a sort by filetype and then by filename, TOPREV reverses 'T' option.
  17.  
  18. ; NOTE: Edit help message at start of code to match your choice of options
  19.  
  20. *             SD.ASM Ver 4.8A
  21. *              (Rev 14 MAY 83)
  22. *
  23. *            SUPER DIRECTORY PROGRAM
  24. *               by Bruce    R. Ratoff
  25. *
  26. *        Based on 'DIRS' by Keith Petersen, W8SDZ
  27. *
  28. * Displays the directory of a CP/M disk, sorted    alphabetically,
  29. * with the file    size in    K, rounded to the nearest CP/M block size.
  30. *
  31. * This latest variation    on a common theme will automatically adjust
  32. * itself for any block size and    directory length under CP/M 1.4    or 2.x
  33. * or MP/M (any version).  Provisions are made for (1) automatic    pauses
  34. * when the screen fills    up; (2)    searching individual or    multiple drives
  35. * and/or user areas; (3) unconditional or optionally resetting the disk
  36. * system before    execution begins; (4) directing    output to a disk file
  37. * and appending    to it on subsequent runs; (5) summary line output giving
  38. * drive    and user information, #    of files matched and how much space they
  39. * consume, and the amount of free space    remaining on the disk; (6) displaying
  40. * or suppressing CP/M 2    "system" files;    (7) accepting ambiguous    filenames
  41. * with or without a drive name;    and (8)    printer    output.
  42.  
  43. * See SD.DOC for detailed instructions on configuring and running SD.ASM
  44. *
  45. * ==========================================================================
  46. *
  47. *        NOTE: If you add improvements or otherwise update
  48. *        this program, please modem a copy of the new file
  49. *        to "TECHNICAL CBBS"    in Dearborn, Michigan -    phone
  50. *        313-846-6127 (110, 300, 450    or 600 baud).  Use the
  51. *        filename SD-NEW.NEW.  (KBP)
  52. *
  53. *        P.S.  As author of the original version as well as
  54. *        this latest update (4.5), I would also appreciate
  55. *        hearing your comments/changes.  Please leave me a
  56. *        note on Cranford, NJ RIBBS - 201-272-1874.  (BRR)
  57. *
  58. * ==========================================================================
  59. * Fixes/updates    (in reverse order to minimize reading time):
  60. *
  61. * 05/14/83 Put back in 0AH,0DH in TOTMS6 (removed in SD-47) for an extra
  62. *          line after 'free space' to make screen. Corrected sense of LOPREV
  63. *       EQU to reverse 'L' option.  Bill Wood
  64. *
  65. * 05/10/83 With SD-48 comes a major revision to this very popular SD
  66. *          program. This revision adds the optional capability to search
  67. *          and print the members of LIBRARY (.LBR) files formed by the LU
  68. *          library utility that is getting to be so popular.
  69. *
  70. *          See LOPT & LOPREV
  71. *
  72. *          The option has been given the "L" tag and at assembly time you
  73. *          can set LOPREV to TRUE to print all library members found,
  74. *          unless the "L" option is given, then no members will be printed.
  75. *          If you set LOPREV to FALSE then the library members will only
  76. *          be printed when the "L" option is given on the command line.
  77. *
  78. *          The member file sizes are shown in 128 byte sectors to allow a
  79. *          slightly different appearance between the normal DIR and library
  80. *          DIR printouts.  This sector size conforms to the -s command that
  81. *          is now found in the LDIR211 program.
  82. *
  83. *          I won't go into all of the places that parts of the code came
  84. *          from or who wrote it as that would be highly redundant. I do
  85. *          give thanks to them in any case, for some great ideas.
  86. *
  87. *                              G.B.Shaffstall Lakewood RCP/M
  88. *
  89. * 12Feb83 Added an improved version of Dave Roznar's and Bob Kohler's
  90. *    "BYELOW" modifications, which will allow SD to work in a system
  91. *    where BYE is running under the CCP (the "D" option didn't work).
  92. *    >> 20Jan83 Added fix to SWAPEM routine to allow use with BYELOW
  93. *    >> when using BYE.  Added BDOSPAG equate at beginning of code.
  94. *    -- Note: If you are going to use the LOWCCP option, you cannot
  95. *    --     MOVCPM without re-modifying SD.  (but you can just change
  96. *    --     The one byte at the beginning of the program).
  97. *    --     BUT, SD will operate properly if you only use one size of
  98. *    --     CP/M system (DOPT will work when BYE runs or if it isn't
  99. *    --     runnint) <<sigh, if you understand what I just said, congrats
  100. *
  101. *    ALSO: Changed code so that the newline feature of 21Aug82 will only
  102. *    be sent to the printer-- and it will only be sent when the program
  103. *    is done, NOT, after every free space message.    (4.7 - Paul Traina)
  104. *
  105. * 15Nov82 Added Set Error Mode call and new free space calculation method
  106. *    for compatibility with CP/M 3.0  (4.6 - B. Ratoff)
  107. *
  108. * 21Aug82 Added newline after free space message since some buffered 
  109. *    hardcopy devices won't print an incomplete line.  Made hilite
  110. *    sequences, column delimiter, names per line and lines per screen
  111. *    patchable to avoid reassembly.  Added $V option to display version
  112. *    number string.  (4.5 - B. Ratoff)
  113. *
  114. * 28feb82 Ignore attribute bits in compare subrs, equate CRT leadin char.,
  115. *    add Hazeltine 1500 equates. (4.4 - W.Earnest)
  116. *
  117. * 06feb82 Modified use of BDOS error vector table for DOPT.  The previous
  118. *     arrangement would change BDOS without checking whether it really was
  119. *     pointing to the right location.  In addition, the trap vectors are 
  120. *     swapped only when called for.
  121. *    Modified RMAC/MAC options: ASEG statement added for using RMAC
  122. *    without the requirement for external defs.
  123. *    Also added dim for ADM-31 (works same as reverse video), and cleared
  124. *    high^order bit when being sent to printer. (4.3 - R.B.STRAND)
  125. *
  126. * 11-1-81 Eliminated LF after "More" message. Allows yet another
  127. *     line per more.
  128. *
  129. * 10-25-81 Incorporated 10/21 updates renamed version. -CAF
  130. *     Also made display more compact by eliminating unneeded lf's
  131. *    This allows two more lines per "more"
  132. *
  133. * 10-21-81 Added conditionals for REVIDEO for reverse video
  134. *       display of tags ($SYS, etc.) -CAF
  135. *
  136. * 10/20/81 minor update to correct (1) malfunction when appending to an
  137. *       existing sd.dir file with the directory from an empty disk;
  138. *       (2) clobbering data area while closing sd.dir when last record
  139. *       appended is completely full; and (3) equate interaction error
  140. *       between fopt and aopt.  (ver 4.1 - david boruff)
  141. *
  142. * 10/19/81 MAJOR UPDATE adding new command line options for
  143. *       (1) disk system reset;  (2) page pause override;
  144. *       (3) displaying directory of a specified user    area;
  145. *       (4) searching ranges    of drives or user areas; and
  146. *       (5) printer output.    Corrected previous name error
  147. *       to avoid confusion with Keith Petersen's old SDIR.
  148. *
  149. *       Corrected obscure file output bug which occurred only
  150. *       when appending on even record or extent boundaries.
  151. *       Reset equate    of Ver 2.3 deleted as redundant    now that
  152. *       command line    reset available    as an option or    default.
  153. *       Shortened page-pause    message    to free-up program space.
  154. *       Optimized much of the existing code to compact the load
  155. *       module and gain space for new features.  Option scanner
  156. *       rewritten to    permit free form input and to simplify any
  157. *       future expansions of    the command line option    set.
  158. *       Reclaimed uninitialized data    memory to further compact
  159. *       load    module size.  By popular demand, restored code to
  160. *       display free    space remaining    when no    files are found.
  161. *       Added tables    to allow restricting directory searches
  162. *       to a    range of drives    and/or user areas.  BDOS intercept
  163. *       added to facilitate searching drives    that may not be
  164. *       on-line (more generally applicable than the FILEFIND
  165. *       method if your BIOS returns control to BDOS on fatal disk
  166. *       errors).  General cosmetic overhaul including tabular
  167. *       realignment and additional comments to enhance readability
  168. *       at the cost of a "few" extra bytes.    (Ver 4.0 - David Boruff)
  169. *
  170. * 09/23/81 MINOR UPDATE    to add equate to allow suppressing user
  171. *       numbers in the directory output. (Ver 3.1 - David Boruff)
  172. *
  173. * 09/18/81 MAJOR UPDATE    implementing new file output option allowing
  174. *       directory output to be appended to a    disk file.  Changed
  175. *       option specification    format to require a dollar sign
  176. *       preceding the option    specifiers.  Changed header format
  177. *       to display drive & user #'s for each line less than 4
  178. *       files wide.    Changed    code for no files found    to display
  179. *       error message only.    (Ver 3.0 - David Boruff)
  180. *
  181. * 09/12/81 MINOR UPDATE    deleting WIDE and NOT WIDE code    in deference
  182. *       to equating screen size.  Added Flashwriter II equate to
  183. *       allow display of file attributes in reverse video.  Changed
  184. *       tag-line to display drive and user #.  Added    equate to allow
  185. *       disk    system reset on    startup.  Other    cosmetic changes made
  186. *       to open up display format and give output a less cramped
  187. *       appearance. (Ver 2.3    - David    Boruff)
  188. *
  189. * 06/05/81 Added PGPAWZ    (page pause) conditional for remote
  190. *       CP/M    systems    where pausing may not be wanted.
  191. *       Setting PGPAWZ and REPSIZ to    FALSE will result in
  192. *       a display like DIR, but sorted and with the stat
  193. *       of space remaining.    Rearranged equates to allow
  194. *       15 lines per    page when narrow display is chosen.
  195. *       (Ver    2.2 - KBP)
  196. *
  197. * 06/01/81 Added version number, restored CTL-C    break, added
  198. *       CTL-C test to allow break at    page pause, added
  199. *       routine to gobble up    any waiting console character
  200. *       at EXIT, added conditional assembly to allow    no
  201. *       report of file sizes, added conditional assembly
  202. *       for direct console I/O for remote CP/M systems
  203. *       where phone line noise would    garbage    display.  (KBP)
  204. *
  205. * 05/06/81 Corrected double printing of    drive name in CALLB.
  206. *       Error only occurred with narrow display when    file
  207. *       wasn't found. (Tim Nicholas)
  208. *
  209. * 02/06/81 Changed sort    to have    odd gap    (KBP say its faster)
  210. *
  211. * 01/06/81 Changed sort    from bubble sort to shell sort
  212. *       for faster speed.
  213. *
  214. * 12/24/80 Changed BIOS    conout to BDOS conout to allow
  215. *       printing of directory with CTL-P.  Also added
  216. *       print of remaining space even if file not
  217. *       found. (Steve Nossen)
  218. *
  219. * 12/15/80 Added space suppression when    printing file
  220. *       totals.  (KBP)
  221. *
  222. * 12/14/80 Added logic to print    space remaining    on disk.
  223. *       Changed ^C test so that interrupting    character is
  224. *       not echoed (makes remote use    cleaner).  (BRR)
  225. *
  226. * 12/02/80 Fixed bug in    print routine which compared last file
  227. *       against garbage before printing. (BRR)
  228. *
  229. * 11/29/80 Changed to allow printing 4 file names. (Ben    Bronson
  230. *       and Keith Petersen)
  231. *
  232. * 11/22/80 Fixed bug in    handling >256 files.  Changed abort test
  233. *       in print routine to only abort on control-c.     (BRR)
  234. *
  235. * ==========================================================================
  236. *
  237. *         Set 'RMAC'    TRUE to    assemble with relocating assembler
  238. *         (requires link with PAGE 0    equates    in separate file).
  239. *
  240. * ==========================================================================
  241.  
  242. FALSE    EQU    0
  243. TRUE    EQU    NOT FALSE
  244.  
  245. ******************************
  246. *                 *
  247. * USER OPTION SPECIFICATIONS *
  248. *                 *
  249. ******************************
  250.  
  251. ALTCPM    EQU    FALSE        ;True for H8 or    TRS-80
  252. DIRCON    EQU    FALSE        ;True for direct console output
  253. LOWCCP    EQU    FALSE        ;True only if you are running with BYELOW
  254. BDOSPG    EQU    0CCh        ;Set properly if LOWCCP is true
  255. OPTION    EQU    TRUE        ;True if allowing ANY command line options
  256. AOPT    EQU    TRUE         ;True to allow searching all user areas
  257. DOPT    EQU    TRUE          ;True to allow searching all drives on-line
  258. STARTZ    EQU    TRUE        ;True to start with zero dr & user in none spec
  259. FOPT    EQU    TRUE        ;True to allow file output option
  260. NOPT    EQU    TRUE        ;True to allow disabling page pause option
  261. PGPAWZ    EQU    TRUE        ;True for pause after each page
  262. POPT    EQU    TRUE        ;True to allow printer option
  263. REPERR    EQU    TRUE         ;True to report command line option errors
  264. REPSIZ    EQU    TRUE        ;True to report file sizes
  265. REPUSR    EQU    TRUE        ;True to report user numbers
  266. RMAC    EQU    FALSE        ;True for RMAC assembly and external def link
  267. ROPT    EQU    TRUE         ;True to allow reset option
  268. SOPT    EQU    TRUE         ;True to allow system file option
  269. TOPT    EQU    TRUE        ;True for sort by filetype & filename
  270. TOPREV    EQU    FALSE        ;False to reverse "T" opt for normal sort
  271. UOPT    EQU    TRUE        ;True to allow user number option
  272. VOPT    EQU    TRUE        ;True to allow version number display
  273. LOPT    EQU    TRUE        ;True to allow Library file member printing
  274. LOPREV    EQU    FALSE        ;False to reverse the "L" option and not print
  275.  
  276. REVIDEO    EQU    TRUE          ;Use reverse video sequences
  277. LEADIN    EQU    27        ;Esc. leadin for ADM-31 & Z19
  278. INTOREV    EQU    0029H        ;Dim video for ADM-31 type terminals
  279. OUTAREV    EQU    0028H        ;and to get out (note digits are reversed)
  280. * NOTE: use a 2 digit INTO/OUTA sequence &  set one to 0 if only one needed
  281.  
  282. * INTOREV    EQU    3847H        ;Seq. for underline mode (for WYSE-200)
  283. * OUTAREV    EQU    3047H        ;Normal video         "     "
  284. * INTOREV    EQU    0070H        ;Sequence to enter reverse video (Z19)
  285. * OUTAREV    EQU    0071H        ;And to get out
  286. * LEADIN    EQU    '~'        ;Tilda leadin for hazeltine 1500
  287. * INTOREV    EQU    0019H        ;Background mode on Hazeltine 1500
  288. * OUTAREV    EQU    001FH        ;Foreground mode on Hazeltine 1500
  289. VECTOR    EQU    FALSE        ;True to display attributes on Flashwriter II
  290. VIDEO    EQU    0E009H        ;Entry to Flashwriter video driver PROM
  291.  
  292. DELIM    EQU    7CH        ;Fence (delimiter) character (vertical bar)
  293. ;DELIM    EQU    20H        ;Space
  294.  
  295. NPL    EQU    4        ;# of names per line (max of 3 for 64x16)
  296. *                             (max of 4 for 80x24)
  297.  
  298. LPS    EQU    23        ;# of lines per screen (max of 14 for 64x16)
  299. *                               (max of 23 for 80x24)
  300. STMSG    EQU    TRUE        ;true to start each directory with message
  301. *
  302. STSKIP    EQU    3        ;Start skipping at this drive number
  303. SKIPTO  EQU    13        ;and skip to this drive number
  304.  
  305.  
  306.  
  307.     IF    NOPT AND NOT PGPAWZ
  308.     ++++ NOPT OPTION REDUNDANT WITHOUT PGPAWZ ++++
  309.     ENDIF
  310.  
  311.     IF    REPERR AND NOT OPTION
  312.     ++++ REPERR EQUATE USELESS WITHOUT OPTION ++++
  313.     ENDIF
  314.  
  315. * BDOS equates
  316.  
  317. RDCHR    EQU    1        ;Read char from    console
  318. WRCHR    EQU    2        ;Write char to console
  319. CONST    EQU    11        ;Check cons stat
  320. RESET    EQU    13        ;Reset disk system
  321. SELDSK    EQU    14        ;Select    disk
  322. OPEN    EQU    15        ;0FFH=not found
  323. CLOSE    EQU    16        ;   "    "
  324. SEARCH    EQU    17        ;   "    "
  325. NEXT    EQU    18        ;   "    "
  326. READ    EQU    20        ;not 0 = EOF
  327. WRITE    EQU    21        ;not 0 = disk full
  328. MAKE    EQU    22        ;0FFH =    directory full
  329. CURDSK    EQU    25        ;Get currently logged disk name
  330. SETDMA    EQU    26        ;Set current DMA
  331. GALLOC    EQU    27        ;Get address of    allocation vector
  332. CURDPB    EQU    31        ;Get current disk parameters
  333. CURUSR    EQU    32        ;Get currently logged user number (2.x only)
  334.  
  335.     IF    ALTCPM
  336. BASE    EQU    4200H
  337. TPA    EQU    4300H
  338.     ENDIF
  339.  
  340.     IF    (NOT ALTCPM) AND (NOT RMAC)
  341. BASE    EQU    0        ;Default to 0 (or 100H with MAC    +R option)
  342. TPA    EQU    100H
  343.     ENDIF
  344.  
  345.     IF    RMAC
  346.     EXTRN    BASE,FCB,BDOS    ;Make base external
  347.     ELSE
  348. FCB    EQU    BASE+5CH
  349. BDOS    EQU    BASE+5
  350.     ASEG        ; Ignore this error if using MAC
  351.     ORG    TPA
  352.     ENDIF
  353.  
  354. FILL    MACRO    BYTES,WITH
  355.     REPT    BYTES
  356.     DB    WITH
  357.     ENDM
  358.     ENDM
  359.  
  360. $-MACRO
  361.  
  362.     PAGE    60
  363.     TITLE    'SD Version 4.8 - 10 May 1983'
  364.  
  365. *********************************
  366. *                *
  367. * BEGIN    EXECUTABLE PROGRAM CODE    *
  368. *                *
  369. *********************************
  370.  
  371.     JMP    START
  372.  
  373. MLEADIN DB    LEADIN        ;leadin char for hilite sequences
  374. MINTOREV DW    INTOREV        ;code to enter hilite mode
  375. MOUTAREV DW    OUTAREV        ;code to return to normal mode
  376. MDELIM    DB    DELIM        ;char to delimit columns on display
  377. MNPL    DB    NPL        ;names per line (# of columns)
  378. MLPS    DB    LPS        ;lines per screen (between pauses)
  379. BDOSPAG    DB    BDOSPG        ;normal residing place for BDOS if LOWCCP
  380. VERNAME:
  381.     DB    'SD 4.8A-10May83/HMVT rev-B 10Aug8','3'+80H
  382.  
  383. HLPMES:    DB    13,10,10
  384.     DB    'Useage: SD dr:FILENAME.TYP [option,option...]'
  385.     DB    13,10,10,'Drive and/or filespec are optional'
  386.     DB    13,10,'Wildcards * and ? allowed'
  387.     DB    13,10,'SD // for help'
  388.     DB    13,10,10,'Options Are:'
  389.     DB    13,10,09,'A=All Users'
  390.     DB    13,10,09,'D=All Disks'
  391.     DB    13,10,09,'F=Make File'
  392.     DB    13,10,09,'L=Library'
  393.     DB    13,10,09,'N=No Paging'
  394.     DB    13,10,09,'P=Printer'
  395.     DB    13,10,09,'R=Reset'
  396.     DB    13,10,09,'S=System'
  397.     DB    13,10,09,'T=Sort by Type'
  398.     DB    13,10,09,'Un=User No.'
  399.     DB    13,10,09,'V=Versio','n'+80H
  400.  
  401. START:    LXI    H,0
  402.     DAD    SP        ;HL=old    stack
  403.     SHLD    STACK        ;Save it
  404.     LXI    SP,STACK    ;Get new stack
  405.  
  406.     MVI    C,12        ;Get and save the CP/M version #
  407.     CALL    BDOS
  408.     MOV    A,L
  409.     STA    VERFLG
  410.     CPI    20H        ;Set carry if CP/M 1.4
  411.  
  412.     MVI    E,0FFH        ;Get current user number if using CP/M 2, or
  413.     MVI    C,CURUSR    ;Fall through with A=0 if not
  414.     CNC    CPM
  415.  
  416.     STA    OLDUSR        ;Initialize startup user number
  417.     STA    NEWUSR        ;..and make new    user match it
  418.  
  419.     IF    DOPT
  420.     STA    BASUSR        ;Save extra copy for multi-disk    directories
  421.     ENDIF
  422.  
  423.     MVI    C,CURDSK
  424.     CALL    CPM        ;Get current disk nr
  425.     STA    OLDDSK        ;Save for reset    if needed
  426.  
  427.     IF    FOPT
  428.     INR    A
  429.     STA    OUTFCB        ;Set directory output file drive
  430.     ENDIF
  431.  
  432. * If at    least one option is allowed, scan the command line for the
  433. * option field delimiter.  The option field delimiter is considered
  434. * valid    only if    it is preceded by at least 1 space (otherwise, it
  435. * may be part of the directory filename).  Any unrecognized options
  436. * or illegal user numbers will be flagged or ignored (see REPERR).
  437. * (We scan the command line buffer rather than the 2nd default FCB
  438. * because all 8    options    plus a 2 digit user number won't fit in
  439. * the FCB name field).
  440.  
  441.     IF    OPTION
  442.     LXI    H,80H        ;Set command line buffer+2 pointer
  443.     MOV    B,M        ;Get length of command line buffer
  444.  
  445. * Check for a help request
  446.     INX    H
  447.     INX    H
  448.     MOV    A,M
  449.     CPI    '/'
  450.     CZ    HELP
  451.     DCX    H
  452.     DCX    H
  453. * Search for the command line delimiter.  If not found, assume no options.
  454.  
  455. SCNDOL:    INX    H
  456.     DCR    B
  457.     JM    CKREST        ;Exit if command line buffer empty
  458.     MOV    A,M
  459.     CPI    '['        ;Digital Research changing to "["
  460.     JNZ    SCNDOL
  461. ;    DCX    H        ;'$' found - make sure space precedes it
  462. ;    MOV    A,M
  463. ;    INX    H
  464. ;    CPI    ' '
  465. ;    JNZ    SCNDOL        ;No space - ignore "$" and search again
  466.  
  467. * Valid    delimiter found.  Scan the rest    of the buffer for options.  Errors
  468. * past this point will cause an    abort if the command line error    option is
  469. * enabled.  Otherwise, the dud option will be ignored and SD will attempt
  470. * to continue stumbling    through    the rest of the    field.
  471.  
  472.     XCHG            ;Get option field pointer to DE
  473. SCNOPT:    INX    D        ;Bump to next option field character
  474.     DCR    B        ;Dock characters left in option    field
  475.     JM    CKREST        ;If option field exhausted, exit
  476. SCNAGN:    LDAX    D        ;Get the next option character
  477.     CPI    ' '        ;Do we have a space?
  478.     JZ    SCNOPT        ;Ignore    it if so
  479.     CPI    ','        ;Same for comma
  480.     JZ    SCNOPT
  481.     CPI    ']'        ;End of option list
  482.     JZ    CKREST
  483.     LXI    H,OTBL-1    ;Get base of option lookup table
  484.     MVI    C,OEND-OTBL+1    ;Get length of option lookup table
  485. NOMACH:    INX    H        ;Bump to next option table character
  486.     DCR    C        ;Are we    out of the table?
  487.     JZ    CK4USR        ;If so, check for user option
  488.     CMP    M        ;Compare our character with option table
  489.     JNZ    NOMACH        ;Exit if no match
  490.     MVI    M,0        ;Otherwise, activate the flag
  491.     JMP    SCNOPT        ;..and go get the next option character
  492.  
  493. * If option character doesn't match the table, see if we have a User
  494. * option.
  495.  
  496. CK4USR:    IF    UOPT        ;Check for user    number option
  497.     CPI    'U'
  498.     JNZ    CLERR        ;Last option, so bad deal if that ain't it
  499.  
  500. UAGN:    INX    D        ;Bump to user number digit
  501.     DCR    B
  502.     JM    CLERR        ;Error if nothing left
  503.     LDAX    D        ;Get decimal digit
  504.     CPI    ' '        ;Ignore    leading    spaces
  505.     JZ    UAGN
  506.     SUI    30H        ;Subtract ASCII    BIAS
  507.     JC    CLERR        ;Error if < 0
  508.     CPI    10
  509.     JNC    CLERR        ;Error if > 9
  510.     STA    NEWUSR        ;Save user number as it    may be only 1 digit
  511.  
  512.     IF    DOPT
  513.     STA    BASUSR        ;Duplicate it if multi-disk mode
  514.     PUSH    PSW
  515.     MVI    A,0FFH        ;Set got user flag
  516.     STA    GOTUSR
  517.     POP    PSW
  518.     ENDIF
  519.  
  520.     INX    D        ;Bump to possible 2nd digit of user number
  521.     DCR    B
  522.     JM    CKREST        ;If no more buffer, exit with complete user #
  523.     LDAX    D        ;Else, check for another digit
  524.     SUI    30H
  525.     JC    SCNAGN        ;If next char not numeric, its not part    of
  526.     CPI    10        ;..user    number so go check for another option
  527.     JNC    SCNAGN
  528.     MOV    L,A        ;Save units digit
  529.     LDA    NEWUSR        ;Get tens digit
  530.     ADD    A        ;Multiply by 10
  531.     MOV    H,A
  532.     ADD    A
  533.     ADD    A
  534.     ADD    H
  535.     ADD    L        ;Combine with units digit
  536.     STA    NEWUSR        ;Save the total    user number
  537.  
  538.     IF    DOPT
  539.     STA    BASUSR        ;Duplicate it if multi-disk mode
  540.     ENDIF
  541.  
  542.     JMP    SCNOPT        ;Continue scanning
  543.     ENDIF            ;Balance UOPT
  544.  
  545. * If command line error    option enabled,    playback the command line up
  546. * to the character that    we gagged on and exit.    If REPERR is not enabled,
  547. * then continue    as if nothing were amiss to avoid acknowledging    that
  548. * some options are available.
  549.  
  550. CLERR:    IF    REPERR
  551.     XRA    A
  552.     INX    D        ;Tag end of command line with terminator
  553.     STAX    D
  554.     CALL    CRLF
  555.     LXI    D,ERRMS2
  556.     CALL    PRINT
  557.     LXI    D,ERRTAG
  558.     CALL    PRINT
  559.     LXI    H,81H        ;Playback bad command line to error point
  560. CLELP:    MOV    A,M
  561.     ORA    A
  562.     JZ    CLEX
  563.     CALL    TYPE
  564.     INX    H
  565.     JMP    CLELP
  566.  
  567. CLEX:    MVI    A,'?'        ;Tag line with a '?' field
  568.     CALL    TYPE
  569.     JMP    HELP1        ;..and tell how to do it
  570.     ELSE
  571.  
  572.     JMP    SCNOPT        ;If not    reporting errors, ignore the dud
  573.  
  574.     ENDIF            ;Balance REPERR
  575.     ENDIF            ;Balance OPTION
  576.  
  577. * Options input or not specified.  If reset option specified, reset
  578. * the disk system now.    Its important that the reset be done OUTSIDE
  579. * the multiple drive loop if the file output option is enabled because
  580. * CP/M 1.4 clobbers the DMA buffer on reset.
  581.  
  582. CKREST: IF    ROPT
  583.     LDA    ROPFLG        ;If reset flag set, reset disk system before
  584.     ORA    A        ;..starting to update allocation vectors
  585.     MVI    C,RESET
  586.     CZ    CPM
  587.     ENDIF            ;Balance ROPT
  588.  
  589.     IF    VOPT
  590.     LDA    VOPFLG        ;If version display flag set, print it
  591.     ORA    A
  592.     JNZ    NOVOPT
  593.     LXI    D,VERNAME
  594.     CALL    PRINT
  595.     CALL    CRLF
  596. NOVOPT:
  597.     ENDIF
  598.  
  599.     IF    DOPT
  600.     LDA    DOPFLG        ;If multi-disk flag set, 
  601.     ORA    A        ;..need to set error traps
  602.     CZ    SWAPEM        ;Swap BDOS error vector    tables
  603.     ENDIF
  604.  
  605. * If "A" option choosen and no user number specified
  606. * set user to zero
  607.  
  608.     IF (AOPT AND STARTZ)
  609. ZUSR:    LDA    GOTUSR        ;Was a user specified?
  610.     ORA    A
  611.     JNZ    ZDRV        ;YES-quit now
  612.     LDA    AOPFLG        ;Was D option specified?
  613.     ORA    A        
  614.     JNZ    ZDRV        ;JMP if NO
  615.     XRA    A
  616.     STA    NEWUSR        ;ZERO NEWUSR for all users
  617.     IF    DOPT
  618.     STA    BASUSR        ;ZERO BASUSR for all users
  619.     ENDIF
  620.     ENDIF
  621.  
  622. * If "D" option choosen and no drive specified
  623. * set drive to physical zero
  624.  
  625. ZDRV:    LXI    H,FCB
  626.     MOV    A,M        ;Get drive name    for directory search
  627.     ORA    A        ;Any specified?
  628.     JNZ    NOOPT        ;Yes skip next routine
  629.  
  630.     IF  (DOPT AND STARTZ)
  631.     LDA    DOPFLG        ;else if DOPT then
  632.     ORA    A
  633.     JNZ    ZDRV1
  634.     INR    A        ;always start with A
  635.     MOV    M,A
  636.     JMP    NOOPT
  637.     ENDIF
  638.  
  639. ZDRV1:    LDA    OLDDSK        ;Otherwise, get    default    disk
  640.     INR    A
  641.     MOV    M,A        ;Put the absolute drive    code in    directory FCB
  642.  
  643.  
  644. * Validate drive code and user area numbers from the drive table.
  645.  
  646. NOOPT:    LXI    D,DREMSG    ;Get the drive/user error message
  647.     PUSH    D
  648.     LDA    FCB        ;Get directory drive code
  649.     DCR    A        ;Normalize to range of 0-15
  650.     CPI    HIDRV-LODRV    ;Compare with maximum drives on-line
  651.     JNC    ERXIT        ;Take drive error exit if out of range
  652.     LXI    H,USRMSG    ;Switch    to user    # error    message
  653.     XTHL
  654.     MOV    E,A        ;Use drive code    as index into table
  655.     MVI    D,0
  656.     LXI    H,LODRV        ;Point to base of drive/user table
  657.     DAD    D
  658.     MOV    A,M        ;Get the maximum user #    for this drive
  659.     ANI    0FH        ;Make sure its in range    0 - 15
  660.     STA    MAXUSR        ;Save it for later
  661.     LXI    H,NEWUSR    ;Point to the directory    user area
  662.     CMP    M        ;Compare it with the maximum
  663.     JC    ERXIT        ;Take error exit if user number    illegal
  664.     POP    D        ;Destroy error message pointer
  665.  
  666.     LXI    H,FCB+1     ;Point to name
  667.     MOV    A,M        ;Any specified?
  668.     CPI    '['
  669.     JZ    GOTDL
  670.     CPI    ' '
  671.     JNZ    GOTFCB
  672.  
  673. * No FCB - make    FCB all    '?'
  674.  
  675. GOTDL:    MVI    B,11        ;FN+FT count
  676.  
  677. QLOOP:    MVI    M,'?'        ;Store '?' IN FCB
  678.     INX    H
  679.     DCR    B
  680.     JNZ    QLOOP
  681.  
  682. GOTFCB:    MVI    A,'?'        ;Force wild extent
  683.     STA    FCB+12
  684.     CALL    SETSRC        ;Set DMA for BDOS media change check
  685.     LXI    H,FCB        ;Point to FCB drive code for directory
  686.     MOV    E,M        ;Get the drive code out of the FCB
  687.     DCR    E        ;Normalize drive code for SELECT
  688.     MVI    C,SELDSK    ;Select the directory drive to retrieve
  689.     CALL    CPM        ;..the proper allocation vector
  690.     CALL    CKVER        ;Check version
  691.     JC    V14        ;Pre-2.X...get params the 1.4 way
  692.  
  693.     MVI    C,CURDPB    ;It's 2.X or MP/M...request DPB
  694.     CALL    BDOS
  695.     INX    H
  696.     INX    H
  697.     MOV    A,M        ;Get block shift
  698.     STA    BLKSHF
  699.     INX    H        ;Bump to block mask
  700.     MOV    A,M
  701.     STA    BLKMSK        ;Get it
  702.     INX    H
  703.     INX    H
  704.     MOV    E,M        ;Get max block #
  705.     INX    H
  706.     MOV    D,M
  707.     XCHG
  708.     SHLD    BLKMAX        ;Save it
  709.     XCHG
  710.     INX    H
  711.     MOV    E,M        ;Get directory size
  712.     INX    H
  713.     MOV    D,M
  714.     XCHG
  715.     JMP    FREE        ;Let FREE save it and setup order table
  716.  
  717. V14:    LHLD    BDOS+1        ;Get params 1.4 style
  718.     MVI    L,3BH        ;Point to directory size
  719.     MOV    E,M        ;Get it
  720.     MVI    D,0        ;Force high order to 0
  721.     PUSH    D        ;Save for later
  722.     INX    H        ;Point to block    shift
  723.     MOV    A,M        ;Fetch
  724.     STA    BLKSHF        ;Save
  725.     INX    H        ;Point to block    mask
  726.     MOV    A,M        ;Fetch it
  727.     STA    BLKMSK        ;And save it
  728.     INX    H
  729.     MOV    E,M        ;Get max. block    no.
  730.     MVI    D,0
  731.     XCHG
  732.     SHLD    BLKMAX        ;Save it
  733.     POP    H        ;Restore directory size
  734.     JMP    FREE20        ;Go figure free space from alloc vector
  735.  
  736. * Calculate # of K free    on selected drive now so that the FREE figure
  737. * will not reflect either the creation or additions to the SD.DIR
  738. * file (which we would probably    erase or move anyway).
  739.  
  740. FREE:    SHLD    DIRMAX        ;Save max # of entries in directory
  741.     LDA    VERFLG        ;check version #
  742.     CPI    30H        ;3.0?
  743.     JC    FREE20        ;use old method if not
  744.     LDA    FCB        ;get drive #
  745.     DCR    A
  746.     MOV    E,A        ;Use new Compute Free Space BDOS call
  747.     MVI    C,46
  748.     CALL    CPM
  749.     MVI    C,3        ;answer is a 24-bit integer
  750. FRE3L1:
  751.     LXI    H,BASE+82H    ;answer is in 1st 3 bytes of DMA adr
  752.     MVI    B,3        ;convert it from sectors to K
  753.     ORA    A        ;by dividing by 8
  754. FRE3L2:
  755.     MOV    A,M
  756.     RAR
  757.     MOV    M,A
  758.     DCX    H
  759.     DCR    B
  760.     JNZ    FRE3L2        ;Loop for 3 bytes
  761.     DCR    C
  762.     JNZ    FRE3L1        ;Shift 3 times
  763.     LHLD    BASE+80H    ;Now get result in K
  764.     JMP    SAVFRE        ;Go store it
  765. FREE20:
  766.     MVI    C,GALLOC    ;Get address of    allocation vector
  767.     CALL    BDOS
  768.     XCHG
  769.     LHLD    BLKMAX        ;Get its length
  770.     INX    H
  771.     LXI    B,0        ;Init block count to 0
  772.  
  773. GSPBYT:    PUSH    D        ;Save alloc address
  774.     LDAX    D
  775.     MVI    E,8        ;Set to    process    8 blocks
  776.  
  777. GSPLUP:    RAL            ;Test bit
  778.     JC    NOTFRE
  779.     INX    B
  780.  
  781. NOTFRE:    MOV    D,A        ;Save bits
  782.     DCX    H        ;Count down blocks
  783.     MOV    A,L
  784.     ORA    H
  785.     JZ    ENDALC        ;Quit if out of    blocks
  786.     MOV    A,D        ;Restore bits
  787.     DCR    E        ;Count down 8 bits
  788.     JNZ    GSPLUP        ;Do another bit
  789.     POP    D        ;Bump to next byte..
  790.     INX    D        ;..of alloc. vector
  791.     JMP    GSPBYT        ;Process it
  792.  
  793. ENDALC:    POP    D        ;Clear allocation vector pointer from stack
  794.     MOV    L,C        ;Copy blocks to    hl
  795.     MOV    H,B
  796.     LDA    BLKSHF        ;Get block shift factor
  797.     SUI    3        ;Convert from sectors to K
  798.     JZ    SAVFRE        ;Skip shifts if 1K blocks - return free in HL
  799.  
  800. FREKLP: DAD    H        ;Multiply blocks by K/BLK
  801.     DCR    A
  802.     JNZ    FREKLP
  803. SAVFRE: SHLD    FREEBY        ;Save the free space for output later
  804.  
  805. * Reenter here on subsequent passes while in the all-users mode
  806.  
  807. SETTBL:    LHLD    DIRMAX        ;Get directory maximum again
  808.     INX    H        ;Directory size    is DIRMAX+1
  809.     DAD    H        ;Double    directory size
  810.     LXI    D,ORDER        ;To get    size of    order table
  811.     DAD    D        ;Allocate order    table
  812.     SHLD    TBLOC        ;Name table begins where order table ends
  813.     SHLD    NEXTT
  814.     XCHG
  815.     LHLD    BDOS+1        ;Make sure we have room    to continue
  816.     MOV    A,E
  817.     SUB    L
  818.     MOV    A,D
  819.     SBB    H
  820.     JNC    OUTMEM
  821.  
  822.     IF    UOPT
  823.     CALL    CKVER        ;Set carry if pre-CP/M 2
  824.     LDA    NEWUSR        ;Get user area for directory
  825.     MOV    E,A
  826.     MVI    C,CURUSR    ;Get the user function
  827.     CNC    CPM        ;..and set new user number if CP/M 2
  828.     ENDIF
  829.  
  830. * Look up the FCB in the directory
  831.  
  832. SFIRST:    LXI    H,0
  833.     SHLD    COUNT        ;Initialize match counter
  834.     SHLD    TOTFIL        ;     "        total file counter
  835.     SHLD    TOTSIZ        ;     "        total size counter
  836.     CALL    SETSRC        ;Set DMA for directory search
  837.     MVI    C,SEARCH    ;Get 'search first' function
  838.     JMP    LOOK        ;..and go search for 1st match
  839.  
  840. * Read more directory entries
  841.  
  842. MORDIR:    MVI    C,NEXT        ;Search    next
  843. LOOK:    LXI    D,FCB
  844.     CALL    CPM        ;Read directory    entry
  845.     INR    A        ;Check for end (0FFH)
  846.     JZ    SPRINT        ;If no more, sort & print what we have
  847.  
  848. * Point    to directory entry
  849.  
  850. SOME:    DCR    A        ;Undo prev 'INR A'
  851.     ANI    3        ;Make modulus 4
  852.     ADD    A        ;Multiply...
  853.     ADD    A        ;..by 32 because
  854.     ADD    A        ;..each    directory
  855.     ADD    A        ;..entry is 32
  856.     ADD    A        ;..bytes long
  857.     LXI    H,BASE+81H    ;Point to buffer
  858.                 ;(skip to FN/FT)
  859.     ADD    L        ;Point to entry
  860.     ADI    9        ;Point to SYS byte
  861.     MOV    L,A        ;Save (can't carry to H)
  862.  
  863.     IF    SOPT
  864.     LDA    SOPFLG        ;Did user request SYS files?
  865.     ORA    A
  866.     JZ    SYSFOK
  867.     ENDIF
  868.  
  869.     MOV    A,M        ;Get SYS byte
  870.     ORA    A        ;Check bit 7
  871.     JM    MORDIR        ;Skip that file
  872.  
  873. SYSFOK:    MOV    A,L        ;Go back now
  874.     SUI    10        ;Back to user number (alloc flag)
  875.     MOV    L,A        ;HL points to entry now
  876.  
  877.     LDA    NEWUSR        ;Get current user
  878.     CMP    M
  879.     JNZ    MORDIR        ;Ignore    if different
  880.     INX    H
  881.  
  882. * Move entry to    table
  883.  
  884.     XCHG            ;Entry to DE
  885.     LHLD    NEXTT        ;Next table entry to HL
  886.     MVI    B,12        ;Entry length (name, type, extent)
  887.  
  888. TMOVE:    LDAX    D        ;Get entry char
  889.  
  890.     IF    NOT (VECTOR OR REVIDEO)
  891.     ANI    7FH        ;Remove    attributes
  892.     ENDIF
  893.  
  894.     MOV    M,A        ;Store in table
  895.     INX    D
  896.     INX    H
  897.     DCR    B        ;More?
  898.     JNZ    TMOVE
  899.     INX    D
  900.     INX    D        ;Point to sector count
  901.     LDAX    D        ;Get it
  902.     MOV    M,A        ;Store in table
  903.     INX    H
  904.     SHLD    NEXTT        ;Save updated table addr
  905.     XCHG
  906.     LHLD    COUNT        ;Bump the # of matches made
  907.     INX    H
  908.     SHLD    COUNT
  909.     LXI    H,13        ;Size of next entry
  910.     DAD    D
  911.     XCHG            ;Future    NEXTT is in DE
  912.     LHLD    BDOS+1        ;Pick up TPA end
  913.     MOV    A,E
  914.     SUB    L        ;Compare NEXTT-TPA end
  915.     MOV    A,D
  916.     SBB    H
  917.     JC    MORDIR        ;If TPA    END > NEXTT then loop back for more
  918.  
  919. OUTMEM:    CALL    ERXIT        ;Exit if directory too large
  920.     DB    'Memor','y' OR 80H
  921.  
  922. * Sort and print
  923.  
  924. SPRINT: IF    AOPT OR FOPT OR UOPT
  925.     CALL    SETFOP        ;Return to file output DMA & user #
  926.     ENDIF
  927.  
  928.     LHLD    COUNT        ;Get file name count
  929.     MOV    A,L
  930.     ORA    H        ;Any found?
  931.     JZ    PRTOTL        ;Exit if no files found
  932.     PUSH    H        ;Save file count
  933.     STA    SUPSPC        ;Enable    leading    zero suppression
  934.  
  935. * Initialize the order table
  936.  
  937.     LHLD    TBLOC        ;Get start of name table
  938.     XCHG            ;Into DE
  939.     LXI    H,ORDER        ;Point to order    table
  940.     LXI    B,13        ;Entry length
  941.  
  942. BLDORD:    MOV    M,E        ;Save low order    address
  943.     INX    H
  944.     MOV    M,D        ;Save high order address
  945.     INX    H
  946.     XCHG            ;Table addr to HL
  947.     DAD    B        ;Point to next entry
  948.     XCHG
  949.     XTHL            ;Save tbl addr,    fetch loop counter
  950.     DCX    H        ;Count down loop
  951.     MOV    A,L
  952.     ORA    H        ;More?
  953.     XTHL            ;(restore tbl addr, save counter)
  954.     JNZ    BLDORD        ;Yes, go do another one
  955.     POP    H        ;Clean loop counter off    stack
  956.     LHLD    COUNT        ;Get count
  957.     SHLD    SCOUNT        ;Save as # to sort
  958.     DCX    H        ;Only 1    entry?
  959.     MOV    A,L
  960.     ORA    H
  961.     JZ    DONE        ;Yes, so skip sort
  962.  
  963. * This sort routine is adapted from SOFTWARE TOOLS
  964. * by Kernigan and Plaugher.
  965.  
  966. SORT:    LHLD    SCOUNT        ;Number    of entries
  967.  
  968. L0:    ORA    A        ;Clear carry
  969.     MOV    A,H        ;GAP=GAP/2
  970.     RAR
  971.     MOV    H,A
  972.     MOV    A,L
  973.     RAR
  974.     MOV    L,A
  975.     ORA    H        ;Is it zero?
  976.     JZ    DONE        ;Then none left
  977.     MOV    A,L        ;Make gap odd
  978.     ORI    01
  979.     MOV    L,A
  980.     SHLD    GAP
  981.     INX    H        ;I=GAP+1
  982.  
  983. L2:    SHLD    I
  984.     XCHG
  985.     LHLD    GAP
  986.     MOV    A,E        ;J=I-GAP
  987.     SUB    L
  988.     MOV    L,A
  989.     MOV    A,D
  990.     SBB    H
  991.     MOV    H,A
  992.  
  993. L3:    SHLD    J
  994.     XCHG
  995.     LHLD    GAP        ;JG=J+GAP
  996.     DAD    D
  997.     SHLD    JG
  998.     CALL    COMPARE        ;Compare (J) and (JG)
  999.     JP    L5        ;If A(J)<=A(JG)
  1000.     LHLD    J
  1001.     XCHG
  1002.     LHLD    JG
  1003.     CALL    SWAP        ;Exchange A(J) and A(JG)
  1004.     LHLD    J        ;J=J-GAP
  1005.     XCHG
  1006.     LHLD    GAP
  1007.     MOV    A,E
  1008.     SUB    L
  1009.     MOV    L,A
  1010.     MOV    A,D
  1011.     SBB    H
  1012.     MOV    H,A
  1013.     JM    L5        ;If J>0    GOTO L3
  1014.     ORA    L        ;Check for zero
  1015.     JZ    L5
  1016.     JMP    L3
  1017.  
  1018. L5:    LHLD    SCOUNT        ;For later
  1019.     XCHG
  1020.     LHLD    I        ;I=I+1
  1021.     INX    H
  1022.     MOV    A,E        ;IF I<=N GOTO L2
  1023.     SUB    L
  1024.     MOV    A,D
  1025.     SBB    H
  1026.     JP    L2
  1027.     LHLD    GAP
  1028.     JMP    L0
  1029.  
  1030. * Sort is all done - print entries
  1031.  
  1032. DONE:    IF    FOPT        ;If output option wanted, prepare file
  1033.     LDA    FOPFLG
  1034.     ORA    A
  1035.     JNZ    NOOUT        ;If file output, fall through with A=0
  1036.  
  1037. * If all user option enabled, and we're not on the first pass, then the
  1038. * output file is already open and positioned, so we can skip the open.
  1039.  
  1040. ;    IF    AOPT
  1041.     LXI    H,OPNFLG    ;point to output file open flag
  1042.     CMP    M        ;a=0, set z if opnflg=0 also
  1043.     JNZ    NOOUT        ;if opnflg not zero, skip open
  1044.     DCR    M        ;else, make opnflg not zero and open
  1045. ;    ENDIF            ;Balance AOPT
  1046.  
  1047. * First pass on file append - prepare SD.DIR to receive new or appended
  1048. * output.
  1049.  
  1050.     LXI    D,OUTFCB    ;Does output file already exist?
  1051.     MVI    C,SEARCH
  1052.     CALL    CPM
  1053.     INR    A
  1054.     JNZ    OPENIT        ;If it does, then open it for processing
  1055.     MVI    C,MAKE        ;Otherwise, create the output file
  1056.     CALL    CPM
  1057.     INR    A
  1058.     JNZ    NOOUT        ;Continue if open successful
  1059.  
  1060. * If make or open fails, declare error
  1061.  
  1062. OPNERR:    CALL    ERXIT
  1063.     DB    'Ope','n' OR 80H
  1064.  
  1065. WRTERR:    CALL    ERXIT
  1066.     DB    'Writ','e' OR 80H
  1067.  
  1068. * Output file already exists - open it and position to the last
  1069. * record of the    last extent.
  1070.  
  1071. OPENIT: MVI    C,OPEN        ;Open 1st extent of output file
  1072.     CALL    CPM
  1073.     INR    A
  1074.     JZ    OPNERR        ;Bad deal if 1st won't open
  1075.  
  1076. OPNMOR:    LDA    OUTFCB+15
  1077.     CPI    128
  1078.     JC    LSTEXT        ;If RC<128, this is last extent
  1079.     LXI    H,OUTFCB+12
  1080.     INR    M        ;Else, bump to next extent
  1081.     MVI    C,OPEN        ;..and try to open it
  1082.     CALL    CPM
  1083.     INR    A
  1084.     JNZ    OPNMOR        ;Continue opening extents til no more
  1085.     DCR    M        ;Then, reopen preceding    extent
  1086.     MVI    C,OPEN
  1087.     CALL    CPM
  1088.     LDA    OUTFCB+15    ;Get RC    for the    last extent
  1089.  
  1090. * At this point, OUTFCB is opened to the last extent of the file,
  1091. * so read in the last record in the last extent.
  1092.  
  1093. LSTEXT:    ORA    A        ;Is this extent    empty?
  1094.     JZ    NOOUT        ;If so, then we're starting a clean slate
  1095.     DCR    A        ;Normalize record count
  1096.     STA    OUTFCB+32    ;Set record number to read
  1097.     MVI    C,READ        ;..and read last record    of file
  1098.     CALL    CPM
  1099.     ORA    A        ;Was read successful?
  1100.     JZ    RDOK        ;If so,    proceed    to scan    for EOF    mark
  1101. APERR:    CALL    ERXIT
  1102.     DB    'Appen','d' OR 80H
  1103.  
  1104. * We now have the last record in the file in our buffer.
  1105. * Scan the last    record for the EOF mark, indicating where
  1106. * we can start adding data.
  1107.  
  1108. RDOK:    LXI    H,OUTBUF    ;Point to start of output buffer
  1109.     MVI    B,128        ;Get length of output buffer
  1110. SCAN:    MOV    A,M
  1111.     CPI    'Z'-40H        ;Have we found end of file?
  1112.     JZ    RESCR        ;If so, save pointers and reset CR
  1113.     INX    H
  1114.     DCR    B
  1115.     JNZ    SCAN        ;Otherwise, keep looking til end of buffer
  1116.  
  1117. * If we find an explicit EOF mark in the last buffer (or an implied EOF
  1118. * if the last record is full), move the FCB record and extent pointers
  1119. * back to correct for the read operation so that our first write operation
  1120. * will effectively replace the last record of the SD.DIR file.
  1121.  
  1122. RESCR:    PUSH    H        ;Save EOF buffer pointer
  1123.     PUSH    B        ;Save EOF buffer remaining
  1124.     LXI    H,OUTFCB+32    ;Get current record again
  1125.     DCR    M        ;Dock it
  1126.     JP    SAMEXT        ;If CR >=0, we're still in same extent
  1127.     LXI    H,OUTFCB+12    ;Else, move to previous    extent
  1128.     DCR    M
  1129.     MVI    C,OPEN        ;Then, reopen the previous extent
  1130.     CALL    CPM
  1131.     INR    A
  1132.     JZ    APERR        ;Append position error if we can't reopen
  1133.     LDA    OUTFCB+15    ;Else, position to last record of extent
  1134.     DCR    A
  1135.     STA    OUTFCB+32
  1136. SAMEXT: POP    PSW        ;Recall where EOF is in buffer
  1137.     STA    BUFCNT        ;..and set buffer counter
  1138.     POP    H        ;Recall next buffer pointer
  1139.     SHLD    BUFPNT        ;.. and set pointer for first addition
  1140.  
  1141.     ENDIF            ;Balance FOPT
  1142.  
  1143. NOOUT:
  1144.     IF    LOPT
  1145.     LHLD    COUNT
  1146.     SHLD    LCOUNT
  1147.     LXI    H,0
  1148.     SHLD    LBTOTL
  1149.     SHLD    LMTOTL
  1150.     LXI    H,ORDER        ;Initialize order table    pointer
  1151.     SHLD    NEXTL
  1152.     ELSE
  1153.  
  1154.     LXI    H,ORDER        ;Initialize order table    pointer
  1155.     ENDIF
  1156.  
  1157.     SHLD    NEXTT
  1158.  
  1159.     IF    STMSG        ;Print "Driectory for...
  1160.     LXI    D,DIRMS1    ;at start of each section
  1161.     CALL    PRINT
  1162.     CALL    PRDIR        ;Print " Drive, x User, y"
  1163.     LDA    LINCNT
  1164.     INR    A        ;Bump line count
  1165.     STA    LINCNT
  1166.     ENDIF
  1167.  
  1168.     JMP    NEWLIN        ;Start new line    and output the files
  1169.  
  1170. * Output the directory files we've matched.
  1171.  
  1172. ENTRY:    LHLD    COUNT
  1173.     DCX    H        ;Dock file count
  1174.     SHLD    COUNT
  1175.     MOV    A,H        ;Is this the last file?
  1176.     ORA    L
  1177.     JZ    OKPRNT        ;If COUNT=0, last file so skip compare
  1178.  
  1179. * Compare each entry to    make sure that it isn't part of a multiple
  1180. * extent file.    Go only    when we    have the last extent of    the file.
  1181.  
  1182.     PUSH    B        ;Save NPL
  1183.     CALL    CKABRT        ;Check for abort code from keyboard
  1184.     LHLD    NEXTT
  1185.     MVI    A,11
  1186.     CALL    COMPR        ;Does this entry match next one?
  1187.     POP    B        ;Recall    NPL
  1188.     JNZ    OKPRNT        ;No, print it
  1189.     INX    H
  1190.     INX    H        ;Skip since highest extent comes last in list
  1191.     SHLD    NEXTT
  1192.     JMP    ENTRY        ;Loop back for next lowest extent
  1193.  
  1194. * Valid    entry obtained - spit it out.
  1195.  
  1196. OKPRNT:    LHLD    NEXTT        ;Get order table pointer
  1197.     MOV    E,M        ;Get low order address
  1198.     INX    H
  1199.     MOV    D,M        ;Get high order    address
  1200.     INX    H
  1201.     SHLD    NEXTT        ;Save updated table pointer
  1202.     XCHG            ;Table entry to    HL
  1203.  
  1204.     MVI    B,8        ;File name length
  1205.     CALL    TYPEIT        ;Type filename
  1206.  
  1207.     MVI    A,'.'        ;Period    after FN
  1208.     CALL    TYPE
  1209.  
  1210.     MVI    B,3        ;Display 3 characters of filetype
  1211.     CALL    TYPEIT
  1212.  
  1213. * Compute the size of the file and update our summary datum.
  1214.  
  1215.     MOV    E,M        ;Get extent #
  1216.     MVI    D,0
  1217.     INX    H
  1218.     MOV    A,M        ;Get sector count of last extent
  1219.     XCHG
  1220.     DAD    H        ;# of extents times 16k
  1221.     DAD    H
  1222.     DAD    H
  1223.     DAD    H
  1224.     XCHG            ;Save in DE
  1225.     LXI    H,BLKMSK
  1226.     ADD    M        ;Round last extent to block size
  1227.     RRC
  1228.     RRC            ;Convert from sectors to K
  1229.     RRC
  1230.     ANI    1FH
  1231.     MOV    L,A        ;Add to    total K
  1232.     MVI    H,0
  1233.     DAD    D
  1234.     LDA    BLKMSK        ;Get SECTORS/BLK-1
  1235.     RRC
  1236.     RRC            ;Convert to K/BLK
  1237.     RRC
  1238.     ANI    1FH
  1239.     CMA            ;Use to    finish rounding
  1240.     ANA    L
  1241.     MOV    L,A
  1242.     XCHG            ;Save file size    in DE
  1243.     LHLD    TOTSIZ
  1244.     DAD    D        ;Add to    total used
  1245.     SHLD    TOTSIZ
  1246.     LHLD    TOTFIL        ;Increment file    count
  1247.     INX    H
  1248.     SHLD    TOTFIL
  1249.     XCHG            ;Get back file size
  1250.  
  1251. * If report size enabled, output the size of the individual file.
  1252.  
  1253.     IF    REPSIZ        ;If file size report wanted
  1254.     CALL    DECPRT        ;..go print it
  1255.     MVI    A,'k'        ;..and follow with K size
  1256.     CALL    TYPE
  1257.     ENDIF
  1258.  
  1259. * One file output - test to see    if we have to output another one.
  1260.  
  1261.     LHLD    COUNT        ;Get current file counter and test it
  1262.     MOV    A,H
  1263.     ORA    L
  1264.     JZ    PRTOTL        ;If no more files, exit    to summary output
  1265.  
  1266. * At least one more file to output - can we put    it on the current line?
  1267.  
  1268.     DCR    C
  1269.     PUSH    PSW
  1270.     CNZ    FENCE        ;If room left, output the fence    character
  1271.     POP    PSW
  1272.     JNZ    ENTRY        ;.. and    go output another file
  1273.  
  1274. * Current line full, start a new one.
  1275.  
  1276. NEWLIN:    LDA    MNPL
  1277.     MOV    C,A        ;Reset names per line counter
  1278.     CALL    CRLF        ;Space down to next line
  1279.  
  1280.     MVI    A,3        ;If printing less than 4 wide
  1281.     CMP    C
  1282.     JC    NWLA
  1283.  
  1284.     LDA    FCB        ;.. precede new    line with drive    name
  1285.     ADI    'A'-1
  1286.     CALL    TYPE
  1287.  
  1288.     IF    REPUSR        ;If reporting user numbers and running under
  1289.     CALL    CKVER        ;..CP/M    2, output the user number too
  1290.     CNC    TYPUSR
  1291.     ENDIF            ;Balance REPUSR
  1292.  
  1293.     MVI    A,':'        ;Tag header with a colon and a space
  1294.     CALL    FPAD        ;..and exit back to ENTRY
  1295.  
  1296. NWLA:
  1297.  
  1298.     JMP    ENTRY        ;Go back and output another file
  1299.  
  1300. * Print    HL in decimal with leading zero    suppression
  1301.  
  1302. DECPRT:    SUB    A        ;Clear leading zero flag
  1303.     STA    LZFLG
  1304.     LXI    D,-1000        ;Print 1000's digit
  1305.     CALL    DIGIT
  1306.     LXI    D,-100        ;Etc.
  1307.     CALL    DIGIT
  1308.     LXI    D,-10
  1309.     CALL    DIGIT
  1310.     MVI    A,'0'        ;Get 1's digit
  1311.     ADD    L
  1312.     JMP    TYPE
  1313.  
  1314. DIGIT:    MVI    B,'0'        ;Start off with    ASCII 0
  1315.  
  1316. DIGLP:    PUSH    H        ;Save current remainder
  1317.     DAD    D        ;Subtract
  1318.     JNC    DIGEX        ;Quit on overflow
  1319.     POP    PSW        ;Throw away remainder
  1320.     INR    B        ;Bump digit
  1321.     JMP    DIGLP        ;Loop back
  1322.  
  1323. DIGEX:    POP    H        ;Restore pointer
  1324.     MOV    A,B
  1325.     CPI    '0'        ;Zero digit?
  1326.     JNZ    DIGNZ        ;No, type it
  1327.     LDA    LZFLG        ;Leading zero?
  1328.     ORA    A
  1329.     MVI    A,'0'
  1330.     JNZ    TYPE        ;Print digit
  1331.     LDA    SUPSPC        ;Get space suppression flag
  1332.     ORA    A        ;See if    printing file totals
  1333.     RZ            ;Yes, don't give leading spaces
  1334.     JMP    SPACE        ;Leading zero...print space
  1335.  
  1336. DIGNZ:    STA    LZFLG        ;Set leading zero flag so next zero prints
  1337.     JMP    TYPE        ;And print digit
  1338.  
  1339. * Show total space and files used
  1340.  
  1341. PRTOTL:
  1342.     IF    LOPT
  1343.     LDA    LOPFLG
  1344.     ORA    A
  1345.  
  1346.     IF    LOPREV
  1347.     JZ    PRTOT1
  1348.     ELSE
  1349.     JNZ    PRTOT1
  1350.     ENDIF
  1351.  
  1352.     LHLD    TOTFIL        ;How many files    did we match?
  1353.     MOV    A,H
  1354.     ORA    L
  1355.     CNZ    PRTLMEM        ;Skip the Library check if we didn't find any
  1356. PRTOT1    EQU    $
  1357.     ENDIF    
  1358.  
  1359.     XRA    A        ;Get a zero to...
  1360.     STA    SUPSPC        ;Suppress leading spaces in totals
  1361.  
  1362.     LHLD    TOTFIL        ;How many files    did we match?
  1363.     MOV    A,H
  1364.     ORA    L
  1365.  
  1366.     JZ    NXTUSR        ;Skip the summary if we    didn't find any
  1367.  
  1368.     PUSH    H        ;Save TOTFIL
  1369.     STA    FNDFLG        ;Set file found flag
  1370.  
  1371.     CALL    CRLF
  1372.     CALL    PRDIR        ;Print "  Drive, x User, y"
  1373.  
  1374. NOUSER:    LXI    D,TOTMS3    ;Print " CONTAINS "
  1375.     CALL    PRINT
  1376.     LHLD    TOTSIZ        ;Print total K used by files matched
  1377.     CALL    DECPRT
  1378.     LXI    D,TOTMS4    ;PRINT "K IN "
  1379.     CALL    PRINT
  1380.     POP    H        ;Recall    TOTFIL
  1381.     CALL    DECPRT        ;Print number of files matched
  1382.     LXI    D,TOTMS5    ;Print " FILES WITH "
  1383.     CALL    PRINT
  1384.     CALL    PRTFRE        ;Output    free space remaining & " FREE."
  1385.  
  1386. * Directory for    one user area completed.  If all users option is
  1387. * selected, then go do another directory on the    next user number
  1388. * until    we exceed the maximum user # for the selected drive.
  1389.  
  1390. NXTUSR:    IF    AOPT        ;If all    users option enabled
  1391.     LDA    AOPFLG        ;If not    all users mode - skip next
  1392.     ORA    A
  1393.     JNZ    GOCLZ
  1394.     CALL    CKVER        ;Are we running CP/M 2?
  1395.     JC    GOCLZ        ;Skip user increment if not
  1396.     CALL    CKABRT        ;Check for user    abort first
  1397.     LDA    MAXUSR        ;No abort - get    maximum    user number
  1398.     LXI    H,NEWUSR    ;Bump directory    user number
  1399.     INR    M
  1400.     CMP    M        ;Does next user    # exceed maximum?
  1401.     JNC    SETTBL        ;Continue if more user areas to    go
  1402.     ENDIF    ;AOPT
  1403.  
  1404.     IF    DOPT AND AOPT    ;If multi-disk option enabled
  1405.     LDA    BASUSR        ;Reset base user number    for the
  1406.     MOV    M,A        ;..next    directory search
  1407.     ENDIF            ;Balance DOPT and AOPT
  1408.  
  1409. * We've finished all of our outputting.  Flush the remainder of the
  1410. * output buffer and close the file before going to exit routine.
  1411.  
  1412. GOCLZ:    IF    FOPT
  1413. ;    LDA    FOPFLG        ;Is file output mode active?
  1414. ;    ORA    A
  1415. ;    JNZ    NXTDSK        ;If not, move to next drive, otherwise ..
  1416. ;    STA    PASS1        ;Make PASS1=0 to force reopen on next drive
  1417.  
  1418.     LXI    H,OPNFLG    ;get file open status then reset flag to
  1419.     MOV    A,M        ;..force reopen on next pass
  1420.     MVI    M,0
  1421.     ORA    A
  1422.     JZ    NXTDSK        ;skip closing sd.dir if it wasn't opened
  1423.  
  1424.     LXI    H,BUFCNT
  1425.     MOV    A,M        ;RETRIEVE # OF UNFLUSHED CHARACTERS IN BUFFER
  1426.     MVI    M,128        ;FORCE BUFCNT TO EMPTY STATUS FOR NEXT DRIVE
  1427.     ORA    A        ;IF BUFCNT=128, BUFFER EMPTY SO SET SIGN BIT
  1428.     JM    CLOSE        ;close sd.dir if buffer is empty
  1429.     JZ    FLUSH        ;write last record to sd.dir if buffer full
  1430.  
  1431.     LHLD    BUFPNT        ;OTHERWISE, PAD UNUSED BUFFER WITH CTRL-ZS
  1432. PUTAGN:    MVI    M,'Z'-40H
  1433.     INX    H
  1434.     DCR    A
  1435.     JNZ    PUTAGN        ;CONTINUE PADDING TIL BUFFER FILLED OUT
  1436. ;    MVI    A,128
  1437. ;    STA    BUFCNT        ;Force buffer to empty status
  1438.  
  1439. FLUSH:    LXI    D,OUTFCB    ;FLUSH THE LAST OUTPUT BUFFER
  1440.     MVI    C,WRITE
  1441.     CALL    CPM
  1442.     ORA    A
  1443.     JNZ    WRTERR
  1444. CLOZE:    LXI    D,OUTFCB    ;CLOSE THE OUTPUT FILE
  1445.     MVI    C,CLOSE
  1446.     CALL    CPM
  1447.     ENDIF            ;BALANCE FOPT
  1448.  
  1449. * Directory for    all user areas completed.  If the multi-disk option
  1450. * is enabled and selected, reset to the    base user area and repeat
  1451. * the directory    for next drive on-line until we    either exceed the
  1452. * drives in our    LODRV-HIDRV table, or the BDOS shuts us    down with
  1453. * a select or bad sector error,    which will be intercepted back to
  1454. * the EXIT module.
  1455.  
  1456. NXTDSK: LXI    H,FNDFLG    ;Get file found flag
  1457.     MOV    A,M
  1458.     MVI    M,0        ;Clear file found flag for next drive
  1459.     ORA    A
  1460.     JNZ    NDSK        ;Continue if at least 1 file found
  1461.  
  1462.     IF    FOPT        ;If file output enabled, disable temporarily
  1463.     LXI    H,FOPFLG
  1464.     DCR    M
  1465.     PUSH    H
  1466.     ENDIF
  1467.  
  1468.     LDA    FCB        ;Stash ASCII directory drive in NO FILE msg
  1469.     ADI    'A'-1
  1470.     STA    NOFMS2
  1471.     LXI    D,NOFMS1    ;Print "No file on ? - "
  1472.     CALL    PRINT
  1473.     CALL    PRTFRE        ;Tag with free message
  1474.  
  1475.     IF    FOPT        ;Restore original file output mode
  1476.     POP    H
  1477.     INR    M
  1478.     ENDIF
  1479.  
  1480. NDSK:    IF    DOPT        ;If multi-disk option enabled
  1481.     LDA    DOPFLG        ;If multi-disk not selected - skip next
  1482.     ORA    A
  1483.     JNZ    NPRT
  1484.     CALL    CKABRT        ;Check for user    abort first
  1485.     MVI    A,STSKIP    ;Skip if STart SKIP
  1486.     LXI    H,FCB        ;Bump directory    FCB drive code
  1487.     INR    M
  1488.     CMP    M
  1489.     JNZ    NEXT1
  1490.     MVI    A,SKIPTO    ;If STSKIP then SKIPTO
  1491.     MOV    M,A
  1492. NEXT1:    MVI    A,HIDRV-LODRV    ;Get maximum drive code    to search
  1493.     CMP    M        ;Does next disk    exceed maximum?
  1494.     JNC    NOOPT        ;Search    next disk if not
  1495.     ENDIF            ;Balance DOPT
  1496.  
  1497. NPRT:                ;if no printer, fall through to EXIT
  1498.  
  1499.     IF    POPT        ;now, check if printer is in use
  1500.     LDA    POPFLG
  1501.     ORA    A        ;printer active?
  1502.     JNZ    EXIT        ;no, just exit...
  1503.     MVI    C,5
  1504.     MVI    E,13        ;print a CRLF
  1505.     CALL    CPM
  1506.     MVI    E,10        ;line feed
  1507.     CALL    CPM
  1508.     ENDIF    ;POPT
  1509.  
  1510.     JMP    EXIT        ;All done - exit to CCP
  1511.  
  1512. * Print "Directory for....
  1513.  
  1514. PRDIR:    LXI    D,TOTMS1    ;Print [CR,LF]  " Drive    "
  1515.     CALL    PRINT
  1516.     LDA    FCB
  1517.     ADI    'A'-1
  1518.     CALL    TYPE        ;Output    the drive code
  1519.  
  1520.     IF    REPUSR
  1521.     CALL    CKVER
  1522.     JC    PRDIR1
  1523.     LXI    D,TOTMS2    ;Print ", USER "
  1524.     CALL    PRINT
  1525.     CALL    TYPUSR        ;Output    the user number
  1526.     ENDIF
  1527. PRDIR1:    RET
  1528.  
  1529. * Print    the user number    of the directory in decimal
  1530.  
  1531. TYPUSR:    IF    REPUSR
  1532.     LDA    NEWUSR
  1533.     CPI    10        ;If user no. > 9 print leading 1
  1534.     JC    DUX
  1535.     MVI    A,'1'
  1536.     CALL    TYPE
  1537.     LDA    NEWUSR        ;Print low digit of user no.
  1538.     SUI    10
  1539. DUX:    ADI    '0'
  1540.     JMP    TYPE
  1541.     ENDIF
  1542.  
  1543. * Force    new line on video and check for    page pause
  1544.  
  1545. CRLF:    MVI    A,0DH        ;Send CR
  1546.     CALL    TYPE
  1547.     MVI    A,0AH        ;Send LF
  1548.     JMP    TYPE        ;Exit to caller    from TYPE
  1549.  
  1550. * Separate the directory output    on a line with a space,    the delimiter,
  1551. * followed by another space.
  1552.  
  1553. FENCE:    CALL    SPACE
  1554.  
  1555.     LDA    MDELIM        ;Fence character
  1556. FPAD:    CALL    TYPE        ;Print it, fall    into space
  1557.  
  1558. SPACE:    MVI    A,' '        ;Fall through to TYPE
  1559.  
  1560. * Output character in A to console, and optionally to printer and/or
  1561. * the output file.
  1562.  
  1563. TYPE:    PUSH    B
  1564.     PUSH    D
  1565.     PUSH    H
  1566.  
  1567.     PUSH    PSW        ;Save the character to output
  1568.     CALL    TYPE1        ;Send it to console
  1569.     POP    PSW        ;Restore the output character
  1570.     ANI    7FH        ;Strip parity bit on character
  1571.  
  1572. * Test file output mode and skip to page pause test if not active.
  1573.  
  1574.     IF    FOPT
  1575.     MOV    B,A        ;Save stripped character to B
  1576.     LDA    FOPFLG        ;Is file output    active?
  1577.     ORA    A
  1578.     JNZ    NOWRIT        ;Go check for page pause if not
  1579.  
  1580. * File output mode active - make sure we have room in buffer to add
  1581. * next character.  If buffer full, write out current record first
  1582. * and then start a new record with current character.
  1583.  
  1584.     LHLD    BUFPNT        ;Get current buffer pointer
  1585.     LDA    BUFCNT        ;Get buffer capacity remaining
  1586.     ORA    A
  1587.     JNZ    PUTBUF        ;Continue if buffer not full
  1588.     CALL    SETFOP        ;Set the DMA address
  1589.     LXI    D,OUTFCB    ;Otherwise, write the current buffer out
  1590.     MVI    C,WRITE
  1591.     CALL    CPM        ;(Note call must save character    in B)
  1592.     ORA    A
  1593.     JNZ    WRTERR        ;Take write error exit if disk full or R/O
  1594.     LXI    H,OUTBUF    ;Reset buffer pointer
  1595.     MVI    A,128        ;Reset buffer capacity
  1596.  
  1597. PUTBUF: MOV    M,B        ;Shove character to next buffer position
  1598.     INX    H        ;Bump buffer pointer
  1599.     SHLD    BUFPNT        ;.. and save it
  1600.     DCR    A        ;Dock count of characters left in buffer
  1601.     STA    BUFCNT        ;..and save it
  1602.  
  1603. NOWRIT:    MOV    A,B        ;Recall    stripped character
  1604.  
  1605.     ENDIF            ;Balance FOPT
  1606.  
  1607.     IF    POPT        ;If printer option
  1608.     ANI    7FH        ;Strip parity bit on character
  1609.     MOV    E,A        ;Setup list output call
  1610.     MVI    C,5
  1611.     LDA    POPFLG        ;Test printer flag
  1612.     ORA    A
  1613.     CZ    CPM        ;Print character if flag true
  1614.     MOV    A,E        ;Recall    character
  1615.     ENDIF
  1616.  
  1617.     IF    PGPAWZ
  1618.     CPI    0AH        ;Do we have a LF?
  1619.     JNZ    TYPRET        ;Exit if not
  1620.     ENDIF
  1621.  
  1622.     IF    NOPT AND PGPAWZ
  1623.     LDA    NOPFLG        ;Is the    page pause function disabled?
  1624.     ORA    A
  1625.     JZ    TYPRET        ;Exit if so
  1626.     ENDIF
  1627.  
  1628.     IF    PGPAWZ
  1629.     LDA    LINCNT        ;Get line count
  1630.     INR    A        ;Bump it
  1631.     LXI    H,MLPS
  1632.     CMP    M        ;Are we    at the end of the screen?
  1633.     JC    NOTEOS        ;Skip if not
  1634.     LXI    D,EOSMSG    ;Else, display pause message
  1635.     MVI    C,9        ;..without checking for    LFs
  1636.     CALL    BDOS
  1637.     CALL    CINPUT        ;Wait for character
  1638.     CPI    'C'-40H
  1639.     JZ    EXIT        ;Abort on CTRL-C
  1640.     XRA    A        ;Reset line count
  1641. NOTEOS:    STA    LINCNT        ;Save new line count
  1642.     ENDIF
  1643.  
  1644. TYPRET:    POP    H        ;Exit from TYPE
  1645.     POP    D
  1646.     POP    B
  1647.     RET
  1648.  
  1649. * Output character
  1650.  
  1651. TYPE1:    IF    VECTOR
  1652.     ORA    A        ;Set sign flag if MS bit is on
  1653.     JP    TYPE2        ;If character is ASCII,    continue
  1654.     MOV    B,A        ;Else, get character to    B
  1655.     MVI    A,5        ;Set video driver function for direct output
  1656.     JMP    VIDEO        ;Display in reverse video and exit from    VIDEO
  1657.     ENDIF
  1658.  
  1659. TYPE2:    IF    REVIDEO
  1660.     ORA    A
  1661.     JP    TYPE99
  1662.     PUSH    PSW
  1663.     LDA    MLEADIN        ;Send ESC char first
  1664.     CALL    TYPE99
  1665.     LDA    MINTOREV    ;INTO REV VIDEO
  1666.     CALL    TYPE99
  1667.     LDA    MINTOREV+1
  1668.     CALL    TYPE99
  1669.     POP    PSW        ;Retrieve character
  1670.     ANI    7FH
  1671.     CALL    TYPE99
  1672.     LDA    MLEADIN        ;Send ESC first
  1673.     CALL    TYPE99
  1674.     LDA    MOUTAREV    ;The out of reverse video character
  1675.     CALL    TYPE99
  1676.     LDA    MOUTAREV+1    ;The out of reverse video character
  1677.  
  1678. TYPE99:
  1679.     ENDIF            ;Balance REVIDEO
  1680.  
  1681.     IF    DIRCON
  1682.     MOV    C,A        ;Get character into BIOS entry register
  1683.     LHLD    BASE+1        ;Get page base of BIOS
  1684.     MVI    L,12        ;Get entry vector to CONOUT
  1685.     JMP    GOHL        ;Call CONOUT direct through the BIOS
  1686.     ELSE
  1687.  
  1688.     MOV    E,A        ;Get character into BDOS entry register
  1689.     MVI    C,WRCHR
  1690.     JMP    BDOS        ;Call CONOUT via the BDOS
  1691.     ENDIF            ;Balance DIRCON
  1692.  
  1693.  
  1694. * Print    a string at HL of length B
  1695.  
  1696. TYPEIT:    MOV    A,M
  1697.     CALL    TYPE
  1698.     INX    H
  1699.     DCR    B
  1700.     JNZ    TYPEIT
  1701.     RET
  1702.  
  1703. * Print    string terminated with last byte high on console.
  1704.  
  1705. PRINT:    LDAX    D
  1706.     PUSH    PSW
  1707.     ANI    7FH
  1708.     CALL    TYPE
  1709.     POP    PSW
  1710.     ORA    A
  1711.     RM
  1712.     INX    D
  1713.     JMP    PRINT
  1714.  
  1715. * Fetch    character from console (without    echo)
  1716.  
  1717. CINPUT:    LHLD    BASE+1
  1718.     MVI    L,9
  1719.     CALL    GOHL
  1720.     ANI    7FH
  1721.     RET
  1722.  
  1723. * Check    for a CTRL-C or    CTRL-S entered from the    keyboard.  Jump    to
  1724. * exit if CTRL-C, pause    on CTRL-S.
  1725.  
  1726. CKABRT:    LHLD    BASE+1
  1727.     MVI    L,6        ;Check status of keyboard
  1728.     CALL    GOHL        ;Any key pressed?
  1729.     ORA    A
  1730.     RZ            ;No, return to caller
  1731.     CALL    CINPUT        ;Get character
  1732.     CPI    'C'-40H        ;CTRL-C?
  1733.     JZ    EXIT        ;If CTRL-C then    quit
  1734.     CPI    'S'-40H        ;CTRL-S?
  1735.     RNZ            ;No, return to caller
  1736.     CALL    CINPUT        ;Yes, wait for another char.
  1737.     CPI    'C'-40H        ;Might be CTRL-C
  1738.     JZ    EXIT        ;Exit if CTRL-C, else fall thru    and continue
  1739.     RET
  1740.  
  1741. * Kludge to allow call to address in HL
  1742.  
  1743. GOHL:    PCHL
  1744.  
  1745. * Entry    to BDOS    saving all extended registers
  1746.  
  1747. CPM:    PUSH    B
  1748.     PUSH    D
  1749.     PUSH    H
  1750.     CALL    BDOS
  1751.     MOV    B,A        ; Save return code
  1752.     LDA    VERFLG        ; Is this 3.0?
  1753.     CPI    30H
  1754.     MOV    A,B
  1755.     JC    CPM20        ; No, exit normally
  1756.     CPI    0FFH        ; It is 3.0 - was return code FF?
  1757.     JNZ    CPM20        ; No, exit normally
  1758.     MOV    A,H        ; 3.0 and A=FF - check for extended error code
  1759.     ORA    A
  1760.     JNZ    DSKERR        ; Trap out if we got a physical error
  1761.     MOV    A,B        ; Else continue normally
  1762. CPM20:
  1763.     POP    H
  1764.     POP    D
  1765.     POP    B
  1766.     RET
  1767.  
  1768. * For file output mode,    return to old user area    and set    DMA for
  1769. * the file output buffer.
  1770.  
  1771. SETFOP:    IF    UOPT OR    AOPT
  1772.     CALL    CKVER        ;Clear carry if    CP/M 2 or later
  1773.     LDA    OLDUSR        ;Get user number at startup
  1774.     MOV    E,A
  1775.     MVI    C,CURUSR
  1776.     CNC    CPM        ;Reset the old user number if CP/M 2
  1777.     ENDIF
  1778.  
  1779.     IF    FOPT
  1780.     LXI    D,OUTBUF    ;Move DMA from search buffer into the
  1781.     JMP    SET2        ;..output buffer
  1782.     ENDIF
  1783.     RET
  1784.  
  1785. * Move disk buffer DMA to default buffer for directory search operations
  1786. * and BDOS media change routines (necessary for pre-CP/M 2 systems while
  1787. * in file output mode with an active buffer).
  1788.  
  1789. SETSRC: LXI    D,BASE+80H
  1790. SET2:    MVI    C,SETDMA
  1791.     JMP    CPM
  1792.  
  1793. * Print    the amount of free space remaining on the selected drive
  1794.  
  1795. PRTFRE: LHLD    FREEBY        ;Get space left before adding to MASTER.DIR
  1796.     CALL    DECPRT        ;Print K free
  1797.     LXI    D,TOTMS6    ;Print " FREE."
  1798.     JMP    PRINT
  1799.  
  1800. * Compare routine for sort
  1801.  
  1802. COMPR:    PUSH    H        ;Save table addr
  1803.     MOV    E,M        ;Load low order
  1804.     INX    H
  1805.     MOV    D,M        ;Load high order
  1806.     INX    H
  1807.     MOV    C,M
  1808.     INX    H
  1809.     MOV    B,M
  1810.  
  1811. * BC, DE now point to entries to be compared
  1812.  
  1813.     XCHG
  1814.     MOV    E,A        ;Get count
  1815.  
  1816. CMPLP:    MOV    A,M
  1817.     ANI    7FH
  1818.     MOV    D,A
  1819.     LDAX    B
  1820.     ANI    7FH
  1821.     CMP    D
  1822.     INX    H
  1823.     INX    B
  1824.     JNZ    NOTEQL        ;Quit on mismatch
  1825.     DCR    E        ;Or end    of count
  1826.     JNZ    CMPLP
  1827.  
  1828. NOTEQL:    POP    H
  1829.     RET            ;Cond code tells all
  1830.  
  1831. * Swap entries in the order table
  1832.  
  1833. SWAP:    LXI    B,ORDER-2    ;Table base
  1834.     DAD    H        ;*2
  1835.     DAD    B        ;+ base
  1836.     XCHG
  1837.     DAD    H        ;*2
  1838.     DAD    B        ;+ base
  1839.     MOV    C,M
  1840.     LDAX    D
  1841.     XCHG
  1842.     MOV    M,C
  1843.     STAX    D
  1844.     INX    H
  1845.     INX    D
  1846.     MOV    C,M
  1847.     LDAX    D
  1848.     XCHG
  1849.     MOV    M,C
  1850.     STAX    D
  1851.     RET
  1852.  
  1853. * New compare routine - modified for filetype sort
  1854.  
  1855. COMPARE:
  1856.     LXI    B,ORDER-2
  1857.     DAD    H    
  1858.     DAD    B    
  1859.     XCHG        
  1860.     DAD    H    
  1861.     DAD    B
  1862.     XCHG
  1863.  
  1864.     MOV    C,M        
  1865.     INX    H        
  1866.     MOV    B,M
  1867.     XCHG
  1868.     MOV    E,M    
  1869.     INX    H    
  1870.     MOV    D,M
  1871.     XCHG
  1872.  
  1873.     IF    TOPT        ;If T option true
  1874.     LDA    TOPFLG        ;Get option flag
  1875.     ORA    A        ;test for zero
  1876.     IF    TOPREV        ;If reverse "T" option
  1877.     JZ    CMPFNFT        ;and "T" option choosen JMP
  1878.     ELSE
  1879.     JNZ    CMPFNFT
  1880.     ENDIF
  1881. *
  1882. * Compare by Filename, Filetype, and Extent - in that order
  1883. *
  1884.     PUSH    H
  1885.     PUSH    B
  1886.     LXI    D,8    ;Pt to FT
  1887.     CALL    ADDEM
  1888.     MVI    E,3    ; 3 bytes in type
  1889.     CALL    CMPLPE    ;compare FT'S
  1890.     POP    B
  1891.     POP    H
  1892.     RNZ        ;Continue if match
  1893.     PUSH    H
  1894.     PUSH    B
  1895.     MVI    E,8    ;8 bytes in name
  1896.     CALL    CMPLPE    ;Compare FN'S
  1897.     POP    B
  1898.     POP    H
  1899.     RNZ        ;Continue if match
  1900.     LXI    D,11    ;Pt to EXT
  1901.     CALL    ADDEM
  1902.     LDAX    B    ;Compare EXT'S
  1903.     CMP    M
  1904.     RET
  1905.  
  1906. ADDEM:    PUSH    H    ;Adds DE to HL & BC
  1907.     MOV    H,B
  1908.     MOV    L,C
  1909.     DAD    D
  1910.     MOV    B,H
  1911.     MOV    C,L
  1912.     POP    H
  1913.     DAD    D
  1914.     RET
  1915.     ENDIF
  1916.  
  1917. *
  1918. *  Compare by Filename, Filetype, Extent - in that order
  1919. *
  1920. CMPFNFT:
  1921.     MVI    E,12    ;Compare FN, FT, EX
  1922.             ; and fall into routine
  1923. CMPLPE:
  1924.     MOV    A,M    
  1925.     ANI    7FH    
  1926.     MOV    D,A    
  1927.     LDAX    B    
  1928.     ANI    7FH    
  1929.     CMP    D
  1930.     INX    B
  1931.     INX    H
  1932.     RNZ
  1933.     DCR    E        
  1934.     JNZ    CMPLPE
  1935.     RET
  1936.  
  1937. HELP:    INX    H        ;Make sure there is a 
  1938.     CMP    M        ;second "/" else return
  1939.     DCX    H        ;since some people use / 
  1940.     RNZ            ;for a file name
  1941. HELP1:    LXI    D,HLPMES    ;Print a short HELP message
  1942.     CALL    PRINT
  1943.     CALL    CRLF
  1944.     JMP    EXIT
  1945.  
  1946. * Error    exit
  1947.  
  1948. ERXIT:    IF    FOPT
  1949.     MVI    A,-1
  1950.     STA    FOPFLG        ;Disable file output mode on error
  1951.     ENDIF
  1952.  
  1953.     CALL    CRLF        ;Space down
  1954.     POP    D        ;Get pointer to    message    string
  1955.     CALL    PRINT        ;Print it
  1956.     LXI    D,ERRMS1    ;Print " Error"
  1957.     CALL    PRINT
  1958.     CALL    CRLF        ;Space down
  1959.  
  1960. * Exit - all done, restore stack
  1961.  
  1962. EXIT:    MVI    C,CONST        ;Check console status
  1963.     CALL    CPM
  1964.     ORA    A        ;Char waiting?
  1965.     MVI    C,RDCHR
  1966.     CNZ    CPM        ;Gobble    up char
  1967.  
  1968.     IF    DOPT        ;Restore BDOS intercept    vectors
  1969.     LDA    VERFLG        ;Or error mode, depending on version
  1970.     CPI    30H
  1971.     JC    EXIT0
  1972.     MVI    C,45
  1973.     MVI    E,0        ;Set error mode back to default
  1974.     CALL    CPM
  1975.     JMP    EXIT1
  1976. EXIT0:
  1977.     LDA    DOPFLG        ;..if they were swapped
  1978.     ORA    A
  1979.     CZ    SWAPEM
  1980. EXIT1:
  1981.     ENDIF
  1982.  
  1983.     IF    ROPT
  1984.     LDA    ROPFLG        ;If disk system    was reset
  1985.     ORA    A
  1986.     LDA    OLDDSK        ;Get default disk at startup
  1987.     MOV    E,A
  1988.     MVI    C,SELDSK    ;Reselect it
  1989.     CZ    CPM
  1990.     ENDIF            ;Balance ROPT
  1991.  
  1992.     LHLD    STACK        ;Get old stack pointer
  1993.     SPHL            ;Move back to old stack
  1994.     RET            ;..and return to CCP
  1995.  
  1996. * Trap BDOS select and sector error vectors to our own intercept
  1997. * routine so we    can catch a reference to an illegal drive.
  1998.  
  1999.     IF    DOPT
  2000. SWAPEM:    LDA    VERFLG        ;Check version
  2001.     CPI    30H        ;see if error mode call is available
  2002.     JC    SWAP20        ;If not, use BDOS error vectors
  2003.     MVI    C,45
  2004.     MVI    E,0FFH        ;Use Set Error Mode call
  2005.     CALL    CPM        ;set "return code only" mode
  2006.     RET
  2007.  
  2008. SWAP20:    LHLD    BDOS+1        ;Get pointer to    base of    BDOS
  2009.     ENDIF    ;DOPT
  2010.  
  2011.     IF    DOPT AND LOWCCP
  2012.     LDA    BDOSPAG        ;get "proper" BDOS page
  2013.     MOV    E,A        ;save it in "E"
  2014. ;
  2015.     MOV    A,H        ;get location of BDOS
  2016.     CMP    E        ;is it where BDOS normally is?
  2017.     JZ    BDCHK2        ;yes, but perform second check just to be
  2018.                 ;sure we are OK.
  2019.     INX    H        ;swap in the new pointer if running a prg
  2020.     MOV    E,M        ;below the CCP
  2021.     INX    H
  2022.     MOV    D,M
  2023.     XCHG            ;now HL points to the proper vector
  2024.     JMP    SWAPOK        ;bypass second check
  2025.     ENDIF    ;DOPT AND LOWCCP
  2026.  
  2027.     IF    DOPT
  2028. BDCHK2:    MOV    A,L
  2029.     SUI    6        ;Check if pointing directly to BDOS
  2030.     JZ    SWAPOK        ;Continue if true
  2031.     MVI    A,'D'        ;Undo option request for multi-disk
  2032.     STA    DOPFLG
  2033. SWAPOK:    MVI    L,9        ;Point to sector error vector
  2034.     LXI    D,VECTBL    ;Exchanging with our own vector    table
  2035.     MVI    A,4        ;4 bytes to swap
  2036. SWAPLP:    MOV    B,M        ;Get byte from HL
  2037.     XCHG
  2038.     MOV    C,M        ;Get byte from DE
  2039.     MOV    M,B        ;Put byte from HL
  2040.     XCHG
  2041.     MOV    M,C        ;Put byte from DE
  2042.     INX    H        ;Bump exchange pointers
  2043.     INX    D
  2044.     DCR    A        ;Dock counter
  2045.     JNZ    SWAPLP        ;Continue swapping til done
  2046.     RET
  2047.     ENDIF
  2048.  
  2049. * Check    CP/M version number.  Return carry flag    set if pre-CP/M    2.
  2050. * If CP/M 2 or later or    MP/M (any version), return carry clear.
  2051.  
  2052. CKVER:    LDA    VERFLG
  2053.     CPI    20H
  2054.     RET
  2055.  
  2056. * Recovery point from intercepted BDOS select and bad sector errors.
  2057.  
  2058. DSKERR: IF    DOPT
  2059.     LXI    SP,STACK    ;Get out of BDOS' stack
  2060.     JMP    EXIT        ;..and exit back to CCP
  2061.     ENDIF
  2062.  
  2063.     IF    LOPT
  2064. ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2065. ;
  2066. ;    SUBROUTINES to read library file directory
  2067. ;
  2068. ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2069. ;
  2070. PRTLMEM    LXI    H,ORDER        ;Initialize order table    pointer
  2071.     SHLD    NEXTL
  2072.     XRA    A
  2073.     STA    LNCNT
  2074. ENTRYL    LHLD    LCOUNT
  2075.     MOV    A,H        ;Is this the last file?
  2076.     ORA    L
  2077.     JZ    LBEXIT        ;If COUNT=0, last file so RETURN
  2078.     DCX    H        ;Dock file count
  2079.     SHLD    LCOUNT
  2080.     PUSH    B
  2081.     CALL    CKABRT        ;Check for abort code from keyboard
  2082.     LHLD    NEXTL
  2083.     MVI    A,11
  2084.     CALL    COMPR        ;Does this entry match next one?
  2085.     POP    B
  2086.     JNZ    LBRTST        ;No, print it
  2087.     INX    H
  2088.     INX    H        ;Skip since highest extent comes last in list
  2089.     SHLD    NEXTL
  2090.     JMP    ENTRYL        ;Loop back for next lowest extent
  2091. ;
  2092. ;    Exit Library member printing
  2093. ;
  2094. LBEXIT    LHLD    LMTOTL
  2095.     MOV    A,H
  2096.     ORA    L
  2097.     RZ
  2098.     PUSH    H        ;Save Member count
  2099.     XRA    A        ;Get a zero to...
  2100.     STA    SUPSPC        ;Suppress leading spaces in totals
  2101.     LXI    H,MNPL
  2102.     LDA    LNCNT
  2103.     CMP    M
  2104.     CNZ    CRLF
  2105.     LXI    D,CONTM        ;Print "There are "
  2106.     CALL    PRINT
  2107.     POP    H        ;GET TOTAL MEMBER COUNT BACK
  2108.     CALL    DECPRT
  2109.     LXI    D,MFILES    ;PRINT "Members in "
  2110.     CALL    PRINT
  2111.     LHLD    LBTOTL
  2112.     CALL    DECPRT
  2113.     LXI    D,LIBR
  2114.     CALL    PRINT
  2115.     RET
  2116.  
  2117. * Valid    entry obtained - spit it out.
  2118.  
  2119. LBRTST:    LHLD    NEXTL        ;Get order table pointer
  2120.     MOV    E,M        ;Get low order address
  2121.     INX    H
  2122.     MOV    D,M        ;Get high order    address
  2123.     INX    H
  2124.     SHLD    NEXTL        ;Save updated table pointer
  2125.     LXI    H,8
  2126.     DAD    D
  2127.     CALL    CKLBR
  2128.     JNZ    ENTRYL
  2129.     PUSH    D
  2130.     LXI    H,MNPL
  2131.     LDA    LNCNT
  2132.     CMP    M
  2133.     CNZ    CRLF
  2134.     LXI    H,LFMSEP
  2135.     MVI    B,31
  2136.     CALL    TYPEIT
  2137.     POP    H
  2138.     PUSH    H
  2139.     MVI    B,8        ;File name length
  2140.     CALL    TYPEIT
  2141.     MVI    A,'.'        ;Period    after FN
  2142.     CALL    TYPE
  2143.     MVI    B,3        ;Display 3 characters of filetype
  2144.     CALL    TYPEIT
  2145.     CALL    CRLF
  2146.     POP    H
  2147. ;
  2148. ; Saves the library file name into LBRFCB
  2149. ;
  2150.     LDA    FCB
  2151.     LXI    D,LBRFCB    ;TO
  2152.     STAX    D
  2153.     INX    D
  2154.     MVI    B,11        ;LEN
  2155.     CALL    MOVE        ;DO THE MOVE
  2156.     XCHG
  2157.     MVI    B,25
  2158. CLMFCB    MVI    M,0
  2159.     INX    H
  2160.     DCR    B
  2161.     JNZ    CLMFCB
  2162.     CALL    SETLDMA
  2163.     LXI    D,LBRFCB    ;POINT TO FILE
  2164.     MVI    C,OPEN        ;GET FUNCTION
  2165.     CALL    CPM        ;OPEN IT
  2166.     MVI    C,READ
  2167.     LXI    D,LBRFCB
  2168.     CALL    CPM
  2169.     CALL    SETFOP
  2170.     LXI    H,LBBUF
  2171.     MOV    A,M
  2172.     ORA    A
  2173.     JZ    CKLDIR        ;check directory present?
  2174. BADLBR    LXI    H,NLBRF
  2175.     MVI    B,25
  2176.     CALL    TYPEIT
  2177. LMLEXI    CALL    LBCLOSE
  2178.     JMP    ENTRYL
  2179. NLBRF    DB    '++Not a LIBRARY file.++',13,10
  2180. ;
  2181. ;    Close the library file
  2182. ;
  2183. LBCLOSE    LXI    D,LBRFCB
  2184.     MVI    C,CLOSE
  2185.     CALL    CPM
  2186.     RET
  2187. ;
  2188. ; SETLDMA - Set the Library file DMA adderss
  2189. ;
  2190. SETLDMA    CALL    CKVER        ;Set carry if pre-CP/M 2
  2191.     LDA    NEWUSR        ;Get user area for directory
  2192.     MOV    E,A
  2193.     MVI    C,CURUSR    ;Get the user function
  2194.     CNC    CPM        ;..and set new user number if CP/M 2
  2195.     LXI    D,LBBUF
  2196.     MVI    C,SETDMA
  2197.     CALL    CPM
  2198.     RET
  2199. ;
  2200. ; CKLDIR - check to see if there indeed is a LBR file
  2201. ;      directory and barf if not!
  2202. ;
  2203. CKLDIR:    MVI    B,11        ;len of file name
  2204.     MVI    A,' '        ;space
  2205.     INX    H
  2206. CKDLP:    CMP    M
  2207.     JNZ    BADLBR
  2208.     DCR    B
  2209.     INX    H
  2210.     JNZ    CKDLP
  2211. ;
  2212. ; The first entry in the LBR directory is indeed blank.
  2213. ; Now see if the directory size is >0
  2214. ;
  2215.     MOV    E,M    ;file starting location low
  2216.     INX    H    ;must be zero here
  2217.     MOV    A,M    ;file starting location high
  2218.     ORA    E    ;must be zero here also
  2219.     JNZ    BADLBR
  2220.     INX    H
  2221.     MOV    E,M    ;get library size low
  2222.     INX    H    ;point to library size high
  2223.     MOV    D,M    ;get library size high
  2224.     MOV    A,D
  2225.     ORA    E    ;library must have some size
  2226.     JZ    BADLBR
  2227.     DCX    D
  2228.     XCHG
  2229.     SHLD    SLFILE
  2230.     LHLD    LBTOTL
  2231.     INX    H
  2232.     SHLD    LBTOTL
  2233.     LDA    MNPL
  2234.     STA    LNCNT        ;Reset names per line counter
  2235.     MVI    B,3
  2236.     LXI    H,17
  2237.     DAD    D
  2238.     LDA    MNPL
  2239.     STA    LNCNT        ;Reset names per line counter
  2240.     JMP    LMTEST
  2241. LFMLOP    LHLD    SLFILE    ;GET
  2242.     MOV    A,L
  2243.     ORA    H
  2244.     JZ    LMLEXI
  2245.     DCX    H
  2246.     SHLD    SLFILE
  2247.     CALL    SETLDMA
  2248.     MVI    C,READ
  2249.     LXI    D,LBRFCB
  2250.     CALL    CPM
  2251.     CALL    SETFOP
  2252.     MVI    B,4    ;GET FILE COUNT PER SECTOR
  2253.     LXI    H,LBBUF    ;GET BUFFER STARTING ADDRESS
  2254. LMTEST    MOV    A,M    ;Get member open flag
  2255.     ORA    A    ;TEST FOR OPEN
  2256.     JZ    PRMNAM
  2257. LMTESA    LXI    D,32    ;Member not open get offset
  2258.     DAD    D    ;to next and add it in.
  2259.     DCR    B    ;is buffer empty ?
  2260.     JNZ    LMTEST    ;No so test next entry
  2261.     JMP    LFMLOP    ;Yes get next buffer...
  2262. PRMNAM    PUSH    H    ;Print member NAME and SIZE
  2263.     PUSH    B
  2264.     CALL    CKABRT    ;Check for abort code from keyboard
  2265.     LXI    H,LNCNT
  2266.     LDA    MNPL
  2267.     CMP    M
  2268.     JNZ    PRMNA1
  2269.     MVI    A,3        ;If printing less than 4 wide
  2270.     CMP    M
  2271.     JC    PRMNA1
  2272.     LDA    LBRFCB        ;.. precede new    line with drive    name
  2273.     ADI    'A'-1
  2274.     CALL    TYPE
  2275.  
  2276.     IF    REPUSR        ;If reporting user numbers and running under
  2277.     CALL    CKVER        ;..CP/M    2, output the user number too
  2278.     CNC    TYPUSR
  2279.     ENDIF            ;Balance REPUSR
  2280.  
  2281.     MVI    A,':'        ;Tag header with a colon and a space
  2282.     CALL    FPAD        ;..and exit back to ENTRY
  2283. PRMNA1    POP    B
  2284.     POP    H
  2285.     PUSH    H
  2286.     PUSH    B
  2287.     INX    H
  2288.     MVI    B,8        ;File name length
  2289.     CALL    TYPEIT
  2290.     MVI    A,'.'        ;Period    after FN
  2291.     CALL    TYPE
  2292.     MVI    B,3        ;Display 3 characters of filetype
  2293.     CALL    TYPEIT
  2294.     INX    H
  2295.     INX    H
  2296.     MOV    E,M
  2297.     INX    H
  2298.     MOV    D,M
  2299.     XCHG
  2300.  
  2301. * If report size enabled, output the size of the individual file.
  2302.  
  2303.     IF    REPSIZ        ;If file size report wanted
  2304.     CALL    DECPRT        ;..go print it
  2305.     MVI    A,'s'        ;..and follow with S size
  2306.     CALL    TYPE
  2307.     ENDIF
  2308.  
  2309. * At least one more file to output - can we put    it on the current line?
  2310.  
  2311.     LHLD    LMTOTL
  2312.     INX    H
  2313.     SHLD    LMTOTL
  2314.     LDA    LNCNT
  2315.     DCR    A
  2316.     STA    LNCNT
  2317.     PUSH    PSW
  2318.     CNZ    FENCE        ;If room left, output the fence    character
  2319.     POP    PSW
  2320.     POP    B
  2321.     POP    H
  2322.     JNZ    LMTESA        ;.. and    go output another file
  2323.  
  2324. * Current line full, start a new one.
  2325.  
  2326.     LDA    MNPL
  2327.     STA    LNCNT        ;Reset names per line counter
  2328.     CALL    CRLF        ;Space down to next line
  2329.     JMP    LMTESA
  2330. ;
  2331. ; Move characters from 'HL' to 'DE' length in 'B'
  2332. ;
  2333. MOVE:    MOV    A,M        ;GET A CHAR
  2334.     STAX    D        ;STORE IT
  2335.     INX    H        ;TO NEXT "FROM"
  2336.     INX    D        ;TO NEXT "TO"
  2337.     DCR    B        ;MORE?
  2338.     JNZ    MOVE        ;   YES, LOOP
  2339.     RET            ;   NO, RETURN
  2340. ;
  2341. ; cklbr -- test file extent for LBR
  2342. ;
  2343. CKLBR    PUSH    H
  2344.     PUSH    D
  2345.     PUSH    B
  2346.     XCHG
  2347.     LXI    H,LBRTYP
  2348.     MVI    C,3
  2349. CKLBL    LDAX    D
  2350.     ANI    7FH
  2351.     CMP    M
  2352.     JNZ    CKLBX
  2353.     INX    H
  2354.     INX    D
  2355.     DCR    C
  2356.     JNZ    CKLBL
  2357. CKLBX    POP    B
  2358.     POP    D
  2359.     POP    H
  2360.     RET
  2361. ;
  2362. LFMSEP    db    '    Library file members for : '
  2363. LBRTYP    db    'LBR'
  2364.     ENDIF    ;LOPT
  2365.  
  2366. ***********************
  2367. *              *
  2368. * End of Program Code *
  2369. *              *
  2370. ***********************
  2371.  
  2372. * Initialized data area
  2373.  
  2374. DREMSG:    DB    'Driv','e' OR 80H
  2375.  
  2376.     IF    PGPAWZ
  2377. EOSMSG: DB    '    [More]',0DH,'$'
  2378.     ENDIF
  2379.  
  2380. ERRMS1: DB    ' '
  2381. ERRMS2:    DB    'Erro','r' OR 80H
  2382.  
  2383.     IF    REPERR
  2384. ERRTAG:    DB    ' -','>' OR 80H
  2385.     ENDIF
  2386.  
  2387. NOFMS1: DB    0DH,0AH,'No file on '
  2388. NOFMS2: DB    '  -',' ' OR 80H
  2389.  
  2390. DIRMS1:    DB    0DH,0AH,'  Directory fo','r' OR 80H 
  2391.  
  2392. TOTMS1:    DB    '  Drive',' ' OR 80H
  2393.  
  2394.     IF    REPUSR
  2395. TOTMS2:    DB    ', user',' ' OR    80H
  2396.     ENDIF
  2397.  
  2398. TOTMS3:    DB    ' contains',' '    OR 80H
  2399. TOTMS4: DB    'k in',' ' OR 80H
  2400. TOTMS5:    DB    ' files with',' ' OR 80H
  2401. TOTMS6: DB    'k free','.',0DH,0AH OR 80H            ;,0DH,0AH OR 80H
  2402. USRMSG: DB    'User ','#' OR 80H
  2403.  
  2404.     IF    LOPT
  2405. CONTM    DB    '    There are',' '+80H
  2406. MFILES    DB    ' Member Files in',' '+80H
  2407. LIBR    DB    ' Library(s)','.'+80H
  2408.     ENDIF
  2409.  
  2410. FNDFLG: DB    0        ;Flag whether any files matched
  2411.  
  2412.     IF    PGPAWZ
  2413. LINCNT:    DB    0        ;Count of lines    printed    on screen
  2414.     ENDIF
  2415.  
  2416. * Drive    code/user area lookup table
  2417.  
  2418. * Note that the    LODRV-HIDRV table is included here fully configured.
  2419. * For your own use, you    should change the maximum user areas as
  2420. * appropriate for each drive on    your system, and then delete any
  2421. * DBs referencing drives that don't exist.  Note also that there
  2422. * are only 16 user areas available under CP/M 2, so the highest
  2423. * legal user area you can specify is 15 (range 0-15 = 16 areas).
  2424. * The program will convert anything over 15 into mod 15.
  2425. * NOTE: If some drives in active table are unused then skip these
  2426. * drives by using STSKIP and SKIPTO equates.
  2427.  
  2428. LODRV    EQU    $        ;Mark beginning    of drive/user table
  2429.  
  2430.     DB    15         ;Maximum user area for Drive A
  2431.     DB    15         ;   "      "    "    "     "   B
  2432.      DB    00        ;   "      "    "    "     "   C
  2433.      DB    00        ;   "      "    "    "     "   D
  2434.      DB    00        ;   "      "    "    "     "   E
  2435.      DB    00        ;   "      "    "    "     "   F
  2436.      DB    00         ;   "      "    "    "     "   G
  2437.      DB    00         ;   "      "    "    "     "   H
  2438.      DB    00         ;   "      "    "    "     "   I
  2439.      DB    00         ;   "      "    "    "     "   J
  2440.      DB    00           ;   "      "    "    "     "   K
  2441.      DB    00         ;   "      "    "    "     "   L
  2442.      DB    15        ;   "      "    "    "     "   M
  2443. ;    DB    15        ;   "      "    "    "     "   N
  2444. ;    DB    15        ;   "      "    "    "     "   O
  2445. ;    DB    15        ;   "      "    "    "     "   P
  2446.  
  2447. HIDRV    EQU    $        ;Mark end of drive/user    table
  2448.  
  2449. * Option field lookup table.
  2450. * Note that you    can force any of these options as a DEFAULT by
  2451. * changing the letter for the option into a zero (assuming that
  2452. * its enabling equate is true).     Each option that you hard-wire    in
  2453. * this manner will no longer be    recognized as a    command    line OPTION,
  2454. * and if you redundantly key it in, SD will flag it as unrecognized.
  2455.  
  2456. OTBL    EQU    $        ;Mark start of option table
  2457.  
  2458.     IF    AOPT        ;All users-option flag
  2459. AOPFLG:    DB     'A'
  2460.     ENDIF
  2461.  
  2462.     IF    DOPT        ;Multi-disk-option flag
  2463. DOPFLG:    DB     'D' 
  2464.     ENDIF
  2465.  
  2466.     IF    FOPT        ;File-output-option flag
  2467. FOPFLG:    DB    'F'
  2468.     ENDIF
  2469.  
  2470.     IF    LOPT        ;Display Library members flag
  2471. LOPFLG:    DB    'L'
  2472.     ENDIF
  2473.  
  2474.     IF    NOPT AND PGPAWZ    ;No page-pause option flag
  2475. NOPFLG:    DB    'N'
  2476.     ENDIF
  2477.  
  2478.     IF    POPT        ;Printer option    flag
  2479. POPFLG:    DB    'P'
  2480.     ENDIF
  2481.  
  2482.     IF    ROPT        ;Reset option flag
  2483. ROPFLG:    DB    'R'
  2484.     ENDIF
  2485.  
  2486.     IF    SOPT        ;System    file option flag
  2487. SOPFLG:    DB     'S' 
  2488.     ENDIF
  2489.  
  2490.     IF    TOPT
  2491. TOPFLG:    DB    'T'        ;Type sort option flag
  2492.     ENDIF
  2493.  
  2494.     IF    VOPT        ;Display version number flag
  2495. VOPFLG:    DB    'V'
  2496.     ENDIF
  2497.  
  2498. OEND    EQU    $        ;Mark end of option table
  2499.  
  2500. * End of option    lookup table
  2501.  
  2502. ;    IF    AOPT
  2503. ;PASS1: DB    0        ;First pass flag for all user file output
  2504. ;    ENDIF
  2505.  
  2506.     IF    DOPT
  2507. VECTBL: DW    DSKERR        ;BDOS SECTOR ERROR INTERCEPT VECTOR
  2508.     DW    DSKERR        ;BDOS SELECT ERROR INTERCEPT VECTOR
  2509.     ENDIF
  2510.  
  2511.     IF    FOPT
  2512. BUFPNT: DW    OUTBUF        ;POINTER TO NEXT LOCATION IN OUTPUT BUFFER
  2513. BUFCNT: DB    128        ;NUMBER OF BYTES LEFT IN OUTPUT BUFFER
  2514. opnflg: db    0        ;file open flag for all user file output
  2515. OUTFCB:    DB    0,'SD      DIR'
  2516.     FILL    21,0        ;REST OF SD.DIR FCB
  2517. OUTBUF    DS    128        ;OUTPUT FILE BUFFER
  2518.     ENDIF
  2519.  
  2520.     IF    STARTZ
  2521. GOTUSR:    DB    0
  2522.     ENDIF
  2523.  
  2524. * Uninitialized    data area
  2525.  
  2526. BASUSR    DS    1        ;Dupe of original directory user # to search
  2527. BLKMAX    DS    2        ;Highest block # on drive
  2528. BLKMSK    DS    1        ;SEC/BLK - 1
  2529. BLKSHF    DS    1        ;# shifts to mult by SEC/BLK
  2530. COUNT    DS    2        ;Entry count
  2531. DIRMAX    DS    2        ;Highest file #    in directory
  2532. FREEBY    DS    2        ;Contains number of K left on directory    drive
  2533. GAP    DS    2        ;Sort routine storage
  2534. I    DS    2        ;Sort routine storage
  2535. J    DS    2        ;Sort routine storage
  2536. JG    DS    2        ;Sort routine storage
  2537. LZFLG    DS    1        ;0 when    printing leading zeros
  2538. MAXUSR    DS    1        ;Maximum user #    for drive from lookup table
  2539. NEWUSR    DS    1        ;Contains user number selected by "$U" option
  2540. NEXTT    DS    2        ;Next table entry
  2541. OLDDSK    DS    1        ;Holder    for currently logged-in    drive
  2542. OLDUSR    DS    1        ;Contains user number upon invocation
  2543. SCOUNT    DS    2        ;# to sort
  2544. SUPSPC    DS    1        ;Leading space flag for    decimal    routine
  2545. TBLOC    DS    2        ;Pointer to start of name table
  2546. TEMP    DS    2        ;Save dir entry
  2547. TOTFIL    DS    2        ;Total number of files
  2548. TOTSIZ    DS    2        ;Total size of all files
  2549. VERFLG    DS    1        ;CP/M version number (0=pre-CP/M 2)
  2550.  
  2551.     IF    LOPT
  2552. LMTOTL    DW    0
  2553. LBTOTL    DW    0
  2554. LNCNT    DB    0
  2555. LCOUNT    DW    0
  2556. NEXTL    DW    0
  2557. SLFILE    DW    0
  2558. LBRFCB:    DS    36
  2559. LBBUF    DS    80H
  2560.     ENDIF
  2561.  
  2562.     DS    60        ;Stack area
  2563. STACK    DS    2        ;Save old stack    pointer    here
  2564.  
  2565. ORDER    EQU    $        ;Order table starts here
  2566.  
  2567.     END
  2568.