home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / lambda / soundpot / p / sd100.lbr / SD100.AZM / SD100.ASM
Encoding:
Assembly Source File  |  1993-10-25  |  95.3 KB  |  4,081 lines

  1. ;************************************************************************
  2. ;*                                    *
  3. ;*             < - SUPER DIRECTORY PROGRAM - >            *
  4. ;*                SD100                    *
  5. ;************************************************************************
  6. ;
  7. MAIN    EQU    1    ; Main block number
  8. VER    EQU    00    ; Current version
  9. ;
  10. MONTH    EQU    7    ; July
  11. DAY    EQU    24    ; Day
  12. YEAR    EQU    85    ; Year
  13. ;
  14.     ASEG    ; Needed for m80, ignore error made with mac
  15. ;
  16. ;    NOTE:    This version can be assembled with ASM, LASM,
  17. ;        MAC, RMAC or M80.  The name has been slightly
  18. ;        changed as M80 cannot use names with a dash.
  19. ;
  20. ;=======================================================================
  21. ;
  22. ; Displays the directory of a CP/M disk, sorted alphabetically, with the
  23. ; file size in k, rounded to the nearest CP/M block size.  Also displays
  24. ; library files with the file size in k if the '$L' option is used.
  25. ;
  26. ;======================================================================
  27. ;
  28. ; 07/24/85  Rewrote the TIMEON code to allow use of the existing time-
  29. ;   v100    on-system data contained in BYE5, BYE3, BYE+ or MBYE's RTC
  30. ;        buffer.  If TIMEON is YES, SD merely reports "Time on system
  31. ;        is nnn minutes" and makes no attempt to log the user off.
  32. ;        Logoff responsibility is delegated to the (M)BYE(+) program.
  33. ;        TIMEON checks to see if BYE is running and continues without
  34. ;        reporting time-on if not.  No installation required to use
  35. ;        this feature if you have clock code installed in your BYE.
  36. ;        All page-1 equates previously used by TIMEON were deleted.
  37. ;
  38. ;        This update also contains the SD99.FIX code for nested IF'
  39. ;
  40. ;                    - Wayne Masters, Potpourri
  41. ;======================================================================
  42. ;
  43. ; 07/11/85  Added THREBYT equate for systems needing a 3-byte sequence
  44. ;   v99     for reverse video.    If THREBYT is YES then the value coded
  45. ;        at TBYTE is added to the reverse video sequence (currently
  46. ;        set for a Kaypro).
  47. ;
  48. ;        Also added a new "?" option which will display a menu
  49. ;        of the $ options available if HELP is YES.
  50. ;
  51. ;                    - Steve Sanders
  52. ;======================================================================
  53. ;
  54. ; 03/15/85  Fixes obscure display bug which deletes display of 1, 2 or
  55. ;   v98     3 file names in 3 out of 4 cases when the directory has
  56. ;        >255 entries.  The fix code was written by Peter Lyman.
  57. ;        (See SD98.NOT).
  58. ;                    - Paul Foote                   ;
  59. ;=======================================================================
  60. ;
  61. ; 01/21/85  Added support for ZRDOS.  Although CP/M compatible, ZRDOS
  62. ;   v97     does not allow the SWAPEM technique of poking local values
  63. ;        into the operating system.    Instead, a test for ZRDOS is
  64. ;        made and, if present, further calls to CPM: set the Warm
  65. ;        Boot Trap in ZRDOS.  On any error detected by ZRDOS the
  66. ;        trap is reset and control is passed to DSKERR:  No equates
  67. ;        need be changed for CPM/ZRDOS, testing is dynamic in the
  68. ;        run-time code.
  69. ;                    - Joe Wright
  70. ;
  71. ;=======================================================================
  72. ;
  73. ; 12/28/84  Added CP/M Plus TIMEON logic controlled by tag CPM3.  Also
  74. ;        inserted a call to CKABRT in routine TYPE to catch an abort
  75. ;        request (^C) sooner.
  76. ;                    - George Peace
  77. ;
  78. ;=======================================================================
  79. ; Current versions of SD automatically adjust for any block size and di-
  80. ; rectory length under CP/M 1.4 or 2.x or MP/M (any version).  They also
  81. ; automatically adjust for any number of disk drives and work satisfac-
  82. ; torily even if no disk is in that drive at the moment.  Provisions are
  83. ; made for:
  84. ;
  85. ;    (1) automatic pauses when the screen fills up
  86. ;    (2) searching individual or multiple drives and/or user areas
  87. ;    (3) unconditional or optional resetting the disk system before
  88. ;        execution begins
  89. ;    (4) directing output to a disk file called SD.DIR and appending
  90. ;        to that file on subsequent runs
  91. ;    (5) summary line output giving drive and user information, num-
  92. ;        ber of files matched and how much space they consume, and
  93. ;        the amount of free space remaining on the disk
  94. ;    (6) displaying or suppressing "system" files
  95. ;    (7) accepting ambiguous filenames with or without a drive name
  96. ;    (8) printer output
  97. ;    (9) optional help menu with $?
  98. ;
  99. ;
  100. ; See SD.DOC for detailed instructions on configuring and running SD.ASM
  101. ;
  102. ;=======================================================================
  103. ;
  104. ; 11/27/84  Would not assemble with ASM or M80.  Now it will.  Replaced
  105. ;   v95     22 'PUSH A' and 'POP A' with conventional 'PUSH PSW' and
  106. ;        'POP PSW'.    Found four instances of labels being used more
  107. ;        than once with the same name.  MAC didn't mind but ASM and
  108. ;        M80 bombed.  Many nested conditionals changed to enable nor-
  109. ;        rmal assembly with ASM or M80 in addition to MAC.  Surprised
  110. ;        this has not been done some time ago.  Name slightly changed
  111. ;        as M80 doesn't seem to accept names with a dash (like SD-95).
  112. ;                    - Irv Hoff
  113. ;
  114. ; 11/24/84  Fixed a display bug, also removed a colon from a macro line.
  115. ;   v94                 - Steve Sanders
  116. ;
  117. ; 11/20/84  In previous versions of SD    "SD $L" gave a size of "0K" for
  118. ;   v93     any library member file which was exactly 255 records in
  119. ;        length.  This bug is fixed in SD-93, with code supplied by
  120. ;        Gene Head.            - Paul Foote
  121. ;
  122. ; 07/27/84  Some systems do not have contiguous disk drives.  The XEROX
  123. ;   v92     820 hard disk system for example assigns the only floppy
  124. ;        drive as A: and the hard disk as drives E:, F:, G: & H:
  125. ;        Code has been added to skip any drive whose maximum user
  126. ;        area in the  'Drive code/user area lookup table' is set
  127. ;        to a negative value.    -  Gene Head (N6NN/7)
  128. ;
  129. ; 07/25/84  Added routine to allow the command line or MAXCL option for
  130. ;   v91     names per line to function with VCODE.  (After several
  131. ;        threats from my friends.)  Also fixed a few small bugs in
  132. ;        the display format I found after releasing SD-90.  The
  133. ;        state of MAXCL now has no affect on the drive status lines.
  134. ;        They now follow the value of MNPL or MAXCL automatically.
  135. ;        Because of this, the status line appears as it did prior to
  136. ;        SD-90.  The NPL equate now sets the default number of names
  137. ;        per line if no command line option for columns is specified
  138. ;        unless MAXCL = YES.     - John Ray
  139. ;
  140. ;=======================================================================
  141. ;
  142. ;
  143. NO    EQU    0
  144. YES    EQU    NOT NO        ; M80 will not work with 0ffh
  145. ;
  146. CR    EQU    0DH
  147. LF    EQU    0AH
  148. ESC    EQU    1BH
  149. ;
  150. ;***********************************************************************
  151. ;
  152. ;     USER OPTION SPECIFICATIONS
  153. ;
  154. ;***********************************************************************
  155. ;
  156. HELP    EQU    YES        ; Yes, allow $? and display options menu
  157. DIRCON    EQU    NO        ; Yes for direct console output
  158. LOWCCP    EQU    NO        ; Yes only if you are running with byelow
  159. BDOSPG    EQU    0D4H        ; Set properly if lowccp is yes
  160. CPM3    EQU    NO        ; Set to yes if running cp/m 3 or above
  161. ;
  162. TIMEON    EQU    NO        ; If yes, SD will fetch TIMEON from BYE5, BYE3
  163.                 ; Or MBYE and display "Time on system is nnn
  164.                 ; Minutes". (or from BYE+nnn).    Logoff, if time
  165.                 ; Limit is exceeded, is left up to (M)BYE(+).
  166.                 ; If (M)BYE(+) is not running it just returns.
  167. ;
  168. ; ZCPR options
  169. ;
  170. ZCPR2    EQU    NO        ; Yes if nzcpr/zcpr2 (wheel byte enabled)
  171. MAXUR    EQU    NO        ; Yes if using maxusr in nzcpr/zcpr2
  172. MAXDR    EQU    NO        ; Yes if using maxdrv in nzcpr/zcpr2
  173. MAXCL    EQU    NO        ; Yes if storing mnpl value at maxc
  174. ;
  175. WHEEL    EQU    3EH        ; Set to wheel location if zcpr2 is yes
  176.                 ; Use 3eh if using nzcpr or zcmd
  177.                 ; Use 3bh if using unmodified zcprhdr file
  178. MAXU    EQU    3FH        ; Set to max user location if maxur is yes
  179. MAXD    EQU    3DH        ; Set to max drive location for maxdr=yes
  180. MAXC    EQU    3BH        ; Set to # of names per line location
  181. MXZUSR    EQU    15        ; Maximum user # allowed whlusr=yes/wheel set
  182. WHLUSR    EQU    YES        ; Yes to allow search 0-mxzusr if wheel set
  183. ;
  184. WHLA    EQU    NO        ; Yes to disallow a option if wheel zero
  185. WHLC    EQU    NO        ; Yes to disallow c option if wheel zero
  186. WHLCL    EQU    NO        ; Yes to disallow 4,6 or 8 options if wheel = 0
  187. WHLD    EQU    NO        ; Yes to disallow d option if wheel zero
  188. WHLF    EQU    NO        ; Yes to disallow f option if wheel zero
  189. WHLL    EQU    NO        ; Yes to disallow l option if wheel zero
  190. WHLP    EQU    NO        ; Yes to disallow p option if wheel zero
  191. WHLR    EQU    NO        ; Yes to disallow r option if wheel zero
  192. WHLS    EQU    NO        ; Yes to disallow s option if wheel zero
  193. WHLU    EQU    NO        ; Yes to disallow u option if wheel zero
  194. ;
  195. ;
  196. ; Command line options
  197. ;
  198. AOPT    EQU    YES        ; Yes to allow searching all user areas
  199. COPT    EQU    YES        ; Yes to allow clear screen
  200. CLOPT    EQU    YES        ; Yes allows a 40, 64 or 80 column display
  201. DOPT    EQU    YES        ; Yes to allow searching all drives on-line
  202. FOPT    EQU    YES        ; Yes to allow file output option
  203. LOPREV    EQU    NO        ; No to reverse the "L" option and not print
  204. LOPT    EQU    YES        ; Yes to allow library file member printing
  205. NOPT    EQU    YES        ; Yes to allow disabling page pause option
  206. PGPAWS    EQU    YES        ; Yes for pause after each page
  207. POPT    EQU    YES        ; Yes to allow printer option
  208. ROPT    EQU    YES        ; Yes to allow reset option
  209. SOPT    EQU    YES        ; Yes to allow system file option
  210. UOPT    EQU    YES        ; Yes to allow user number option
  211. VOPT    EQU    YES        ; Yes to allow version number display
  212. ;
  213. ;===========================================================================
  214. ; Console video equates
  215. ;
  216. REVIDEO    EQU    NO        ; Use reverse video sequences
  217.                 ; If no, the rest of the equates are disabled
  218. LEADIN    EQU    ESC        ; Escape lead-in (try a null if not required)
  219. INTOREV    EQU    'B'        ; Toggle background (enter your value here)
  220. OUTAREV    EQU    'C'        ; Toggle foreground (enter your value here)
  221. ;
  222. ; the following equate allows computers like the kaypro with a 3-byte
  223. ; video sequence to be specified.
  224. ;
  225. THREBYT    EQU    NO        ; Yes, a 3-byte video sequence is needed
  226. ;
  227.      IF    THREBYT
  228. TBYTE    EQU    '0'        ; Third byte if THREBYT is YES
  229.      ENDIF
  230. ;
  231. VECTOR    EQU    NO        ; Yes to display attributes on flashwriter ii
  232. VIDEO    EQU    0E009H        ; Entry to flashwriter video driver prom
  233. ;==========================================================================
  234. ;
  235. ; Hardware equates
  236. ;
  237.      IF    NOT (ZCPR2 AND MAXCL)
  238. NPL    EQU    4        ; # of names per line max values are:
  239.                 ; 2 for 40 x xx, 3 for 64 x 16, & 4 for 80 x 24
  240.      ENDIF
  241. ;
  242. LPS    EQU    24        ; # of lines per screen  max values are:
  243.                 ; ? for 40 x xx, 16 for 64 x 16, 24 for 80x24
  244. LPS1    EQU    16        ; # of lines per screen if names per line = 3
  245. LPS2    EQU    16        ; # of lines per screen if names per line < 3
  246. FENCEC    EQU    ':'        ; Use 00h for none
  247. ;
  248. ;
  249. ; Miscellaneous equates
  250. ;
  251. KTHREE    EQU    YES        ; Yes limits file size columns to 3 digits to
  252.                 ; Gain an additional print colomn.  allows
  253.                 ; Fence to be used with four files per line.
  254. PRDI    EQU    NO        ; Yes to print drive # on each line
  255. PRUS    EQU    NO        ; Yes to print user # on each line
  256. PRLIBD    EQU    NO        ; If yes and prus & prdi are yes then drive and
  257.                 ; User numbers will be displayed on library
  258.                 ; Listing lines
  259. PRBRDR    EQU    YES        ; Yes to print a quasi-border for library files
  260. DORST    EQU    YES        ; Yes to always reset disks when d option active
  261. DUOPT    EQU    YES        ; Yes, allow drive/user spec zcpr2 style
  262. NODISK    EQU    YES        ; Yes if you do not want to specify disk drive
  263.                 ; When asking for options and using default drv
  264. REPERR    EQU    YES        ; Yes to report command line option errors
  265. REPUSR    EQU    YES        ; Yes to report user numbers
  266. VCODE    EQU    YES        ; Yes if files are to be alphabetized vertically
  267. ;
  268. ;
  269.      IF    (MAXUR OR MAXDR    OR MAXCL) AND NOT ZCPR2
  270.     ++++    MAXUR, MAXDR, MAXCL CANNOT BE YES UNLESS ZCPR2 IS YES
  271.      ENDIF
  272. ;
  273. ;
  274. ; BDOS equates
  275. ;
  276. RDCHR    EQU    1        ; Read char from console
  277. WRCHR    EQU    2        ; Write char to console
  278. PRINTS    EQU    9        ; Print string
  279. CONST    EQU    11        ; Check cons stat
  280. CPMVER    EQU    12        ; Return cp/m version
  281. RESET    EQU    13        ; Reset disk system
  282. SELDSK    EQU    14        ; Select disk
  283. OPEN    EQU    15        ; 0ffh=not found
  284. CLOSE    EQU    16        ; " "
  285. SEARCH    EQU    17        ; " "
  286. NEXT    EQU    18        ; " "
  287. READ    EQU    20        ; Not 0 = eof
  288. WRITE    EQU    21        ; Not 0 = disk full
  289. MAKE    EQU    22        ; 0ffh = directory full
  290. CURDSK    EQU    25        ; Get currently logged disk name
  291. SETDMA    EQU    26        ; Set current dma
  292. GALLOC    EQU    27        ; Get address of allocation vector
  293. CURDPB    EQU    31        ; Get current disk parameters
  294. CURUSR    EQU    32        ; Get currently logged user number (2.x only)
  295. ;
  296. ZRDVER    EQU    48        ; Return ZRDOS version
  297. SETWBT    EQU    50        ; Set warm boot trap (ZRDOS)
  298. RESWBT    EQU    52        ; Reset warm boot trap (ZRDOS)
  299. ;
  300. BASE    EQU    0        ; Default to 0 (or 100h with mac +r option)
  301. TPA    EQU    100H
  302. FCB    EQU    BASE+5CH
  303. BDOS    EQU    BASE+5
  304. ;
  305. ;
  306.     ORG    TPA
  307. ;
  308. ;
  309. ;***********************************************************************
  310. ;
  311. ;  BEGIN EXECUTABLE PROGRAM CODE *
  312. ;
  313. ;***********************************************************************
  314. ;
  315. ;
  316.     JMP    START
  317. ;
  318. ;
  319. MLEADIN:DB    LEADIN        ; Leadin char for highlight sequences
  320. MINTOREV: DB    INTOREV        ; Code to enter highlight mode
  321. MOUTAREV: DB    OUTAREV        ; Code to return to normal mode
  322. ;
  323.      IF    NOT MAXCL
  324. MNPL:    DB    NPL        ; Names per line (# of columns)
  325. MLPS:    DB    LPS        ; Lines per screen (between pauses)
  326.      ENDIF            ; Not maxcl
  327. ;
  328.      IF    MAXCL
  329. MNPL:    DB    0
  330. MLPS:    DB    0
  331.      ENDIF            ; Maxcl
  332. ;
  333. FENC:    DB    FENCEC        ; Fence character
  334. ;
  335.      IF    COPT
  336.     DB    'CL SCR CODE->'    ; For easy patching via du/ddt
  337. CLCHR:    DB    1AH        ; Enter your clear screen code(s) here
  338.     DB    '$'        ; End with a '$'
  339.     DB    0,0,0,0,0,0    ; Allow further space for custom version
  340.      ENDIF            ; Copt
  341. ;
  342. ;
  343. VERNAME:DB    CR,LF,'SD',MAIN+'0'
  344.     DB    VER/10+'0',VER MOD 10+'0',' - '
  345.     DB    MONTH/10+'0',MONTH MOD 10+'0','/'
  346.     DB    DAY/10+'0',DAY MOD 10+'0','/'
  347.     DB    YEAR/10+'0',YEAR MOD 10+'0'
  348.     DB    0
  349. ;
  350. ;
  351. ; Drive code/user area lookup table
  352. ;
  353. ; Note that the LODRV-HIDRV table is included here fully configured.
  354. ; For your own use, you should change the maximum user areas as appro-
  355. ; priate for each drive on your system.  Note that there are only 32
  356. ; user areas available under CP/M 2, so the highest legal user area you
  357. ; can specify is 31 (range 0-31 = 32 areas).  The program will convert
  358. ; anything over 31 into mod 31.  The default table below is set for the
  359. ; usual 16 user areas rather than the full 32 available.
  360. ;
  361.     DB    'MAXUSR TBL>'    ; Label to make finding the table easier
  362. ;
  363. LODRV    EQU    $        ; Mark beginning of drive/user table
  364. ;
  365.     DB    15        ; Maximum user area for drive a
  366.     DB    15        ; "    "    "      "    "   b
  367.     DB    15        ; "    "    "      "    "   c
  368.     DB    15        ; "    "    "      "    "   d
  369.     DB    15        ; "    "    "      "    "   e
  370.     DB    15        ; "    "    "      "    "   f
  371.     DB    15        ; "    "    "      "    "   g
  372.     DB    15        ; "    "    "      "    "   h
  373.     DB    15        ; "    "    "      "    "   i
  374.     DB    15        ; "    "    "      "    "   j
  375.     DB    15        ; "    "    "      "    "   k
  376.     DB    15        ; "    "    "      "    "   l
  377.     DB    15        ; "    "    "      "    "   m
  378.     DB    15        ; "    "    "      "    "   n
  379.     DB    15        ; "    "    "      "    "   o
  380.     DB    15        ; "    "    "      "    "   p
  381. ;
  382. HIDRV    EQU    $        ; Mark end of drive/user table
  383. ;
  384. START:    LXI    H,0
  385.     DAD    SP        ; Hl=old stack
  386.     SHLD    STACK        ; Save it
  387.     LXI    SP,STACK    ; Get new stack
  388. ;
  389. ;
  390. ; Initialize reverse video code in message area
  391. ;
  392.      IF    REVIDEO
  393.     LHLD    MLEADIN
  394.     SHLD    REVMS1
  395.     SHLD    REVMS2
  396.     SHLD    REVMS3
  397.     LDA    MOUTAREV
  398.     STA    REVMS3+1
  399.      ENDIF            ; Revideo
  400. ;
  401. ;
  402. ; Zero out the entire initialization data area
  403. ;
  404.     LXI    H,DATA0        ; Point to beginning of init. data area
  405.     PUSH    H        ; Save for non-zero filling later
  406.     MVI    C,DATA1-DATA0    ; Get length of data area
  407.     XRA    A        ; Zero accumulator
  408. ;
  409. ZFILL:    MOV    M,A
  410.     INX    H
  411.     DCR    C
  412.     JNZ    ZFILL
  413. ;
  414. ;
  415. ; Now copy non-zero initialization data from the template area
  416. ;
  417.     POP    H        ; Reset hl to data0
  418.     LXI    D,TMPLT0    ; Set de to beginning of template
  419.     MVI    C,TMPLT1-TMPLT0    ; Get length of template area
  420. ;
  421. NZFILL:    LDAX    D        ; Get template byte
  422.     MOV    M,A        ; Move to data area
  423.     INX    D
  424.     INX    H
  425.     DCR    C
  426.     JNZ    NZFILL
  427.  
  428.     MVI    C,ZRDVER    ; Get zrdos version
  429.     CALL    BDOS
  430.     MOV    A,L
  431.     STA    ZRDFLG        ; Save it
  432.  
  433.     MVI    C,CPMVER    ; Get and save the cp/m version #
  434.     CALL    BDOS
  435.     MOV    A,L
  436.     STA    VERFLG
  437.     CPI    20H        ; Set carry if cp/m 1.4
  438.     MVI    E,0FFH        ; Get current user number if using cp/m 2
  439.     MVI    C,CURUSR    ; Fall through with a=0 if not
  440.     CNC    CPM
  441.     STA    OLDUSR        ; Initialize startup user number
  442.     STA    NEWUSR        ; And make new user match it
  443. ;
  444.      IF    DOPT        ; Save extra copy for multi-disk
  445.     STA    BASUSR        ; Directories
  446.      ENDIF            ; Dopt
  447. ;
  448.      IF    TIMEON
  449.     CALL    TIME
  450.      ENDIF            ; Timeon
  451. ;
  452.      IF    DUOPT        ; Drive/user option?
  453.     LXI    H,81H        ; Point to command line
  454.     MOV    A,M
  455.     INX    H
  456.     ORA    A
  457.     JNZ    CLOK
  458.     MOV    M,A
  459. ;
  460. CLOK:    LXI    D,FCB
  461.     CALL    FNAME
  462.     MOV    A,B
  463.     CPI    0FFH
  464.     JZ    CLUS
  465.     STAX    D
  466. ;
  467. CLUS:    MOV    A,C
  468.     CPI    0FFH
  469.     JZ    CLNON
  470.     STA    NEWUSR
  471.      ENDIF            ; Duopt
  472. ;
  473.      IF    DOPT AND DUOPT
  474.     STA    BASUSR
  475.      ENDIF            ; Dopt and duopt
  476. ;
  477. CLNON:    MVI    C,CURDSK
  478.     CALL    CPM        ; Get current disk nr
  479.     STA    OLDDSK        ; Save for reset if needed
  480. ;
  481.      IF    FOPT
  482.     INR    A
  483.     STA    OUTFCB        ; Set directory output file drive
  484.      ENDIF            ; Fopt
  485. ;
  486.     LXI    H,FCB
  487.     MOV    A,M        ; Get drive name for directory search
  488.     ORA    A        ; Any specified?
  489.     JNZ    STRT1A        ; Yes skip next routine
  490.     LDA    OLDDSK        ; Otherwise, get default disk
  491.     INR    A
  492.     JMP    START2
  493. ;
  494. STRT1A:    PUSH    PSW
  495.     MVI    A,1
  496.     STA    DFLAG
  497.     POP    PSW
  498. ;
  499. START2:    MOV    M,A        ; Put the absolute drive code in
  500.                 ; Directory fcb
  501. ;
  502. ;
  503. ; If at least one option is allowed, scan the command line for the
  504. ; option field delimiter.  The option field delimiter is considered
  505. ; valid only if it is preceded by at least 1 space (otherwise, it
  506. ; may be part of the directory filename).  Any unrecognized options
  507. ; or illegal user numbers will be flagged or ignored (see REPERR).
  508. ; (We scan the command line buffer rather than the 2nd default FCB
  509. ; because all 8 options plus a 2 digit user number won't fit in
  510. ; the FCB name field).
  511. ;
  512.     LXI    H,80H        ; Set command line buffer pointer
  513.     MOV    B,M        ; Get length of command line buffer
  514. ;
  515. ;
  516. ; Search for valid command line delimiter.  If not found, assume no op-
  517. ; tions.
  518. ;
  519. SCNDOL:    INX    H
  520.     DCR    B
  521.     JM    CKREST        ; Exit if command line buffer empty
  522.     MOV    A,M
  523.     CPI    '$'
  524.     JNZ    SCNDOL
  525.     DCX    H        ; '$' found - make sure a space precedes
  526.     MOV    A,M
  527.     INX    H
  528.     CPI    ' '
  529.     JNZ    SCNDOL        ; No space - ignore "$" and search again
  530. ;
  531. ;
  532. ; Valid delimiter found.  Scan the rest of the buffer for options.
  533. ; Errors past this point will cause an abort if the command line error
  534. ; option is enabled.  Otherwise, the dud option will be ignored and SD
  535. ; will attempt to continue stumbling through the rest of the field.
  536. ;
  537.     XCHG            ; Get option field pointer to de
  538. ;
  539. SCNOPT:    INX    D        ; Bump to next option field character
  540.     DCR    B        ; Dock characters left in option field
  541.     JM    CKREST        ; If option field exhausted, exit
  542. ;
  543. SCNAGN:    LDAX    D        ; Get the next option character
  544.     CPI    ' '        ; Do we have a space?
  545.     JZ    SCNOPT        ; Ignore it if so
  546. ;
  547.      IF    HELP
  548.     CPI    '?'        ; User wants help menu
  549.     JZ    HELPME        ; Show option menu and exit
  550.      ENDIF            ; Help
  551. ;
  552.      IF    ZCPR2 AND WHLU
  553.     CPI    'U'        ; Disallowing "U" option, treat
  554.     JZ    CLERR        ; As error if there..
  555.      ENDIF            ; Zcpr2 and whlu
  556. ;
  557.     LXI    H,OTBL-1    ; Get base of option lookup table
  558.     MVI    C,OEND-OTBL+1    ; Get length of option lookup table
  559. ;
  560. NOMACH:    INX    H        ; Bump to next option table character
  561.     DCR    C        ; Are we out of the table?
  562.     JZ    CK4USR        ; If so, check for user option
  563. ;
  564.      IF    ZCPR2        ; Nzcpr/zcpr2? (wheel byte?)
  565.     PUSH    PSW        ; Save accum.
  566.     LDA    WHEEL        ; Get wheel byte
  567.     ORA    A        ; Check it
  568.     JZ    NOMAC1        ; It's zero, so forget it
  569.     MOV    A,M        ; Get the table option
  570.     CPI    '4'        ; If 4 then skip lc con
  571.     JZ    UCBP
  572.     CPI    '6'        ; If 6 then skip lc con
  573.     JZ    UCBP
  574.     CPI    '8'        ; If 8 then skip lc con
  575.     JZ    UCBP
  576.     ANI    0DFH        ; Make sure is upper case
  577. ;
  578. UCBP:    MOV    M,A        ; Stuff back in table
  579. ;
  580. NOMAC1:    POP    PSW        ; Restore accum.
  581.      ENDIF            ; Zcpr2
  582. ;
  583.     CMP    M        ; Compare our character with option table
  584.     JNZ    NOMACH        ; Exit if no match
  585.     MVI    M,0        ; Otherwise, activate the flag
  586.     CPI    'D'        ; All disk search?
  587.     CZ    NOMAC2        ; Yes, start at a always
  588.     CPI    'A'        ; All user search?
  589.     CZ    NOMAC4        ; Yes, start at user no. 0 always
  590.     JMP    SCNOPT        ; And go get the next option character
  591. ;
  592. NOMAC2:    PUSH    PSW
  593.     PUSH    H
  594.     LDA    DFLAG
  595.     ORA    A
  596.     JNZ    NOMAC3
  597.     LXI    H,FCB        ; Set fcb drive byte to drive a
  598.     MVI    A,1
  599.     MOV    M,A
  600.     POP    H
  601.     POP    PSW
  602.     RET
  603. ;...
  604. ;
  605. ;
  606. NOMAC3:    POP    H
  607.     POP    PSW
  608.     RET
  609. ;...
  610. ;
  611. ;
  612. NOMAC4:    LDA    AFLAG        ; Asking for $u3a or $u4a, etc.?
  613.     ORA    A
  614.     RNZ
  615.     MVI    A,0        ; Always start at user #0
  616.     STA    NEWUSR
  617.     STA    BASUSR
  618.     RET
  619. ;.....
  620. ;
  621. ;
  622. ; If option character doesn't match the table, see if we have a User
  623. ; option.
  624. ;
  625. CK4USR:     IF    UOPT        ; Check for user number option
  626.     CPI    'U'
  627.     JNZ    CLERR        ; Last option, so bad deal if not it
  628. ;
  629. UAGN:    INX    D        ; Bump to user number digit
  630.     DCR    B
  631.     JM    CLERR        ; Error if nothing left
  632.     LDAX    D        ; Get decimal digit
  633.     CPI    ' '        ; Ignore leading spaces
  634.     JZ    UAGN
  635.     SUI    30H        ; Subtract ascii bias
  636.     JC    CLERR        ; Error if < 0
  637.     CPI    10
  638.     JNC    CLERR        ; Error if > 9
  639.     STA    NEWUSR        ; Save user number, might be only 1 digit
  640.      ENDIF            ; Uopt
  641. ;
  642.      IF    DOPT AND UOPT
  643.     STA    BASUSR        ; Duplicate it if multi-disk mode
  644.      ENDIF            ; Dopt and uopt
  645. ;
  646.      IF    UOPT
  647.     MVI    A,1
  648.     STA    AFLAG        ; To allow $u3a, etc.
  649.     INX    D        ; Bump to possible 2nd digit of user #
  650.     DCR    B
  651.     JM    CKREST        ; No more buffer, exit with user #
  652.     LDAX    D        ; Else, check for another digit
  653.     SUI    30H
  654.     JC    SCNAGN        ; If next char not numeric, it is not
  655.     CPI    10        ; Part of user number so go check for
  656.     JNC    SCNAGN        ; Another option
  657.     MOV    L,A        ; Save units digit
  658.     LDA    NEWUSR        ; Get tens digit
  659.     ADD    A        ; Multiply by 10
  660.     MOV    H,A
  661.     ADD    A
  662.     ADD    A
  663.     ADD    H
  664.     ADD    L        ; Combine with units digit
  665.     STA    NEWUSR        ; Save the total user number
  666.      ENDIF            ; Uopt
  667. ;
  668.      IF    DOPT AND UOPT
  669.     STA    BASUSR        ; Duplicate it if multi-disk mode
  670.      ENDIF            ; Dopt and uopt
  671. ;
  672.      IF    UOPT
  673.     JMP    SCNOPT        ; Continue scanning
  674.      ENDIF            ; Uopt
  675. ;
  676. ;
  677. ; If command line error option enabled, playback the command line up
  678. ; to the character that we gagged on and exit.    If REPERR is not enabled
  679. ; then continue as if nothing were amiss to avoid acknowledging that
  680. ; some options are available.
  681. ;
  682. CLERR:     IF    REPERR
  683.     XRA    A
  684.     INX    D        ; Tag end of command line with terminator
  685.     STAX    D
  686.     CALL    CRLF
  687.     LXI    D,ERRMS2
  688.     CALL    PRINT
  689.     LXI    D,ERRTAG
  690.     CALL    PRINT
  691.     LXI    H,81H        ; Playback bad cmd line to error point
  692. ;
  693. CLELP:    MOV    A,M
  694.     ORA    A
  695.     JZ    CLEX
  696.     CALL    TYPE
  697.     INX    H
  698.     JMP    CLELP
  699. ;
  700. CLEX:    MVI    A,'?'        ; Tag line with a '?' field
  701.     CALL    TYPE
  702.     CALL    CRLF        ; Space down 1 more line
  703.     JMP    EXIT        ; And return to cp/m
  704.      ENDIF            ; Reperr
  705. ;
  706.      IF    (NOT REPERR)
  707.     JMP    SCNOPT        ; If not reporting errors, ignore the dud
  708.      ENDIF            ; (not reperr)
  709. ;
  710. ;
  711. ; Options input or not specified.  If reset option specified, reset
  712. ; the disk system now.    Its important that the reset be done OUTSIDE
  713. ; the multiple drive loop if the file output option is enabled because
  714. ; CP/M 1.4 clobbers the DMA buffer on reset.
  715. ;
  716. CKREST:     IF    COPT
  717.     LDA    COPFLG
  718.     ORA    A
  719.     JNZ    CLOPN
  720.     LDA    CLCHR
  721.     CPI    0C3H        ; Op-code for jmp
  722.     JZ    CLCAL
  723.     LXI    D,CLCHR        ; Get it from down under
  724.     MVI    C,PRINTS    ; Print just to console
  725.     CALL    BDOS
  726.     JMP    CLOPN
  727. ;
  728. CLCAL:    LHLD    CLCHR+1
  729.     SHLD    CLCALL+1
  730. ;
  731. CLCALL:    CALL    0        ; To be safe
  732.      ENDIF            ; Copt
  733. ;
  734. ;Check for command line option for 40,64, or 80 column & store value
  735. ;
  736. CLOPN:     IF    CLOPT        ; If clopr inabled then
  737.     LDA    CL4FLG        ; Load a with 40 col flag
  738.     ORA    A        ; Test it
  739.     JNZ    CLOPN1        ; No then skip to 64 col test
  740.     PUSH    PSW        ; If so the save a
  741.     MVI    A,2        ; 2 names per line for 40 column
  742.      ENDIF            ; Clopt
  743. ;
  744.      IF    MAXCL AND CLOPT    ; If storing value in external location
  745.     STA    MAXC        ; Do it
  746.      ENDIF            ; Maxcl and clopt
  747. ;
  748.      IF    NOT MAXCL AND CLOPT ; If storing value internal to sd
  749.     STA    MNPL        ; Do it
  750.      ENDIF            ; Not maxcl and clopt
  751. ;
  752.      IF    CLOPT
  753.     MVI    A,LPS2        ;
  754.     STA    MLPS        ;
  755.     POP    PSW        ; Get it back a
  756. ;
  757. CLOPN1:    LDA    CL6FLG        ; Load a with 64 col flag
  758.     ORA    A        ; Test it
  759.     JNZ    CLOPN2        ; No then skip to 80 col test
  760.     PUSH    PSW        ; If so then save a
  761.     MVI    A,3        ; 3 names per line for 64 column
  762.      ENDIF            ; Clopt
  763. ;
  764.      IF    MAXCL AND CLOPT    ; If storing value in external location
  765.     STA    MAXC        ; Do it
  766.      ENDIF            ; Maxcl and clopt
  767. ;
  768.      IF    NOT MAXCL AND CLOPT ; If storing value internal to sd
  769.     STA    MNPL        ; Do it
  770.      ENDIF            ; Not maxcl and clopt
  771. ;
  772.      IF    CLOPT
  773.     MVI    A,LPS1        ;
  774.     STA    MLPS        ;
  775.     POP    PSW        ; Get back where you belong
  776. ;
  777. CLOPN2:    LDA    CL8FLG        ; Load a with 80 col flag
  778.     ORA    A        ; Test it
  779.     JNZ    ROPTN        ; No then exit to test for r option
  780.     PUSH    PSW        ; If so then save a
  781.     MVI    A,4        ; 4 names per line for 80 column
  782.      ENDIF            ; Clopt
  783. ;
  784.      IF    MAXCL AND CLOPT    ; If storing value in external location
  785.     STA    MAXC        ; Do it
  786.      ENDIF            ; Maxcl and clopt
  787. ;
  788.      IF    NOT MAXCL AND CLOPT ; If storing value internal to sd
  789.     STA    MNPL        ; Do it
  790.      ENDIF            ; Not maxcl and clopt
  791. ;
  792.      IF    CLOPT
  793.     MVI    A,LPS
  794.     STA    MLPS
  795.     POP    PSW        ; Get it back
  796.      ENDIF            ; Clopt
  797. ;
  798. ROPTN:     IF    ROPT
  799.     LDA    ROPFLG        ; If reset flag set, reset disk system
  800.     ORA    A        ; Before starting to update allocation
  801.     MVI    C,RESET        ; Vetors
  802.     CZ    CPM
  803.      ENDIF            ; Ropt
  804. ;
  805.      IF    DOPT
  806.     LDA    DOPFLG        ; If multi-disk flag set,
  807.     ORA    A        ; Need to set error traps
  808.     CZ    SWAPEM        ; Swap bdos error vector tables
  809.      ENDIF            ; Dopt
  810. ;
  811.      IF    DORST AND DOPT
  812.     LDA    DOPFLG
  813.     ORA    A
  814.     CZ    DSET        ; Reset disk system if $d only
  815.      ENDIF            ; Dorst and dopt
  816. ;
  817. ;
  818. ; Set MNPL and MLPS values if MAXCL
  819. ;
  820.      IF    MAXCL
  821.     LDA    MAXC        ; Load a reg with value @ maxc
  822.     STA    MNPL        ; Punch a into mnpl
  823. ;
  824.     MVI    A,LPS        ; Load a reg with lps
  825.     STA    MLPS        ; Assume 4 names across
  826.     LDA    MAXC        ; Get val @ maxc
  827.     CPI    3        ; 3 columns across?
  828.     JNZ    LPCL1        ; If not then jmp to lpcl1
  829.     MVI    A,LPS1        ; Load a reg with mnpl for col = 3
  830.     STA    MLPS        ; Punch it into mpls
  831. ;
  832. LPCL1:    LDA    MAXC        ; Get maxc val again
  833.     CPI    2        ; 2 columns across?
  834.     JZ    LPCL2        ; If so then jmp to lpcl2 and set mnpl
  835.     CPI    1        ; Not 2 across, how about 1?
  836.     JNZ    LPSE        ; If not then jmp to exit
  837. ;
  838. LPCL2:    MVI    A,LPS2        ; It was 1 or 2 so set mnpl with lps2
  839.     STA    MLPS
  840. ;
  841. LPSE:     ENDIF            ; Maxcl
  842. ;
  843. ;
  844. ; Validate drive code and user area numbers from the drive table.
  845. ;
  846. NOOPT:    LXI    D,DRUMSG    ; Get the drive/user error message
  847.     PUSH    D
  848.     LDA    FCB        ; Get directory drive code
  849.     DCR    A        ; Normalize to range of 0-31
  850.     CPI    HIDRV-LODRV    ; Compare with maximum drives on-line
  851.     JNC    ERXIT        ; Take drive error exit if out of range
  852. ;
  853.      IF    MAXDR        ; Look for maxd
  854.     LXI    H,MAXD        ; Adddress to hl
  855.     MOV    L,M        ; Maxd to l
  856.     INX    H        ; Add one
  857.     CMP    L        ; Check it
  858.     JNC    ERXIT        ; Oops if not bigger
  859.      ENDIF            ; Maxdr
  860. ;
  861.     MOV    E,A        ; Use drive code as index into table
  862.     MVI    D,0
  863. ;
  864.      IF    ZCPR2 AND WHLUSR
  865.     LDA    WHEEL        ; Get wheel byte
  866.     ORA    A        ; Check it
  867.     JZ    USRCK        ; If reset, restrict user
  868.     MVI    A,MXZUSR    ; If set, max user = mxzusr
  869.     JMP    USRCK2
  870.      ENDIF            ; Zcpr2 and whlusr
  871. ;
  872. USRCK:    LXI    H,LODRV        ; Point to base of drive/user table
  873.     DAD    D
  874.     MOV    A,M        ; Get the maximum user # for this drive
  875. ;
  876.      IF    MAXUR        ; Use lomem values if smaller
  877.     MOV    H,A        ; Current value of maxusr
  878.     LDA    MAXU        ; Alternate value
  879.     SBI    1        ; Maxusr was really max user + 1
  880.     CMP    H        ; Compare the two
  881.     JNC    USRCK2        ; Jmp if table value smaller or equal
  882.     STA    MAXUSR        ; Else replace it
  883.      ENDIF            ; Maxur
  884. ;
  885. USRCK2:    MOV    B,A        ; Save the maxuser for later testing (9.2)
  886.     ANI    1FH        ; Make sure its in range 0 - 31
  887.     STA    MAXUSR        ; Save it for later
  888.     LXI    H,NEWUSR    ; Point to the directory user area
  889.     CMP    M        ; Compare it with the maximum
  890.     JC    ERXIT        ; Take error exit if user number illegal
  891.     POP    D        ; Destroy error message pointer
  892.  
  893.     MOV    A,B        ; Check to see if this drive (9.2)
  894.     ORA    A        ; Has been mapped out (9.2)
  895.     JM    NDSK        ; If so then skip this drive (9.2)
  896.  
  897.     LXI    H,FCB+1        ; Point to name
  898.     MOV    A,M        ; Any specified?
  899. ;
  900.      IF    NODISK
  901.     CPI    '$'
  902.     JZ    WCD
  903.      ENDIF            ; Nodisk
  904. ;
  905.     CPI    ' '
  906.     JNZ    GOTFCB
  907. ;
  908. ;
  909. ; No FCB - make FCB all '?'
  910. ;
  911. WCD:    MVI    B,11        ; Fn+ft count
  912. ;
  913. QLOOP:    MVI    M,'?'        ; Store '?' in fcb
  914.     INX    H
  915.     DCR    B
  916.     JNZ    QLOOP
  917. ;
  918. GOTFCB:    MVI    A,'?'        ; Force wild extent
  919.     STA    FCB+12
  920.     CALL    SETSRC        ; Set dma for bdos media change check
  921.     LXI    H,FCB        ; Point to fcb drive code for directory
  922.     MOV    E,M        ; Get the drive code out of the fcb
  923.     DCR    E        ; Normalize drive code for select
  924.     MVI    C,SELDSK    ; Select the directory drive to retrieve
  925.     CALL    CPM        ; The proper allocation vector
  926.     CALL    CKVER        ; Check version
  927.     JC    V14        ; Pre-2.x...get params the 1.4 way
  928.     MVI    C,CURDPB    ; It is 2.x or mp/m...request dpb
  929.     CALL    BDOS
  930.     INX    H
  931.     INX    H
  932.     MOV    A,M        ; Get block shift
  933.     STA    BLKSHF
  934.     INX    H        ; Bump to block mask
  935.     MOV    A,M
  936.     STA    BLKMSK        ; Get it
  937.     INX    H
  938.     INX    H
  939.     MOV    E,M        ; Get max block #
  940.     INX    H
  941.     MOV    D,M
  942.     XCHG
  943.     SHLD    BLKMAX        ; Save it
  944.     XCHG
  945.     INX    H
  946.     MOV    E,M        ; Get directory size
  947.     INX    H
  948.     MOV    D,M
  949.     XCHG
  950.     JMP    FREE        ; Let free save it and setup order table
  951. ;
  952. V14:    LHLD    BDOS+1        ; Get params 1.4 style
  953.     MVI    L,3BH        ; Point to directory size
  954.     MOV    E,M        ; Get it
  955.     MVI    D,0        ; Force high order to 0
  956.     PUSH    D        ; Save for later
  957.     INX    H        ; Point to block shift
  958.     MOV    A,M        ; Fetch
  959.     STA    BLKSHF        ; Save
  960.     INX    H        ; Point to block mask
  961.     MOV    A,M        ; Fetch it
  962.     STA    BLKMSK        ; And save it
  963.     INX    H
  964.     MOV    E,M        ; Get max. block no.
  965.     MVI    D,0
  966.     XCHG
  967.     SHLD    BLKMAX        ; Save it
  968.     POP    H        ; Restore directory size
  969.     JMP    FREE20        ; Go figure free space from alloc vector
  970. ;
  971. ;
  972. ; Calculate # of K free on selected drive now so that the FREE figure
  973. ; will not reflect either the creation or additions to the SD.DIR file
  974. ; (which we would probably erase or move anyway).
  975. ;
  976. FREE:    SHLD    DIRMAX        ; Save max # of entries in directory
  977.     LDA    VERFLG        ; Check version #
  978.     CPI    30H        ; 3.0?
  979.     JC    FREE20        ; Use old method if not
  980.     LDA    FCB        ; Get drive #
  981.     DCR    A
  982.     MOV    E,A        ; Use new compute free space bdos call
  983.     MVI    C,46
  984.     CALL    CPM
  985.     MVI    C,3        ; Answer is a 24-bit integer
  986. ;
  987. FRE3L1:    LXI    H,BASE+82H    ; Answer is in 1st 3 bytes of dma adr
  988.     MVI    B,3        ; Convert it from sectors to k
  989.     ORA    A        ; By dividing by 8
  990. ;
  991. FRE3L2:    MOV    A,M
  992.     RAR
  993.     MOV    M,A
  994.     DCX    H
  995.     DCR    B
  996.     JNZ    FRE3L2        ; Loop for 3 bytes
  997.     DCR    C
  998.     JNZ    FRE3L1        ; Shift 3 times
  999.     LHLD    BASE+80H    ; Now get result in k
  1000.     JMP    SAVFRE        ; Go store it
  1001. ;
  1002. FREE20:    MVI    C,GALLOC    ; Get address of allocation vector
  1003.     CALL    BDOS
  1004.     XCHG
  1005.     LHLD    BLKMAX        ; Get its length
  1006.     INX    H
  1007.     LXI    B,0        ; Init block count to 0
  1008. ;
  1009. GSPBYT:    PUSH    D        ; Save alloc address
  1010.     LDAX    D
  1011.     MVI    E,8        ; Set to process 8 blocks
  1012. ;
  1013. GSPLUP:    RAL            ; Test bit
  1014.     JC    NOTFRE
  1015.     INX    B
  1016. ;
  1017. NOTFRE:    MOV    D,A        ; Save bits
  1018.     DCX    H        ; Count down blocks
  1019.     MOV    A,L
  1020.     ORA    H
  1021.     JZ    ENDALC        ; Quit if out of blocks
  1022.     MOV    A,D        ; Restore bits
  1023.     DCR    E        ; Count down 8 bits
  1024.     JNZ    GSPLUP        ; Do another bit
  1025.     POP    D        ; Bump to next byte..
  1026.     INX    D        ; Of alloc. vector
  1027.     JMP    GSPBYT        ; Process it
  1028. ;
  1029. ENDALC:    POP    D        ; Clear allocation vector pntr from stack
  1030.     MOV    L,C        ; Copy blocks to hl
  1031.     MOV    H,B
  1032.     LDA    BLKSHF        ; Get block shift factor
  1033.     SUI    3        ; Convert from sectors to k
  1034.     JZ    SAVFRE        ; Skip shifts if 1k blocks ret free in hl
  1035. ;
  1036. FREKLP:    DAD    H        ; Multiply blocks by k/blk
  1037.     DCR    A
  1038.     JNZ    FREKLP
  1039. ;
  1040. SAVFRE:    SHLD    FREEBY        ; Save the free space for output later
  1041. ;
  1042. ;
  1043. ; Reenter here on subsequent passes while in the all-users mode
  1044. ;
  1045. SETTBL:    LHLD    DIRMAX        ; Get directory maximum again
  1046.     INX    H        ; Directory size is dirmax+1
  1047.     DAD    H        ; Double directory size
  1048.     LXI    D,ORDER        ; To get size of order table
  1049.     DAD    D        ; Allocate order table
  1050.     SHLD    TBLOC        ; Name tbl begins where order tbl ends
  1051.     SHLD    NEXTT
  1052.     XCHG
  1053.     LHLD    BDOS+1        ; Make sure we have room to continue
  1054.     MOV    A,E
  1055.     SUB    L
  1056.     MOV    A,D
  1057.     SBB    H
  1058.     JNC    OUTMEM
  1059. ;
  1060.      IF    UOPT
  1061.     CALL    CKVER        ; Set carry if pre-cp/m 2
  1062.     LDA    NEWUSR        ; Get user area for directory
  1063.     MOV    E,A
  1064.     MVI    C,CURUSR    ; Get the user function
  1065.     CNC    CPM        ; And set new user number if cp/m 2
  1066.      ENDIF            ; Uopt
  1067. ;
  1068. ;
  1069. ; Look up the FCB in the directory
  1070. ;
  1071.     MVI    A,'?'
  1072.     LXI    H,FCB+12
  1073.     MOV    M,A        ; Match all extents
  1074.     INX    H
  1075.     MOV    M,A        ; Match all s1 bytes
  1076.     INX    H
  1077.     MOV    M,A        ; Match all s2 bytes
  1078.     LXI    H,0
  1079.     SHLD    COUNT        ; Initialize match counter
  1080.     SHLD    TOTFIL        ; "    total file counter
  1081.     SHLD    TOTSIZ        ; "    total size counter
  1082.     CALL    SETSRC        ; Set dma for directory search
  1083.     MVI    C,SEARCH    ; Get 'search first' function
  1084.     JMP    LOOK        ; And go search for 1st match
  1085. ;
  1086. ;
  1087. ; Read more directory entries
  1088. ;
  1089. MORDIR:    MVI    C,NEXT        ; Search next
  1090. ;
  1091. LOOK:    LXI    D,FCB
  1092.     CALL    CPM        ; Read directory entry
  1093.     INR    A        ; Check for end (0ffh)
  1094.     JZ    SPRINT        ; If no more, sort & print what we have
  1095. ;
  1096. ;
  1097. ; Point to directory entry
  1098. ;
  1099. SOME:    DCR    A        ; Undo prev 'inr a'
  1100.     ANI    3        ; Make modulus 4
  1101.     ADD    A        ; Multiply
  1102.     ADD    A        ; By 32 because
  1103.     ADD    A        ; Each directory
  1104.     ADD    A        ; Entry is 32
  1105.     ADD    A        ; Bytes long
  1106.     LXI    H,BASE+81H    ; Point to buffer (skip to fn/ft)
  1107.     ADD    L        ; Point to entry
  1108.     ADI    9        ; Point to sys byte
  1109.     MOV    L,A        ; Save (can't carry to h)
  1110. ;
  1111.      IF    SOPT
  1112.     LDA    SOPFLG        ; Did user request sys files?
  1113.     ORA    A
  1114.     JZ    SYSFOK
  1115.      ENDIF            ; Sopt
  1116. ;
  1117.     MOV    A,M        ; Get system byte
  1118.     ORA    A        ; Check bit 7
  1119.     JM    MORDIR        ; Skip that file
  1120. ;
  1121. SYSFOK:    MOV    A,L        ; Go back now
  1122.     SUI    10        ; Back to user number (alloc flag)
  1123.     MOV    L,A        ; Hl points to entry now
  1124.     LDA    NEWUSR        ; Get current user
  1125.     CMP    M
  1126.     JNZ    MORDIR        ; Ignore if different
  1127.     INX    H
  1128. ;
  1129. ;
  1130. ; Move entry to table
  1131. ;
  1132.     XCHG            ; Entry to de
  1133.     LHLD    NEXTT        ; Next table entry to hl
  1134.     MVI    B,11        ; Entry length (name, type, extent)
  1135. ;
  1136. TMOVE:    LDAX    D        ; Get entry character
  1137. ;
  1138.      IF    NOT (VECTOR OR REVIDEO)
  1139.     ANI    7FH        ; Remove attributes
  1140.      ENDIF            ; Not (vector or revideo)
  1141. ;
  1142.     MOV    M,A        ; Store in table
  1143.     INX    D
  1144.     INX    H
  1145.     DCR    B        ; More?
  1146.     JNZ    TMOVE
  1147.     INX    D        ; De->> s1
  1148.     INX    D        ; De->> s2
  1149.     LDAX    D        ; Get s2 byte, overflow=int(extents/32)
  1150.     PUSH    H        ; Save hl
  1151.     MOV    L,A        ; Set up 16-bit multiply
  1152.     MVI    H,0
  1153.     MVI    B,5
  1154.     CALL    SHLL        ; Hl is now # of overflow extents
  1155.     DCX    D        ; De->> s1
  1156.     DCX    D        ; De->> extent
  1157.     LDAX    D        ; Get extent
  1158.     ADD    L
  1159.     MOV    L,A
  1160.     MOV    A,H
  1161.     ACI    0
  1162.     MOV    H,A        ; Hl now has total extents
  1163.     MVI    B,7
  1164.     CALL    SHLL        ; Hl now has total sectors less last ext
  1165.     INX    D        ; De->> s1
  1166.     INX    D        ; De->> s2
  1167.     INX    D        ; Point to sector count
  1168.     LDAX    D        ; Get it
  1169.     ADD    L
  1170.     MOV    L,A
  1171.     MOV    A,H
  1172.     ACI    0
  1173.     MOV    H,A        ; Hl now has total sectors
  1174.     XTHL            ; Do some fancy shuffling
  1175.     XCHG
  1176.     XTHL
  1177.     XCHG
  1178.     MOV    M,D
  1179.     INX    H
  1180.     MOV    M,E
  1181.     POP    D        ; All back to normal...
  1182.     INX    H
  1183.     SHLD    NEXTT        ; Save updated table address
  1184.     XCHG
  1185.     LHLD    COUNT        ; Bump the # of matches made
  1186.     INX    H
  1187.     SHLD    COUNT
  1188.     LXI    H,13        ; Size of next entry
  1189.     DAD    D
  1190.     XCHG            ; Future nextt is in de
  1191.     LHLD    BDOS+1        ; Pick up tpa end
  1192.     MOV    A,E
  1193.     SUB    L        ; Compare nextt-tpa end
  1194.     MOV    A,D
  1195.     SBB    H
  1196.     JC    MORDIR        ; If tpa end > nextt, loop back for more
  1197. ;
  1198. OUTMEM:    CALL    ERXIT        ; Exit if directory too large
  1199.     DB    'Memory',0
  1200. ;
  1201. ;
  1202. ; Shift HL left by B bits
  1203. ;
  1204. SHLL:    DAD    H
  1205.     DCR    B
  1206.     RZ
  1207.     JMP    SHLL
  1208. ;
  1209. ;
  1210. ; Sort and print
  1211. ;
  1212. SPRINT:     IF    AOPT OR    FOPT OR    UOPT
  1213.     CALL    SETFOP        ; Return to file output dma & user #
  1214.      ENDIF            ; Aopt or fopt or uopt
  1215. ;
  1216.     LHLD    COUNT        ; Get file name count
  1217.     MOV    A,L
  1218.     ORA    H        ; Any found?
  1219.     JZ    PRTOTL        ; Exit if no files found
  1220.     PUSH    H        ; Save file count
  1221.     STA    SUPSPC        ; Enable leading zero suppression
  1222. ;
  1223. ;
  1224. ; Initialize the order table
  1225. ;
  1226.     LHLD    TBLOC        ; Get start of name table
  1227.     XCHG            ; Into de
  1228.     LXI    H,ORDER        ; Point to order table
  1229.     LXI    B,13        ; Entry length
  1230. ;
  1231. BLDORD:    MOV    M,E        ; Save low order address
  1232.     INX    H
  1233.     MOV    M,D        ; Save high order address
  1234.     INX    H
  1235.     XCHG            ; Table addr to hl
  1236.     DAD    B        ; Point to next entry
  1237.     XCHG
  1238.     XTHL            ; Save tbl addr, fetch loop counter
  1239.     DCX    H        ; Count down loop
  1240.     MOV    A,L
  1241.     ORA    H        ; More?
  1242.     XTHL            ; (restore tbl addr, save counter)
  1243.     JNZ    BLDORD        ; Yes, go do another one
  1244.     POP    H        ; Clean loop counter off stack
  1245.     LHLD    COUNT        ; Get count
  1246.     SHLD    SCOUNT        ; Save as # to sort
  1247.     DCX    H        ; Only 1 entry?
  1248.     MOV    A,L
  1249.     ORA    H
  1250.     JZ    DONE        ; Yes, so skip sort
  1251. ;
  1252. ;
  1253. ; This sort routine is adapted from SOFTWARE TOOLS by Kernigan and
  1254. ; Plaugher.
  1255. ;
  1256. SORT:    LHLD    SCOUNT        ; Number of entries
  1257. ;
  1258. L0:    ORA    A        ; Clear carry
  1259.     MOV    A,H        ; Gap=gap/2
  1260.     RAR
  1261.     MOV    H,A
  1262.     MOV    A,L
  1263.     RAR
  1264.     MOV    L,A
  1265.     ORA    H        ; Is it zero?
  1266.     JZ    DONE        ; Then none left
  1267.     MOV    A,L        ; Make gap odd
  1268.     ORI    1
  1269.     MOV    L,A
  1270.     SHLD    GAP
  1271.     INX    H        ; I=gap+1
  1272. ;
  1273. L2:    SHLD    I
  1274.     XCHG
  1275.     LHLD    GAP
  1276.     MOV    A,E        ; J=i-gap
  1277.     SUB    L
  1278.     MOV    L,A
  1279.     MOV    A,D
  1280.     SBB    H
  1281.     MOV    H,A
  1282. ;
  1283. L3:    SHLD    J
  1284.     XCHG
  1285.     LHLD    GAP        ; Jg=j+gap
  1286.     DAD    D
  1287.     SHLD    JG
  1288.     MVI    A,13        ; Compare 13 chars     {sfk}
  1289.     CALL    COMPARE        ; Compare (j) and (jg)
  1290.     JP    L5        ; If a(j)<=a(jg)
  1291.     LHLD    J
  1292.     XCHG
  1293.     LHLD    JG
  1294.     CALL    SWAP        ; Exchange a(j) and a(jg)
  1295.     LHLD    J        ; J=j-gap
  1296.     XCHG
  1297.     LHLD    GAP
  1298.     MOV    A,E
  1299.     SUB    L
  1300.     MOV    L,A
  1301.     MOV    A,D
  1302.     SBB    H
  1303.     MOV    H,A
  1304.     JM    L5        ; If j>0 goto l3
  1305.     ORA    L        ; Check for zero
  1306.     JZ    L5
  1307.     JMP    L3
  1308. ;
  1309. L5:    LHLD    SCOUNT        ; For later
  1310.     XCHG
  1311.     LHLD    I        ; I=i+1
  1312.     INX    H
  1313.     MOV    A,E        ; If i<=n goto l2
  1314.     SUB    L
  1315.     MOV    A,D
  1316.     SBB    H
  1317.     JP    L2
  1318.     LHLD    GAP
  1319.     JMP    L0
  1320. ;
  1321. ;
  1322. ; Sort is all done - print entries
  1323. ;
  1324. DONE:     IF    FOPT        ; If output option wanted, prepare file
  1325.     LDA    FOPFLG
  1326.     ORA    A
  1327.     JNZ    NOOUT        ; If file output, fall through, a=0
  1328. ;
  1329. ;
  1330. ; If all user option enabled, and we're not on the first pass, then the
  1331. ; output file is already open and positioned, so we can skip the open.
  1332. ;
  1333.     LXI    H,OPNFLG    ; Get pointer to output file open flag
  1334.     CMP    M        ; A=0,set z if opnflg=0 also
  1335.     JNZ    NOOUT        ; If opnflg not zero, skip open
  1336.     DCR    M        ; Else, set opnflg for next user #
  1337. ;
  1338. ;
  1339. ; First pass on file append - prepare SD.DIR to receive new or appended
  1340. ; output.
  1341. ;
  1342.     LXI    D,OUTFCB    ; Does output file already exist?
  1343.     MVI    C,SEARCH
  1344.     CALL    CPM
  1345.     INR    A
  1346.     JNZ    OPENIT        ; If it does, then open it for processing
  1347.     MVI    C,MAKE        ; Otherwise, create the output file
  1348.     CALL    CPM
  1349.     INR    A
  1350.     JNZ    NOOUT        ; Continue if open successful
  1351. ;
  1352. ;
  1353. ; If make or open fails, declare error
  1354. ;
  1355. OPNERR:    CALL    ERXIT
  1356.     DB    'Open',0
  1357. ;
  1358. WRTERR:    CALL    ERXIT
  1359.     DB    'Write',0
  1360. ;
  1361. ;
  1362. ; Output file already exists - open it and position to the last record
  1363. ; of the last extent.
  1364. ;
  1365. OPENIT:    MVI    C,OPEN        ; Open 1st extent of output file
  1366.     CALL    CPM
  1367.     INR    A
  1368.     JZ    OPNERR        ; Bad deal if 1st won't open
  1369. ;
  1370. OPNMOR:    LDA    OUTFCB+15
  1371.     CPI    128
  1372.     JC    LSTEXT        ; If rc<128, this is last extent
  1373.     LXI    H,OUTFCB+12
  1374.     INR    M        ; Else, bump to next extent
  1375.     MVI    C,OPEN        ; And try to open it
  1376.     CALL    CPM
  1377.     INR    A
  1378.     JNZ    OPNMOR        ; Continue opening extents til no more
  1379.     DCR    M        ; Then, reopen preceding extent
  1380.     MVI    C,OPEN
  1381.     CALL    CPM
  1382.     LDA    OUTFCB+15    ; Get rc for the last extent
  1383. ;
  1384. ;
  1385. ; At this point, OUTFCB is opened to the last extent of the file, so
  1386. ; read in the last record in the last extent.
  1387. ;
  1388. LSTEXT:    ORA    A        ; Is this extent empty?
  1389.     JZ    NOOUT        ; If so, then  starting a clean slate
  1390.     DCR    A        ; Normalize record count
  1391.     STA    OUTFCB+32    ; Set record number to read
  1392.     MVI    C,READ        ; And read last record of file
  1393.     CALL    CPM
  1394.     ORA    A        ; Was read successful?
  1395.     JZ    RDOK        ; If so, proceed to scan for eof mark
  1396. ;
  1397. APERR:    CALL    ERXIT
  1398.     DB    'Append',0
  1399. ;
  1400. ;
  1401. ; We now have the last record in the file in our buffer.  Scan the last
  1402. ; record for the EOF mark, indicating where we can start adding data.
  1403. ;
  1404. RDOK:    LXI    H,OUTBUF    ; Point to start of output buffer
  1405.     MVI    B,128        ; Get length of output buffer
  1406. ;
  1407. SCAN:    MOV    A,M
  1408.     CPI    'Z'-40H        ; Have we found end of file?
  1409.     JZ    RESCR        ; If so, save pointers and reset cr
  1410.     INX    H
  1411.     DCR    B
  1412.     JNZ    SCAN        ; Otherwise, look until end of buffer
  1413. ;
  1414. ;
  1415. ; If we find an explicit EOF mark in the last buffer (or an implied EOF
  1416. ; if the last record is full), move the FCB record and extent pointers
  1417. ; back to correct for the read operation so that our first write opera-
  1418. ; tion will effectively replace the last record of the SD.DIR file.
  1419. ;
  1420. RESCR:    PUSH    H        ; Save eof buffer pointer
  1421.     PUSH    B        ; Save eof buffer remaining
  1422.     LXI    H,OUTFCB+32    ; Get current record again
  1423.     DCR    M        ; Dock it
  1424.     JP    SAMEXT        ; If cr >=0, we're still in same extent
  1425.     LXI    H,OUTFCB+12    ; Else, move to previous extent
  1426.     DCR    M
  1427.     MVI    C,OPEN        ; Then, reopen the previous extent
  1428.     CALL    CPM
  1429.     INR    A
  1430.     JZ    APERR        ; Append position error if can not reopen
  1431.     LDA    OUTFCB+15    ; Else, position to last record of extent
  1432.     DCR    A
  1433.     STA    OUTFCB+32
  1434. ;
  1435. SAMEXT:    POP    PSW        ; Recall where eof is in buffer
  1436.     STA    BUFCNT        ; And set buffer counter
  1437.     POP    H        ; Recall next buffer pointer
  1438.     SHLD    BUFPNT        ; And set pointer for first addition
  1439.      ENDIF            ; Fopt
  1440. ;
  1441. ;        end of    IF  FOPT  routine
  1442. ;-----------------------------------------------------------------------
  1443. ;
  1444. NOOUT:     IF    VOPT        ; If version option, check if first
  1445.     LDA    FIRSTT        ; Time through
  1446.     ORA    A
  1447.     JNZ    NOVOPT        ; No, we've been here before
  1448.     MVI    A,0FFH        ; Virgin, poke it
  1449.     STA    FIRSTT
  1450.     LDA    VOPFLG        ; If version display flag set, print it
  1451.     ORA    A
  1452.     JNZ    NOVOPT
  1453.     LXI    D,VERNAME
  1454.     CALL    PRINT
  1455.     CALL    CRLF
  1456. ;
  1457. NOVOPT:     ENDIF            ; Vopt
  1458. ;
  1459.      IF    LOPT
  1460.     LHLD    COUNT
  1461.     SHLD    LCOUNT
  1462.     LXI    H,0
  1463.     SHLD    LBTOTL
  1464.     SHLD    LMTOTL
  1465.     LXI    H,ORDER        ; Initialize order table pointer
  1466.     SHLD    NEXTL
  1467.      ENDIF            ; Lopt
  1468. ;
  1469.      IF    NOT LOPT
  1470.     LXI    H,ORDER        ; Initialize order table pointer
  1471.      ENDIF            ; Not lopt
  1472. ;
  1473.     SHLD    NEXTT
  1474. ;
  1475.      IF    VCODE
  1476.     LHLD    COUNT        ; Code computes end of name
  1477.     CALL    MULT13        ; Table (or start of second table
  1478.     XCHG            ; Where files will be stored after
  1479.     LHLD    TBLOC        ; Redundant extents removed.)
  1480.     DAD    D
  1481.     SHLD    NEWPTR        ; Save it twice
  1482.     SHLD    XPOINT        ; For later
  1483.      ENDIF            ; Vcode
  1484. ;
  1485.      IF    NOT VCODE    ;
  1486.     JMP    NEWLIN        ; Start new line and output the files
  1487.      ENDIF            ; Not vcode
  1488. ;
  1489. ;
  1490. ; Output the directory files we've matched.
  1491. ;
  1492. ENTRY:    LHLD    COUNT
  1493.     DCX    H        ; Dock file count
  1494.     SHLD    COUNT
  1495.     MOV    A,H        ; Is this the last file?
  1496.     ORA    L
  1497.     JZ    OKPRNT        ; If count=0, last file so skip compare
  1498. ;
  1499. ;
  1500. ; Compare each entry to make sure that it isn't part of a multiple ex-
  1501. ; tent file.    Go only when we have the last extent of the file.
  1502. ;
  1503.     PUSH    B        ; Save npl
  1504. ;
  1505.      IF    NOT VCODE
  1506.     CALL    CKABRT        ; Check for abort code from keyboard
  1507.      ENDIF            ; Not vcode
  1508. ;
  1509.     LHLD    NEXTT
  1510.     MVI    A,11
  1511.     CALL    COMPR        ; Does this entry match next one?
  1512.     POP    B        ; Recall npl
  1513.     JNZ    OKPRNT        ; No, print it
  1514.     INX    H
  1515.     INX    H        ; Skip since highest extent last in list
  1516.     SHLD    NEXTT
  1517.     JMP    ENTRY        ; Loop back for next lowest extent
  1518. ;
  1519. ;
  1520. ; Vcode substitution .    If VCODE option chosen, OKPRINT moves unique
  1521. ; filenames and sizes in 'k' to a second table above the first for use
  1522. ; later.
  1523. ;
  1524. OKPRNT:    LHLD    NEXTT        ; Get order table pointer
  1525.     MOV    E,M        ; Get low order address
  1526.     INX    H
  1527.     MOV    D,M        ; Get high order address
  1528.     INX    H
  1529.     SHLD    NEXTT        ; Save updated table pointer
  1530.     XCHG            ; Table entry to hl
  1531. ;
  1532.      IF    VCODE
  1533.     PUSH    H        ; Save address of byte to be moved
  1534.     LHLD    NEWPTR        ; Get address in new table to put it in
  1535.     PUSH    H        ; Save it
  1536.     LXI    D,13        ; Update it
  1537.     DAD    D
  1538.     SHLD    NEWPTR        ; Save for later - will be end of table
  1539.     POP    H        ; Get current move to address
  1540.     XCHG            ; Put in de
  1541.     POP    H        ; Get current move from address back
  1542.     MVI    B,11        ; Size of file name, type
  1543.     CALL    MOVE        ; Move it
  1544.     PUSH    D
  1545.      ENDIF            ; Vcode
  1546. ;
  1547.      IF    NOT VCODE
  1548.     MVI    B,8        ; File name length
  1549.     CALL    TYPEIT        ; Type filename
  1550.     MVI    A,'.'        ; Period after fn
  1551.     CALL    TYPE
  1552.     MVI    B,3        ; Display 3 characters of filetype
  1553.     CALL    TYPEIT
  1554.      ENDIF            ; Not vcode
  1555. ;
  1556.     CALL    DOIT
  1557.     LHLD    TOTSIZ        ; De now has rounded size in k
  1558.     DAD    D        ; Add to total used
  1559.     SHLD    TOTSIZ
  1560.     LHLD    TOTFIL        ; Increment file count
  1561.     INX    H
  1562.     SHLD    TOTFIL
  1563.     XCHG            ; Get back file size
  1564. ;
  1565.      IF    VCODE
  1566.     POP    D        ; Get back where size is to go
  1567.     MOV    A,H        ; Move size to table two
  1568.     STAX    D
  1569.     INX    D
  1570.     MOV    A,L
  1571.     STAX    D
  1572. ;
  1573. ;
  1574. ; One file MOVED - test to see if we have to move another one.
  1575. ;
  1576.     LHLD    COUNT        ; Get current file counter and test it
  1577.     MOV    A,H
  1578.     ORA    L
  1579.     JZ    PRTOTL        ; If no more files exit to summary output
  1580.     JMP    ENTRY        ; If more, go get them
  1581.      ENDIF            ; Vcode
  1582. ;
  1583. ;
  1584. ; Output the size of the individual file.
  1585. ;
  1586.      IF    NOT VCODE
  1587.     CALL    FDECPRT        ; Go print it
  1588.     MVI    A,'k'        ; And follow with k size
  1589.     CALL    TYPE
  1590. ;
  1591. ;
  1592. ; One file output - test to see if we have to output another one.
  1593. ;
  1594.     LHLD    COUNT        ; Get current file counter and test it
  1595.     MOV    A,H
  1596.     ORA    L
  1597.     JZ    PRTOTL        ; If no more files exit to summary output
  1598. ;
  1599. ;
  1600. ; At least one more file to output - can we put it on the current line?
  1601. ;
  1602.     DCR    C
  1603.     PUSH    PSW
  1604.     CNZ    FENCE        ; If room left output the fence character
  1605.     POP    PSW
  1606.     JNZ    ENTRY        ; And go output another file
  1607. ;
  1608. ;
  1609. ; Current line full, start a new one.
  1610. ;
  1611. NEWLIN:    LDA    MNPL
  1612.     MOV    C,A        ; Reset names per line counter
  1613.     CALL    CRLF        ; Space down to next line
  1614.      ENDIF            ; Not vcode
  1615. ;
  1616.      IF    PRDI AND (NOT VCODE)
  1617.     LDA    FCB        ; Precede new line with drive name
  1618.     ADI    'A'-1
  1619.     CALL    TYPE
  1620.      ENDIF            ; Prdi and (not vcode)
  1621. ;
  1622.      IF    PRDI AND (NOT VCODE) AND (REPUSR AND PRUS)
  1623.                 ; If reporting user # and running under
  1624.     CALL    CKVER        ; Cp/m 2, output the user number too
  1625.     CNC    TYPUSR
  1626.      ENDIF            ; Prdi and (not vcode) and (repusr and prus)
  1627. ;
  1628.      IF    PRDI AND (NOT VCODE)
  1629.     MVI    A,':'        ; Tag header with a colon and a space
  1630.     CALL    FPAD        ; And exit back to entry
  1631.      ENDIF            ; Prdi and (not vcode)
  1632. ;
  1633.      IF    NOT VCODE
  1634.     JMP    ENTRY        ; Go back and output another file
  1635.      ENDIF            ; Not vcode
  1636. ;
  1637. ;
  1638. ; Compute the size of the file/library and update our summary datum.
  1639. ; This has been changed into a subroutine so that both the file size
  1640. ; computation and a library size (when printing out library members)
  1641. ; can be computed in K.
  1642. ;
  1643. DOIT:    MOV    D,M
  1644.     INX    H
  1645.     MOV    E,M        ; Size in de (sectors)
  1646.     LDA    BLKMSK
  1647.     PUSH    PSW
  1648.     ADD    E
  1649.     MOV    E,A
  1650.     MOV    A,D
  1651.     ACI    0
  1652.     MOV    D,A
  1653.     POP    PSW
  1654.     CMA
  1655.     ANA    E
  1656.     MOV    E,A
  1657.     MVI    B,3
  1658. ;
  1659. SHRR:    MOV    A,D
  1660.     ORA    A
  1661.     RAR
  1662.     MOV    D,A
  1663.     MOV    A,E
  1664.     RAR
  1665.     MOV    E,A
  1666.     DCR    B
  1667.     JNZ    SHRR
  1668.     RET
  1669. ;.....
  1670. ;
  1671. ;
  1672. ; Print HL in decimal with leading zero suppression
  1673. ;
  1674. FDECPRT: IF    KTHREE        ; Individual file size print
  1675.     XRA    A        ; Clear leading zero flag
  1676.     STA    LZFLG
  1677.     JMP    SKTHSD
  1678.      ENDIF            ; Kthree
  1679. ;
  1680. DECPRT:    XRA    A        ; Clear leading zero flag
  1681.     STA    LZFLG
  1682.     LXI    D,-10000
  1683.     LDA    SUPSPC
  1684.     PUSH    PSW
  1685.     XRA    A
  1686.     STA    SUPSPC
  1687.     CALL    DIGIT
  1688.     POP    PSW
  1689.     STA    SUPSPC
  1690.     LXI    D,-1000        ; Print 1000's digit
  1691.     CALL    DIGIT
  1692. ;
  1693. SKTHSD:    LXI    D,-100        ; Etc.
  1694.     CALL    DIGIT
  1695.     LXI    D,-10
  1696.     CALL    DIGIT
  1697.     MVI    A,'0'        ; Get 1's digit
  1698.     ADD    L
  1699.     JMP    TYPE
  1700. ;
  1701. DIGIT:    MVI    B,'0'        ; Start off with ascii 0
  1702. ;
  1703. DIGLP:    PUSH    H        ; Save current remainder
  1704.     DAD    D        ; Subtract
  1705.     JNC    DIGEX        ; Quit on overflow
  1706.     POP    PSW        ; Throw away remainder
  1707.     INR    B        ; Bump digit
  1708.     JMP    DIGLP        ; Loop back
  1709. ;
  1710. DIGEX:    POP    H        ; Restore pointer
  1711.     MOV    A,B
  1712.     CPI    '0'        ; Zero digit?
  1713.     JNZ    DIGNZ        ; No, type it
  1714.     LDA    LZFLG        ; Leading zero?
  1715.     ORA    A
  1716.     MVI    A,'0'
  1717.     JNZ    TYPE        ; Print digit
  1718.     LDA    SUPSPC        ; Get space suppression flag
  1719.     ORA    A        ; See if printing file totals
  1720.     RZ            ; Yes, don't give leading spaces
  1721.     JMP    SPACE        ; Leading zero...print space
  1722. ;
  1723. DIGNZ:    STA    LZFLG        ; Leading zero flag so next zero prints
  1724.     JMP    TYPE        ; And print digit
  1725. ;.....
  1726. ;
  1727. ;=======================================================================
  1728. ;         VCODE subroutines begin here
  1729. ;
  1730. ; Multiply contents of HL register by 13
  1731. ;
  1732.      IF    VCODE
  1733. MULT13:    MOV    D,H
  1734.     MOV    E,L
  1735.     DAD    H
  1736.     DAD    D
  1737.     DAD    H
  1738.     DAD    H
  1739.     DAD    D
  1740.     RET
  1741. ;.....
  1742. ;
  1743. ;
  1744. ; Main subroutine to print out a filename and column delimiter
  1745. ;
  1746. SUBA:    CALL    PFILE1        ; Routine to print a filename
  1747.     RZ            ; If at end of line return with zero set
  1748. ;;    CPI    0FFH        ; If true past the end of the table;850315
  1749. ;;    CNZ    FENCE        ; Print the column delimiter if more;850315
  1750.     CC    FENCE        ; Print col delimiter if more    ;850315
  1751.     LHLD    JUMPER        ; Put the jumper back in de
  1752.     XCHG
  1753.     ORI    1        ; Insure non zero return    ;850315
  1754.     RET
  1755.  
  1756. ;.....
  1757. ;
  1758. ;
  1759. PFILE1:    MOV    A,M        ; Let's see what we have
  1760.     CPI    0FEH
  1761.     RNC
  1762.     ANI    7FH        ; Strip parity bit
  1763.     PUSH    B        ; Save the number of columns
  1764.     MVI    B,8        ; Print file name and type
  1765.     CALL    TYPEIT
  1766.     MVI    A,'.'
  1767.     CALL    TYPE
  1768.     MVI    B,3
  1769.     CALL    TYPEIT
  1770.     PUSH    H
  1771.     CALL    CKABRT        ; Ctl-c from keyboard?
  1772.     POP    H
  1773.     MOV    D,M        ; Get it into
  1774.     INX    H
  1775.     MOV    E,M
  1776.     XCHG            ; Hl
  1777.     CALL    FDECPRT        ; And print it out
  1778.     MVI    A,'k'
  1779.     CALL    TYPE
  1780.     POP    B        ; Get back number of columns
  1781.     LHLD    TOTFIL        ; Get number of files left
  1782.     DCX    H        ; Reduce it by one
  1783.     SHLD    TOTFIL        ; And resave it
  1784.     MOV    A,H
  1785.     ORA    L        ; Down to zero yet?
  1786.     RZ            ; Return if no more files
  1787.     DCR    C        ; Decrement it and
  1788.     STC            ; Force carry on this return    ;850315
  1789.     RET
  1790.      ENDIF            ; Vcode
  1791. ;.....
  1792. ;
  1793. ;            end of VCODE routines
  1794. ;=======================================================================
  1795. ;
  1796. ;
  1797. ; Show total space and files used
  1798. ;
  1799. PRTOTL:     IF    LOPT AND (NOT VCODE)
  1800.     LDA    LOPFLG
  1801.     ORA    A
  1802.      ENDIF            ; Lopt and (not vcode)
  1803. ;
  1804.      IF    LOPT AND (NOT VCODE) AND LOPREV
  1805.     JZ    PRTOT1
  1806.      ENDIF            ; Lopt and (not vcode) and loprev
  1807. ;
  1808.      IF    LOPT AND (NOT VCODE) AND (NOT LOPREV)
  1809.     JNZ    PRTOT1
  1810.      ENDIF            ; Lopt and (not vcode) and (not loprev)
  1811. ;
  1812.      IF    LOPT AND (NOT VCODE)
  1813.     LHLD    TOTFIL        ; How many files did we match?
  1814.     MOV    A,H
  1815.     ORA    L
  1816.     CNZ    PRTLMEM        ; Skip the .lbr check if none found
  1817. ;
  1818. PRTOT1    EQU    $
  1819.      ENDIF            ; Lopt and (not vcode)
  1820. ;
  1821.     XRA    A        ; Get a zero to...
  1822.     STA    SUPSPC        ; Suppress leading spaces in totals
  1823.     LHLD    TOTFIL        ; How many files did we match?
  1824.     MOV    A,H
  1825.     ORA    L
  1826.     JZ    NXTUSR        ; Skip the summary if we didn't find any
  1827.     PUSH    H        ; Save totfil
  1828.     STA    FNDFLG        ; Set file found flag
  1829. ;
  1830.      IF    VCODE        ; Leading crlf for vertical output mode
  1831.     LDA    FIRSTT        ; If not first time through
  1832.     ORA    A
  1833.     CNZ    CRLF
  1834.      ENDIF            ; Vcode
  1835. ;
  1836.     LXI    D,TOTMS1    ; Print [cr,lf]  " Drive "
  1837.     CALL    PRINT
  1838.     LDA    FCB
  1839.     ADI    'A'-1
  1840.     CALL    TYPE        ; Output the drive code
  1841. ;
  1842.      IF    REPUSR
  1843.     CALL    CKVER
  1844.     JC    NOUSER
  1845.     CALL    TYPUSR        ; Output the user number
  1846.      ENDIF            ; Repusr
  1847. ;
  1848. NOUSER:    LXI    D,TOTMS6    ; Print " FILES: "
  1849.     CALL    PRINT
  1850.     POP    H        ; Recall totfil
  1851.     CALL    DECPRT        ; Print number of files matched
  1852.     PUSH    PSW        ; Just in case
  1853.     LDA    MNPL        ; Load a with # of names per line
  1854.     CPI    3        ; Is it 3?
  1855.     JZ    SKDRV        ; Yes then skip cr,lf print
  1856.     CPI    4        ; Is it 4?
  1857.     JZ    SKDRV        ; Yes then skip cr,lf print
  1858.     LXI    D,TOTMS3    ; Split drive status line for 40 < display
  1859.     CALL    PRINT        ; Do it
  1860. ;
  1861. SKDRV:    POP    PSW        ; Put it back
  1862.     LXI    D,TOTMS4    ; No cr,lf needed since display > 40
  1863.     CALL    PRINT
  1864.     LHLD    TOTSIZ        ; Print total k used by files matched
  1865.     CALL    DECPRT
  1866.     LXI    D,TOTMS5    ; Print "K "
  1867.     CALL    PRINT
  1868.     CALL    PRTFRE        ; Output free space remaining & " FREE."
  1869. ;
  1870.      IF    NOT VCODE
  1871.     CALL    CRLF
  1872.      ENDIF            ; Not vcode
  1873. ;
  1874. ;
  1875. ; Summary line printed, now print the detail files, but first compute
  1876. ; total lines the printout will take.
  1877. ;
  1878.      IF    VCODE
  1879. NPRNT:    PUSH    PSW        ; Just in case
  1880.     LDA    MNPL        ; Load a with # names per line
  1881.     CPI    1        ; Is it 1?
  1882.     JNZ    MNC1        ; If not test for 2
  1883.     LXI    D,0-1        ; Minus number of columns
  1884.     LXI    B,1-1        ; Number of columns minus 1
  1885. ;
  1886. MNC1:    CPI    2        ; Wasn't 1, is it 2?
  1887.     JNZ    MNC2        ; If not then test for 3
  1888.     LXI    D,0-2        ; Minus number of columns
  1889.     LXI    B,2-1        ; Number of columns minus 1
  1890. ;
  1891. MNC2:    CPI    3        ; Wasn't 2, is it 3?
  1892.     JNZ    MNC3        ; If not then test for 4
  1893.     LXI    D,0-3        ; Minus number of columns
  1894.     LXI    B,3-1        ; Number of columns minus 1
  1895. ;
  1896. MNC3:    CPI    4        ; Wasn't 3, is it 4?
  1897.     JNZ    MNC4        ; If not then fall through
  1898.     LXI    D,0-4        ; Minus number of columns
  1899.     LXI    B,4-1        ; Number of columns minus 1
  1900. ;
  1901. MNC4:    POP    PSW        ; Put it back
  1902.     LHLD    TOTFIL        ; Get total number of files
  1903.     DAD    B        ; Round up to a full line
  1904.     MVI    C,0FFH
  1905. ;
  1906. NPRNT1:    INR    C        ; 'c' will end up holding number
  1907.     DAD    D        ; Of lines to be displayed.
  1908.     JC    NPRNT1
  1909.     MOV    A,C
  1910.     STA    LINES        ; Done. save it for later
  1911.     STA    SUPSPC        ; Allow spaces in front of file sizes
  1912. ;
  1913. ;
  1914. ; Number of lines times size of an entry equals the number of bytes to
  1915. ; jump in the second table when outputing files in vertical order.
  1916. ;
  1917.     MOV    L,A        ; Put number of lines into hl
  1918.     MVI    H,0
  1919.     CALL    MULT13
  1920.     SHLD    JUMPER        ; Put it away
  1921. ;
  1922. ;
  1923. ; Fill a sector with FF at the end of table 2
  1924. ;
  1925.     LHLD    NEWPTR        ; Now points to end of table 2
  1926.     MVI    B,128
  1927.     MVI    A,0FFH
  1928. ;
  1929. NPRNT2:    MOV    M,A
  1930.     INX    H
  1931.     DCR    B
  1932.     JNZ    NPRNT2
  1933. ;
  1934. ;
  1935. ; Increment the number of files for use later in SUBA.    This insures
  1936. ; that a column delimiter will be printed after the last filename, if
  1937. ; the file appears in other than the last column of the display.
  1938. ;
  1939.     LXI    H,TOTFIL
  1940.     INR    M
  1941. ;
  1942. ;
  1943. ; Print out a line of files
  1944. ;
  1945. NPRNT3:    CALL    CRLF        ; Start a new line
  1946.     PUSH    PSW        ; Save it just in case
  1947.     LDA    MNPL        ; Load a with # of names per line
  1948.     MOV    C,A        ; Reset number of columns
  1949.     POP    PSW        ; Put it back
  1950.      ENDIF            ; Vcode
  1951. ;
  1952.      IF    PRDI AND VCODE
  1953.     PUSH    B
  1954.     LDA    FCB        ; Show drive letter at beginning of
  1955.     ADI    'A'-1        ; Each line
  1956.     CALL    TYPE
  1957.      ENDIF            ; Prdi and vcode
  1958. ;
  1959.      IF    REPUSR AND PRUS    AND PRDI AND VCODE ; Also user number, if allowed
  1960.     CALL    CKVER
  1961.     CNC    TYPUSR
  1962.      ENDIF            ; Repusr and prus and prdi and vcode
  1963. ;
  1964.      IF    PRDI AND VCODE
  1965.     MVI    A,':'
  1966.     CALL    FPAD
  1967.     POP    B
  1968.      ENDIF            ; Prdi and vcode
  1969. ;
  1970. ;
  1971. ; Print first filename
  1972. ;
  1973.      IF    VCODE
  1974.     LHLD    XPOINT        ; Xpoint points to start of second table
  1975.     CALL    SUBA        ; At entry.  below it is incremented
  1976.                 ; For additional lines of printout.
  1977.     JZ    NLINE        ; Either out of columns or out of files.
  1978. ;
  1979. ;
  1980. ; Print second filename
  1981. ;
  1982.     LHLD    XPOINT
  1983.     DAD    D
  1984.     CALL    SUBA
  1985.     JZ    NLINE
  1986. ;
  1987. ;
  1988. ; NOTE: The following conditionals are used only to save some bytes if
  1989. ;    running with only two or three columns of files in display.
  1990. ;
  1991. ; Print third filename, if still room on line
  1992. ;
  1993.     PUSH    PSW        ; Just in case
  1994.     LDA    MNPL        ; Load a with # of names per line
  1995.     CPI    1        ; Is it 1?
  1996.     JZ    VCLT2        ; If so then skip name print
  1997.     CPI    2        ; Is it 2?
  1998.     JZ    VCLT2        ; If so then skip name print
  1999.     POP    PSW        ; Put it back where it belongs
  2000.     LHLD    XPOINT
  2001.     DAD    D
  2002.     DAD    D
  2003.     CALL    SUBA
  2004.     JZ    NLINE
  2005.     JMP    VCMT2
  2006. ;
  2007. VCLT2:    POP    PSW        ; Didn't put it back so do it now
  2008. ;
  2009. ;
  2010. ; Print fourth filename
  2011. ;
  2012. VCMT2:    PUSH    PSW        ; Just in case it's loaded  bang!
  2013.     LDA    MNPL        ; Load a with # of names per line
  2014.     CPI    4        ; Is it 4?
  2015.     JNZ    VCLT3        ; If not then skip fourth name print
  2016.     POP    PSW        ; Put it back
  2017.     LHLD    XPOINT
  2018.     DAD    D
  2019.     DAD    D
  2020.     DAD    D
  2021.     CALL    SUBA
  2022.     JMP    VCMT3
  2023. ;
  2024. VCLT3:    POP    PSW        ; Didn't put it back yet so do it now
  2025. ;
  2026. VCMT3:    DS    0
  2027. ;                ; Wasn't 4 so go
  2028. NLINE:    LHLD    XPOINT        ; Increment xpoint to next file
  2029.     LXI    D,13
  2030.     DAD    D
  2031.     SHLD    XPOINT
  2032.     LHLD    TOTFIL        ; Time to see if we're out of files
  2033.     MOV    A,H
  2034.     ORA    L
  2035.     JZ    DOLIB        ; Yes we are
  2036.     LXI    H,LINES        ; Nope, just need a new line
  2037.     DCR    M
  2038.     JNZ    NPRNT3
  2039.      ENDIF            ; Vcode
  2040. ;
  2041. DOLIB:     IF    LOPT AND VCODE
  2042.     LDA    LOPFLG
  2043.     ORA    A
  2044.      ENDIF            ; Lopt and vcode
  2045. ;
  2046.      IF    LOPREV AND LOPT    AND VCODE
  2047.     JZ    DOLIB1
  2048.      ENDIF            ; Loprev and lopt and vcode
  2049. ;
  2050.      IF    NOT LOPREV AND LOPT AND    VCODE
  2051.     JNZ    DOLIB1
  2052.      ENDIF            ; Not loprev and lopt and vcode
  2053. ;
  2054.      IF    LOPT AND VCODE
  2055.     LHLD    TOTFIL        ; How many files did we match?
  2056.     MOV    A,H
  2057.     ORA    L
  2058.     CNZ    PRTLMEM        ; Skip the library check if none found
  2059. ;
  2060. DOLIB1:     ENDIF            ; Lopt and vcode
  2061. ;
  2062. ;
  2063. ; Directory for one user area completed.  If 'all users' option is se-
  2064. ; lected, then go do another directory on the next user number until we
  2065. ; exceed the maximum user # for the selected drive.
  2066. ;
  2067. NXTUSR:     IF    AOPT        ; If all users option enabled
  2068.     LDA    AOPFLG        ; If not all users mode - skip next
  2069.     ORA    A
  2070.     JNZ    GOCLZ
  2071.     CALL    CKVER        ; Are we running cp/m 2?
  2072.     JC    GOCLZ        ; Skip user increment if not
  2073.     CALL    CKABRT        ; Check for user abort first
  2074.     LDA    MAXUSR        ; No abort - get maximum user number
  2075.     LXI    H,NEWUSR    ; Bump directory user number
  2076.     INR    M
  2077.     CMP    M        ; Does next user # exceed maximum?
  2078.     JNC    SETTBL        ; Continue if more user areas to go
  2079.      ENDIF            ; Aopt
  2080. ;
  2081.      IF    DOPT AND AOPT    ; If multi-disk option enabled
  2082.     LDA    BASUSR        ; Reset base user number for the
  2083.     MOV    M,A        ; Next directory search
  2084.      ENDIF            ; Dopt and aopt
  2085. ;
  2086. ;
  2087. ; We've finished all of our outputting.  Flush the remainder of the out-
  2088. ; put buffer and close the file before going to exit routine.
  2089. ;
  2090. GOCLZ:     IF    FOPT
  2091.     LXI    H,OPNFLG    ; Get file open status then reset flag to
  2092.     MOV    A,M        ; Force reopen on next pass
  2093.     MVI    M,0
  2094.     ORA    A
  2095.     JZ    NXTDSK        ; Skip closing sd.dir if it wasn't opened
  2096.     LXI    H,BUFCNT
  2097.     MOV    A,M        ; Retrieve # of unflushed characters in
  2098.     MVI    M,128        ; Buffer, force bufcnt to empty status
  2099.     ORA    A        ; If bufcnt=128, buffer empty set sign
  2100.     JM    CLOSE        ; Close sd.dir if buffer is empty
  2101.     JZ    FLUSH        ; Write last record to sd.dir if full buf
  2102.     LHLD    BUFPNT        ; Else pad unused buffer with ctl-z
  2103. ;
  2104. PUTAGN:    MVI    M,'Z'-40H
  2105.     INX    H
  2106.     DCR    A
  2107.     JNZ    PUTAGN        ; Keep padding until buffer filled out
  2108. ;
  2109. FLUSH:    LXI    D,OUTFCB    ; Flush the last output buffer
  2110.     MVI    C,WRITE
  2111.     CALL    CPM
  2112.     ORA    A
  2113.     JNZ    WRTERR
  2114. ;
  2115. CLOZE:    LXI    D,OUTFCB    ; Close the output file
  2116.     MVI    C,CLOSE
  2117.     CALL    CPM
  2118.      ENDIF            ; Fopt
  2119. ;
  2120. ;
  2121. ; Directory for all user areas completed.  If the multi-disk option is
  2122. ; enabled and selected, reset to the base user area and repeat the di-
  2123. ; rectory for next drive on-line until we either exceed the drives in
  2124. ; our LODRV-HIDRV table, or the BDOS shuts us down with a select or bad
  2125. ; sector error, which will be intercepted back to the EXIT module.
  2126. ;
  2127. NXTDSK:    LXI    H,FNDFLG    ; Get file found flag
  2128.     MOV    A,M
  2129.     MVI    M,0        ; Clear file found flag for next drive
  2130.     ORA    A
  2131.     JNZ    NDSK        ; Continue if at least 1 file found
  2132. ;
  2133.      IF    FOPT        ; If file output enabled, temp. diasable
  2134.     LXI    H,FOPFLG
  2135.     DCR    M
  2136.     PUSH    H
  2137.      ENDIF            ; Fopt
  2138. ;
  2139.     LXI    D,NOFMS1    ; Print first part of no files message
  2140.     CALL    PRINT        ; Print it
  2141.     LDA    MNPL        ; Load a with # of names per line
  2142.     CPI    4        ; Is it 4?
  2143.     JZ    LNOFM        ; If so then jump to long message print
  2144.     CPI    3        ; Is it 3?
  2145.     JZ    LNOFM        ; If so then jump to long message print
  2146.     LXI    D,NOFSM        ; Isn't 3 or 4 so set up short message
  2147.     CALL    PRINT        ; Print it
  2148.     JMP    NNOFM        ; Skip long message print
  2149.      IF    MAXCL        ; If maxcl then print short message anyway
  2150. LNOFM:    LXI    D,NOFSM        ; Since rcpm's won't want to print the word
  2151.      ENDIF            ; Maxcl
  2152. ;
  2153.      IF    NOT MAXCL    ; Not maxcl so long message is defined
  2154. LNOFM:    LXI    D,NOFLM
  2155.      ENDIF            ; Not maxcl
  2156. ;
  2157.     CALL    PRINT        ; Print message
  2158. ;
  2159. NNOFM:    LDA    FCB
  2160.     ADI    'A'-1
  2161.     CALL    TYPE        ; Output the drive
  2162. ;
  2163.      IF    REPUSR
  2164.     CALL    CKVER
  2165.     JC    NOUSR1
  2166.     CALL    TYPUSR        ; Output the user number
  2167.      ENDIF            ; Repusr
  2168. ;
  2169. NOUSR1:    LXI    D,NOFMS2    ; Print divider
  2170.     CALL    PRINT
  2171.     CALL    PRTFRE        ; Tag with free message
  2172. ;
  2173.      IF    NOT VCODE
  2174.     CALL    CRLF        ; Need another crlf in horiz. output mode
  2175.      ENDIF            ; Not vcode
  2176.  
  2177.      IF    FOPT        ; Restore original file output mode
  2178.     POP    H
  2179.     INR    M
  2180.      ENDIF            ; Fopt
  2181. ;
  2182. NDSK:     IF    DOPT        ; If multi-disk option enabled
  2183.     LDA    DOPFLG        ; If multi-disk not selected - skip next
  2184.     ORA    A
  2185.     JNZ    NPRT
  2186.     CALL    CKABRT        ; Check for user abort first
  2187.     MVI    A,HIDRV-LODRV    ; Get maximum drive code to search
  2188.     LXI    H,FCB        ; Bump directory fcb drive code
  2189.     INR    M
  2190.     CMP    M        ; Does next disk exceed maximum?
  2191.     JC    NPRT
  2192.      ENDIF            ; Dopt
  2193. ;
  2194.      IF    MAXDR AND DOPT
  2195.     LDA    MAXD        ; Look at another value limit
  2196.     INR    A
  2197.     CMP    M        ; Is it lower?
  2198.     JC    NPRT        ; Bail out if too low
  2199.     JMP    NOOPT        ; Search next disk
  2200.      ENDIF            ; Maxdr and dopt
  2201. ;
  2202.      IF    DOPT
  2203.     JNC    NOOPT        ; Search next disk if maxdr not true
  2204.      ENDIF            ; Dopt
  2205. ;
  2206. ;
  2207. ; If no printer, fall through to EXIT
  2208. ;
  2209. NPRT:     IF    POPT        ; Check if printer is in use
  2210.     LDA    POPFLG
  2211.     ORA    A        ; Printer active?
  2212.     JNZ    EXIT        ; No, just exit...
  2213.     MVI    C,5
  2214.     MVI    E,CR        ; Print a crlf
  2215.     CALL    CPM
  2216.     MVI    E,LF        ; Line feed
  2217.     CALL    CPM
  2218.      ENDIF            ; Popt
  2219. ;
  2220.     JMP    EXIT        ; All done - exit to ccp
  2221. ;.....
  2222. ;
  2223. ;
  2224. ; Print the user number of the directory in decimal
  2225. ;
  2226. TYPUSR:     IF    REPUSR
  2227.     LDA    NEWUSR
  2228.     CPI    10        ; If user no. < 10, skip tens digit
  2229.     JC    DUX
  2230.     PUSH    B
  2231.     MVI    C,'0'-1
  2232. ;
  2233. DUY:    INR    C        ; Get tens digit
  2234.     SUI    10
  2235.     JNC    DUY        ; Loop until we've gone too far
  2236.     ADI    10
  2237.     MOV    B,A        ; Save units digit
  2238.     MOV    A,C        ; Print tens digit
  2239.     CALL    TYPE
  2240.     MOV    A,B        ; Get units back
  2241.     POP    B
  2242. ;
  2243. DUX:    ADI    '0'
  2244.     JMP    TYPE
  2245.      ENDIF            ; Repusr
  2246. ;
  2247. ;
  2248. ; Force new line on video and check for page pause
  2249. ;
  2250. CRLF:    MVI    A,CR        ; Send cr
  2251.     CALL    TYPE
  2252.     MVI    A,LF        ; Send lf
  2253.     JMP    TYPE
  2254. ;.....
  2255. ;
  2256. ;
  2257. ; Separate the directory output on a line with a space, the delimiter,
  2258. ; followed by another space.
  2259. ;
  2260. FENCE:    CALL    SPACE
  2261.     LDA    FENC        ; Fence character
  2262. ;
  2263. FPAD:    CALL    TYPE        ; Print it, fall into space
  2264. ;
  2265. SPACE:    MVI    A,' '        ; Fall through to type
  2266. ;
  2267. ;
  2268. ; Output character in A to console, and optionally to printer and/or the
  2269. ; output file.
  2270. ;
  2271. TYPE:    PUSH    B
  2272.     PUSH    D
  2273.     PUSH    H
  2274.     PUSH    PSW        ; Save the character to output
  2275.     CALL    TYPE1        ; Send it to console
  2276.     CALL    CKABRT        ; Check for user abort request
  2277.     POP    PSW        ; Restore the output character
  2278.     ANI    7FH        ; Strip parity bit on character
  2279. ;
  2280. ;
  2281. ; Check if reverse video sequence. If so, do not store the
  2282. ; leadin character or entry/exit characters in SD.DIR
  2283. ;
  2284.      IF    REVIDEO
  2285.     CPI    LEADIN        ; If lead-in for hilite
  2286.     JZ    NOHLT        ; Skip file i/o and printer
  2287.     CPI    INTOREV        ; Reverse start?
  2288.     JZ    CKREV
  2289.     CPI    OUTAREV        ; Reverse end?
  2290.     JNZ    TYSKIP        ; No, skip
  2291. ;
  2292. CKREV:    MOV    B,A        ; Save character
  2293.     LDA    HITRAP        ; Get previous character
  2294.     CPI    LEADIN        ; Was it a leadin?
  2295.     MOV    A,B        ; Restore char
  2296.     JZ    NOHLT        ; Skip file and printer
  2297. ;
  2298. TYSKIP:    STA    HITRAP        ; Save character for hilite trap
  2299.      ENDIF            ; Revideo
  2300. ;
  2301. ;
  2302. ; Test file output mode and skip to page pause test if not active.
  2303. ;
  2304.      IF    FOPT
  2305.     MOV    B,A        ; Save stripped character to b
  2306.     LDA    FOPFLG        ; Is file output active?
  2307.     ORA    A
  2308.     JNZ    NOWRIT        ; Go check for page pause if not
  2309. ;
  2310. ;
  2311. ; File output mode active - make sure we have room in buffer to add the
  2312. ; next character.  If buffer full, write out current record first and
  2313. ; then start a new record with current character.
  2314. ;
  2315.     LHLD    BUFPNT        ; Get current buffer pointer
  2316.     LDA    BUFCNT        ; Get buffer capacity remaining
  2317.     ORA    A
  2318.     JNZ    PUTBUF        ; Continue if buffer not full
  2319.     CALL    SETFOP        ; Set the dma address
  2320.     LXI    D,OUTFCB    ; Otherwise, write the current buffer out
  2321.     MVI    C,WRITE
  2322.     CALL    CPM        ; (note call must save character in b)
  2323.     ORA    A
  2324.     JNZ    WRTERR        ; Write error exit if disk full or r/o
  2325.     LXI    H,OUTBUF    ; Reset buffer pointer
  2326.     MVI    A,128        ; Reset buffer capacity
  2327. ;
  2328. PUTBUF:    MOV    M,B        ; Shove character to next buffer position
  2329.     INX    H        ; Bump buffer pointer
  2330.     SHLD    BUFPNT        ; And save it
  2331.     DCR    A        ; Dock count of characters left in buffer
  2332.     STA    BUFCNT        ; And save it
  2333. ;
  2334. NOWRIT:    MOV    A,B        ; Recall stripped character
  2335.      ENDIF            ; Fopt
  2336. ;
  2337.      IF    POPT        ; If printer option
  2338.     ANI    7FH        ; Strip parity bit on character
  2339.     MOV    E,A        ; Setup list output call
  2340.     MVI    C,5
  2341.     LDA    POPFLG        ; Test printer flag
  2342.     ORA    A
  2343.     CZ    CPM        ; Print character if flag true
  2344.     MOV    A,E        ; Recall character
  2345.      ENDIF            ; Popt
  2346. ;
  2347.      IF    REVIDEO
  2348. NOHLT:    STA    HITRAP        ; Save character for hilite trap
  2349.      ENDIF            ; Revideo
  2350. ;
  2351.      IF    PGPAWS
  2352.     CPI    LF        ; Do we have a lf?
  2353.     JNZ    TYPRET        ; Exit if not
  2354.      ENDIF            ; Pgpaws
  2355. ;
  2356.      IF    NOPT AND PGPAWS
  2357.     LDA    NOPFLG        ; Is the page pause function disabled?
  2358.     ORA    A
  2359.     JZ    TYPRET        ; Exit if so
  2360.      ENDIF            ; Nopt and pgpaws
  2361. ;
  2362.      IF    PGPAWS
  2363.     LDA    LINCNT        ; Get line count
  2364.     INR    A        ; Bump it
  2365.     LXI    H,MLPS
  2366.     CMP    M        ; Are we at the end of the screen?
  2367.     JC    NOTEOS        ; Skip if not
  2368.     LXI    D,EOSMSG    ; Else, display pause message
  2369.     MVI    C,PRINTS    ; Without checking for lfs
  2370.     CALL    BDOS
  2371.     CALL    CINPUT        ; Wait for character
  2372.     CPI    'C'-40H        ; Want to abort?
  2373.     JZ    EXIT1        ; Abort on ctl-c
  2374.     LXI    D,MORERA    ; Wipe the silly '[more]' out
  2375.     MVI    C,PRINTS
  2376.     CALL    BDOS
  2377.     XRA    A        ; Reset line count
  2378. ;
  2379. NOTEOS:    STA    LINCNT        ; Save new line count
  2380.      ENDIF            ; Pbpaws
  2381. ;
  2382. TYPRET:    POP    H        ; Exit from type
  2383.     POP    D
  2384.     POP    B
  2385.     RET
  2386. ;.....
  2387. ;
  2388. ; Output character
  2389. ;
  2390. TYPE1:     IF    VECTOR
  2391.     ORA    A        ; Set sign flag if ms bit is on
  2392.     JP    TYPE2        ; If character is ascii, continue
  2393.     MOV    B,A        ; Else, get character to b
  2394.     MVI    A,5        ; Video driver function for direct output
  2395.     JMP    VIDEO        ; Display in rev video, exit from video
  2396.      ENDIF            ; VECTOR
  2397. ;
  2398. TYPE2:     IF    REVIDEO
  2399.     ORA    A
  2400.     JP    TYPE99
  2401.     PUSH    PSW
  2402.     LDA    MLEADIN        ; Send esc char first
  2403.     CALL    TYPE99
  2404.     LDA    MINTOREV
  2405.     CALL    TYPE99
  2406.      ENDIF            ; REVIDEO
  2407. ;
  2408.      IF    THREBYT        ; 3-byte video?
  2409.     MVI    A,TBYTE        ; If so, add the third byte
  2410.     CALL    TYPE99
  2411.      ENDIF
  2412. ;
  2413.      IF    REVIDEO        ;
  2414.     POP    PSW        ; Retrieve character
  2415.     ANI    7FH
  2416.     CALL    TYPE99
  2417.     LDA    MLEADIN        ; Send esc first
  2418.     CALL    TYPE99
  2419.     LDA    MOUTAREV    ; The out of reverse video character
  2420.      ENDIF            ; REVIDEO
  2421. ;
  2422.      IF    THREBYT        ; 3-byte video?
  2423.     CALL    TYPE99
  2424.     MVI    A,TBYTE        ; If so, add the third byte
  2425.      ENDIF
  2426. ;
  2427. TYPE99:    EQU    $
  2428. ;
  2429. ;
  2430.      IF    DIRCON
  2431.     MOV    C,A        ; Get character into bios entry register
  2432.     LHLD    BASE+1        ; Get page base of bios
  2433.     MVI    L,12        ; Get entry vector to conout
  2434.     JMP    GOHL        ; Call conout direct through the bios
  2435.      ENDIF            ; Dircon
  2436. ;
  2437.      IF    NOT DIRCON
  2438.     MOV    E,A        ; Get character into bdos entry register
  2439.     MVI    C,WRCHR
  2440.     JMP    BDOS        ; Call conout via the bdos
  2441.      ENDIF            ; Not dircon
  2442. ;.....
  2443. ;
  2444. ;
  2445. ; Print a string at HL of length B
  2446. ;
  2447. TYPEIT:    MOV    A,M
  2448.     CALL    TYPE
  2449.     INX    H
  2450.     DCR    B
  2451.     JNZ    TYPEIT
  2452.     RET
  2453. ;.....
  2454. ;
  2455. ;
  2456. ; Print string on the console
  2457. ;
  2458. PRINT:    LDAX    D        ; Get the character from the de string
  2459.     ANI    7FH        ; Strip off any parity
  2460.     ORA    A        ; See if it is a 0
  2461.     RZ            ; Terminates with a 0 character
  2462.     CALL    TYPE        ; Show the character on the console
  2463.     INX    D        ; Next string position
  2464.     JMP    PRINT        ; Go do another
  2465. ;.....
  2466. ;
  2467. ;
  2468. ; Fetch character from console (without echo)
  2469. ;
  2470. CINPUT:    LHLD    BASE+1
  2471.     MVI    L,9
  2472.     CALL    GOHL
  2473.     ANI    7FH        ; Strip off any parity
  2474.     RET
  2475. ;.....
  2476. ;
  2477. ;
  2478. ; Check for a CTRL-C or CTRL-S entered from the keyboard.  Jump to EXIT
  2479. ; if CTRL-C, pause on CTRL-S.
  2480. ;
  2481. CKABRT:    LHLD    BASE+1
  2482.     MVI    L,6        ; Check status of keyboard
  2483.     CALL    GOHL        ; Any key pressed?
  2484.     ORA    A
  2485.     RZ            ; No, return to caller
  2486.     CALL    CINPUT        ; Get character
  2487.     CPI    'C'-40H        ; Ctl-c?
  2488.     JZ    EX0        ; If ctl-c then quit
  2489.     CPI    'S'-40H        ; Ctl-s?
  2490.     RNZ            ; No, return to caller
  2491.     CALL    CINPUT        ; Yes, wait for another char.
  2492.     CPI    'C'-40H        ; Might be ctl-c
  2493.     JZ    EX0        ; If ctl-c, else fall thru and continue
  2494.     RET
  2495. ;.....
  2496. ;
  2497. ;
  2498. ; Routine to do disk reset if D option entered on command line
  2499. ;
  2500. DSET:    MVI    C,RESET
  2501.     CALL    CPM
  2502.     RET
  2503. ;.....
  2504. ;
  2505. ;
  2506. ; Kludge to allow call to address in HL
  2507. ;
  2508. GOHL:    PCHL
  2509. ;
  2510. ; Entry to BDOS saving all extended registers
  2511. ;
  2512. CPM:    PUSH    B
  2513.     PUSH    D
  2514.     PUSH    H
  2515.  
  2516.     LDA    ZRDFLG        ; Zrdos running?
  2517.     ORA    A
  2518.     JNZ    ZRD        ; Zrdos error trap and dos call
  2519.  
  2520.     CALL    BDOS
  2521.     MOV    B,A        ; Save return code
  2522.     LDA    VERFLG        ; Is this 3.0?
  2523.     CPI    30H
  2524.     MOV    A,B
  2525.     JC    CPM20        ; No, exit normally
  2526.     CPI    0FFH        ; It is 3.0 - was return code ff?
  2527.     JNZ    CPM20        ; No, exit normally
  2528.     MOV    A,H        ; 3.0 and a=ff - check for error code
  2529.     ORA    A
  2530.     JNZ    DSKERR        ; Trap out if we got a physical error
  2531.     MOV    A,B        ; Else continue normally
  2532. ;
  2533. CPM20:    POP    H
  2534.     POP    D
  2535.     POP    B
  2536.     RET
  2537. ;
  2538. ; ZRDOS Error Trap and System Call exits to CPM20
  2539. ;
  2540. ZRD:    CALL    SETTRAP        ; Set the warm boot trap
  2541.     CALL    BDOS        ; Do what we're told
  2542.     CALL    RESTRAP        ; Reset the trap
  2543.     JMP    CPM20        ; Error free exit.
  2544. ;
  2545. ; Set Warm Boot Trap in ZRDOS
  2546. ;
  2547. SETTRAP:
  2548.     PUSH    H
  2549.     PUSH    D
  2550.     PUSH    B
  2551.     MVI    C,SETWBT    ; Set warm boot trap to come..
  2552.     LXI    D,WBTRAP    ; Here.
  2553.     CALL    BDOS
  2554.     POP    B
  2555.     POP    D
  2556.     POP    H
  2557.     RET
  2558. ;
  2559. ; WBTRAP is where the ZRDOS returns control on warm boot (error)
  2560. ;
  2561. WBTRAP:    LXI    H,DSKERR    ; After re-setting the trap, return here.
  2562.     PUSH    H        ; Save DSKERR on stack.
  2563. ;
  2564. ; Reset Warm Boot Trap in ZRDOS
  2565. ;
  2566. RESTRAP:PUSH    H
  2567.     PUSH    D
  2568.     PUSH    B
  2569.     PUSH    PSW
  2570.     MVI    C,RESWBT    ; Reset warm boot trap
  2571.     CALL    BDOS
  2572.     POP    PSW
  2573.     POP    B
  2574.     POP    D
  2575.     POP    H
  2576.     RET
  2577. ;.....
  2578. ;
  2579. ;
  2580. ; For file output mode, return to old user area and set DMA for the file
  2581. ; output buffer.
  2582. ;
  2583. SETFOP:     IF    UOPT OR    AOPT
  2584.     CALL    CKVER        ; Clear carry if cp/m 2 or later
  2585.     LDA    OLDUSR        ; Get user number at startup
  2586.     MOV    E,A
  2587.     MVI    C,CURUSR
  2588.     CNC    CPM        ; Reset the old user number if cp/m 2
  2589.      ENDIF            ; Upot or aopt
  2590. ;
  2591.      IF    FOPT
  2592.     LXI    D,OUTBUF    ; Move dma from search buffer into the
  2593.     JMP    SET2        ; Output buffer
  2594.      ENDIF            ; Fopt
  2595. ;
  2596.     RET
  2597. ;.....
  2598. ;
  2599. ;
  2600. ; Move disk buffer DMA to default buffer for directory search operations
  2601. ; and BDOS media change routines (necessary for pre-CP/M 2 systems while
  2602. ; in file output mode with an active buffer).
  2603. ;
  2604. SETSRC:    LXI    D,BASE+80H
  2605. ;
  2606. SET2:    MVI    C,SETDMA
  2607.     JMP    CPM
  2608. ;.....
  2609. ;
  2610. ;
  2611. ; Print the amount of free space remaining on the selected drive
  2612. ;
  2613. PRTFRE:    LXI    D,TOTMS7    ; Print " ( "
  2614.     CALL    PRINT
  2615.     LHLD    FREEBY
  2616.     CALL    DECPRT        ; Print k free
  2617.     LXI    D,TOTMS8    ; Print " K FREE) "
  2618.     JMP    PRINT
  2619. ;.....
  2620. ;
  2621. ;
  2622. ; Compare routine for sort
  2623. ;
  2624. COMPR:    PUSH    H        ; Save table addr
  2625.     MOV    E,M        ; Load low order
  2626.     INX    H
  2627.     MOV    D,M        ; Load high order
  2628.     INX    H
  2629.     MOV    C,M
  2630.     INX    H
  2631.     MOV    B,M
  2632. ;
  2633. ;
  2634. ; BC, DE now point to entries to be compared
  2635. ;
  2636.     XCHG
  2637.     MOV    E,A        ; Get count
  2638. ;
  2639. CMPLP:    MOV    A,M
  2640.     ANI    7FH
  2641.     MOV    D,A
  2642.     LDAX    B
  2643.     ANI    7FH
  2644.     CMP    D
  2645.     INX    H
  2646.     INX    B
  2647.     JNZ    NOTEQL        ; Quit on mismatch
  2648.     DCR    E        ; Or end of count
  2649.     JNZ    CMPLP
  2650. ;
  2651. NOTEQL:    POP    H
  2652.     RET            ; Cond code tells all
  2653. ;.....
  2654. ;
  2655. ;
  2656. ; Swap entries in the order table
  2657. ;
  2658. SWAP:    LXI    B,ORDER-2    ; Table base
  2659.     DAD    H        ; *2
  2660.     DAD    B        ; + base
  2661.     XCHG
  2662.     DAD    H        ; *2
  2663.     DAD    B        ; + base
  2664.     MOV    C,M
  2665.     LDAX    D
  2666.     XCHG
  2667.     MOV    M,C
  2668.     STAX    D
  2669.     INX    H
  2670.     INX    D
  2671.     MOV    C,M
  2672.     LDAX    D
  2673.     XCHG
  2674.     MOV    M,C
  2675.     STAX    D
  2676.     RET
  2677. ;.....
  2678. ;
  2679. ;
  2680. ; New compare routine
  2681. ;
  2682. COMPARE:LXI    B,ORDER-2
  2683.     DAD    H
  2684.     DAD    B
  2685.     XCHG
  2686.     DAD    H
  2687.     DAD    B
  2688.     XCHG
  2689.     MOV    C,M
  2690.     INX    H
  2691.     MOV    B,M
  2692.     XCHG
  2693.     MOV    E,M
  2694.     INX    H
  2695.     MOV    D,M
  2696.     XCHG
  2697.     MOV    E,A        ; Count
  2698. ;
  2699. CMPLPE:    MOV    A,M
  2700.     ANI    7FH
  2701.     MOV    D,A
  2702.     LDAX    B
  2703.     ANI    7FH
  2704.     CMP    D
  2705.     INX    B
  2706.     INX    H
  2707.     RNZ
  2708.     DCR    E
  2709.     JNZ    CMPLPE
  2710.     RET
  2711. ;.....
  2712. ;
  2713. ;
  2714. ; Error exit
  2715. ;
  2716. ERXIT:     IF    FOPT
  2717.     MVI    A,0FFH
  2718.     STA    FOPFLG        ; Disable file output mode on error
  2719.      ENDIF            ; Fopt
  2720. ;
  2721.     CALL    CRLF        ; Space down
  2722.     POP    D        ; Get pointer to message string
  2723.     CALL    PRINT        ; Print it
  2724.     LXI    D,ERRMS1    ; Print " Error"
  2725.     CALL    PRINT
  2726.     CALL    CRLF        ; Space down
  2727. ;
  2728. ;
  2729. ; Exit - all done, restore stack
  2730. ;
  2731. EXIT:     IF    DOPT        ; If multi-disk option enabled
  2732.     LDA    DOPFLG        ; If multi-disk not selected - skip next
  2733.     ORA    A
  2734.     JNZ    EX0
  2735.     CALL    CKABRT        ; Check for user abort first
  2736.     MVI    A,HIDRV-LODRV    ; Get maximum drive code to search
  2737.     LXI    H,FCB        ; Bump directory fcb drive code
  2738.     INR    M
  2739.     CMP    M        ; Does next disk exceed maximum?
  2740.     JC    EX0
  2741.      ENDIF            ; Dopt
  2742. ;
  2743.      IF    MAXDR AND DOPT
  2744.     LDA    MAXD        ; Look at another value limit
  2745.     INR    A
  2746.     CMP    M        ; Is it lower?
  2747.     JC    EX0        ; Bail out if too low
  2748.     JMP    NOOPT        ; Search next disk
  2749.      ENDIF            ; Maxdr and dopt
  2750. ;
  2751.      IF    DOPT
  2752.     JNC    NOOPT        ; Search next disk if maxdr not true
  2753.      ENDIF            ; Dopt
  2754. ;
  2755. EX0:     IF    VCODE
  2756.     CALL    CRLF        ; Turn up a blank line at end
  2757.      ENDIF            ; Vcode
  2758.  
  2759.     MVI    C,CONST        ; Check console status
  2760.     CALL    CPM
  2761.     ORA    A        ; Character waiting?
  2762.     MVI    C,RDCHR
  2763.     CNZ    CPM        ; Gobble up character
  2764. ;
  2765.      IF    DOPT        ; Restore bdos intercept vectors
  2766.  
  2767.     LDA    ZRDFLG        ; Zrdos running?
  2768.     ORA    A
  2769.     JNZ    EXIT1        ; Yes.
  2770.  
  2771.     LDA    VERFLG        ; Or error mode, depending on version
  2772.     CPI    30H
  2773.     JC    EXIT0
  2774.     MVI    C,45
  2775.     MVI    E,0        ; Set error mode back to default
  2776.     CALL    CPM
  2777.     JMP    EXIT1
  2778. ;
  2779. EXIT0:    LDA    DOPFLG        ; If they were swapped
  2780.     ORA    A
  2781.     CZ    SWAPEM
  2782.      ENDIF            ; Dopt
  2783. ;
  2784. EXIT1:     IF    ROPT
  2785.     LDA    ROPFLG        ; If disk system was reset
  2786.     ORA    A
  2787.     LDA    OLDDSK        ; Get default disk at startup
  2788.     MOV    E,A
  2789.     MVI    C,SELDSK    ; Reselect it
  2790.     CZ    CPM
  2791.      ENDIF            ; Ropt
  2792. ;
  2793.     LHLD    STACK        ; Get old stack pointer
  2794.     SPHL            ; Move back to old stack
  2795.     RET            ; And return to ccp
  2796. ;.....
  2797. ;
  2798. ;
  2799. ; Trap BDOS select and sector error vectors to our own intercept routine
  2800. ; so we can catch a reference to an illegal drive.
  2801.  
  2802.      IF    DOPT
  2803. SWAPEM:
  2804.     LDA    ZRDFLG        ; See if zrdos running
  2805.     ORA    A
  2806.     RNZ            ; Yes. quit this.
  2807.  
  2808.     LDA    VERFLG        ; Check version
  2809.     CPI    30H        ; See if error mode call is available
  2810.     JC    SWAP20        ; If not, use bdos error vectors
  2811.     MVI    C,45
  2812.     MVI    E,0FFH        ; Use set error mode call
  2813.     CALL    CPM        ; Set "return code only" mode
  2814.     RET
  2815. ;.....
  2816. ;
  2817. ;
  2818. SWAP20:    LHLD    BDOS+1        ; Get pointer to base of bdos
  2819.      ENDIF            ; Dopt
  2820. ;
  2821.      IF    DOPT AND LOWCCP
  2822.     LDA    BDOSPG        ; Get "proper" bdos page
  2823.     MOV    E,A        ; Save it in "E"
  2824.     MOV    A,H        ; Get location of bdos
  2825.     CMP    E        ; Is it where bdos normally is?
  2826.     JZ    BDCHK2        ; Yes, but perform 2nd check to be sure
  2827.     INX    H        ; Swap in the new pointer if running a
  2828.     MOV    E,M        ; Program below the ccp
  2829.     INX    H
  2830.     MOV    D,M
  2831.     XCHG            ; Now hl points to the proper vector
  2832.     JMP    SWAPOK        ; Bypass second check
  2833.      ENDIF            ; Dopt and lowccp
  2834. ;
  2835.      IF    DOPT
  2836. BDCHK2:    MOV    A,L
  2837.     SUI    6        ; Check if pointing directly to bdos
  2838.     JZ    SWAPOK        ; Continue if true
  2839.     MVI    A,'D'        ; Undo option request for multi-disk
  2840.     STA    DOPFLG
  2841. ;
  2842. SWAPOK:    MVI    L,9        ; Point to sector error vector
  2843.     LXI    D,VECTBL    ; Exchanging with our own vector table
  2844.     MVI    A,4        ; 4 bytes to swap
  2845. ;
  2846. SWAPLP:    MOV    B,M        ; Get byte from hl
  2847.     XCHG
  2848.     MOV    C,M        ; Get byte from de
  2849.     MOV    M,B        ; Put byte from hl
  2850.     XCHG
  2851.     MOV    M,C        ; Put byte from de
  2852.     INX    H        ; Bump exchange pointers
  2853.     INX    D
  2854.     DCR    A        ; Dock counter
  2855.     JNZ    SWAPLP        ; Continue swapping til done
  2856.     RET
  2857.      ENDIF            ; Dopt
  2858. ;.....
  2859. ;
  2860. ;
  2861. ; Check CP/M version number.  Return carry flag set if pre-CP/M 2.  If
  2862. ; CP/M 2 or later or MP/M (any version), return carry clear.
  2863. ;
  2864. CKVER:    LDA    VERFLG
  2865.     CPI    20H
  2866.     RET
  2867. ;.....
  2868. ;
  2869. ;
  2870. ; Recovery point from intercepted BDOS select and bad sector errors.
  2871. ;
  2872. DSKERR:     IF    DOPT
  2873.     LXI    SP,STACK    ; Get out of bdos' stack
  2874.     JMP    EXIT        ; And exit back to ccp
  2875.      ENDIF            ; Dopt
  2876. ;
  2877. ;-----------------------------------------------------------------------
  2878. ;            start of FNAME routine
  2879. ; FNAME module
  2880. ;
  2881.      IF    DUOPT
  2882. MAXDISK    EQU    16        ; Maximum number of disks
  2883. MAXUSER    EQU    31        ; Maximum user number
  2884. ;
  2885. ;  MAIN MODULE
  2886. ;    ON ENTRY, DE PTS TO FCB TO BE FILLED AND HL PTS TO FIRST BYTE OF
  2887. ;        TARGET STRING; FCB IS 36 BYTES LONG
  2888. ;    ON EXIT, B=DISK NUMBER (1 FOR A, ETC) AND C=USER NUMBER
  2889. ;        HL PTS TO TERMINATING CHAR
  2890. ;        A=0 AND Z SET IF ERROR IN DISK OR USER NUMBERS,
  2891. ;        A=0FFH AND NZ
  2892. ;    IF OK
  2893. ;
  2894. FNAME:    PUSH    D        ; Save de
  2895.     MVI    A,0FFH        ; Set default disk and user
  2896.     STA    DISK
  2897.     STA    USER
  2898.     MVI    B,36        ; Initialize fcb
  2899.     PUSH    D        ; Save pointer
  2900.     XRA    A        ; A=0
  2901. ;
  2902. FNINI:    STAX    D        ; Store zero
  2903.     INX    D        ; Point to next
  2904.     DCR    B        ; Count down
  2905.     JNZ    FNINI
  2906.     POP    D        ; Get pointer back
  2907. ;
  2908. ;
  2909. ; Scan for colon in string
  2910. ;
  2911.     PUSH    H        ; Save pointer
  2912. ;
  2913. COLON:    MOV    A,M        ; Scan fora colon or space
  2914.     INX    H        ; Point to next
  2915.     CPI    ':'        ; Colon found?
  2916.     JZ    COLON1
  2917.     CPI    ','        ; Comma found?
  2918.     JZ    GETF1
  2919.     CPI    ' '+1        ; Delimiter?
  2920.     JC    GETF1
  2921.     JMP    COLON        ; Continue if not end of line
  2922. ;
  2923. COLON1:    POP    H        ; Clear stack
  2924.     MOV    A,M        ; Save possible drive specification
  2925.     CALL    CAPS        ; Capitalize
  2926.     CPI    'A'        ; Digit if less than 'a'
  2927.     JC    USERCK        ; Process user number
  2928.     SUI    'A'        ; Convert to 0-31
  2929.     CPI    MAXDISK        ; Within bounds?
  2930.     JC    SVDISK
  2931. ;
  2932. ERREXIT:XRA    A        ; Error indicator
  2933.     POP    D        ; Restore 'de'
  2934.     RET
  2935. ;...
  2936. ;
  2937. ;
  2938. ; Log in specified disk
  2939. ;
  2940. SVDISK:    INR    A        ; Adjust to 1 for 'a'
  2941.     STA    DISK        ; Save flag
  2942.     INX    H        ; Point to next character
  2943. ;
  2944. ;
  2945. ; Check for user
  2946. ;
  2947. USERCK:    MOV    A,M        ; Get possible user number
  2948.     CPI    ':'        ; No user number
  2949.     JZ    GETFILE
  2950.     CPI    '?'        ; All user numbers?
  2951.     JNZ    USERC1
  2952.     STA    USER        ; Set value
  2953.     INX    H        ; Point to after
  2954.     MOV    A,M        ; Must be colon
  2955.     CPI    ':'
  2956.     JZ    GETFILE
  2957.     JMP    ERREXIT        ; Fatal error if not colon after ?
  2958. ;
  2959. USERC1:    XRA    A        ; Zero user number
  2960.     MOV    B,A        ; 'b' = accumulator for user number
  2961. ;
  2962. USRLOOP:MOV    A,M        ; Get digit
  2963.     INX    H        ; Point to next
  2964.     CPI    ':'        ; Done?
  2965.     JZ    USRDN
  2966.     SUI    '0'        ; Convert to binary
  2967.     JC    ERREXIT        ; User number error?
  2968.     CPI    10
  2969.     JNC    ERREXIT
  2970.     MOV    C,A        ; Next digit in 'c'
  2971.     MOV    A,B        ; Old number in 'a'
  2972.     ADD    A        ; *2
  2973.     ADD    A        ; *4
  2974.     ADD    B        ; *5
  2975.     ADD    A        ; *10
  2976.     ADD    C        ; *10+new digit
  2977.     MOV    B,A        ; Result in 'b'
  2978.     JMP    USRLOOP
  2979. ;
  2980. USRDN:    MOV    A,B        ; Get nuer user number
  2981.     CPI    MAXUSER+1    ; Within range?
  2982.     JNC    ERREXIT
  2983.     STA    USER        ; Save in flag
  2984.     JMP    GETFILE
  2985. ;
  2986. ;
  2987. ; Extract file name
  2988. ;
  2989. GETF1:    POP    H        ; Get pointer to byte
  2990. ;
  2991. GETFILE:MOV    A,M        ; Pointing to colon?
  2992.     CPI    ':'
  2993.     JNZ    GFILE1
  2994.     INX    H        ; Skip over colon
  2995. ;
  2996. GFILE1:    MOV    A,M        ; Get next character
  2997.     CPI    ','        ; Delimiter?
  2998.     JZ    GFQUES
  2999.     CPI    ' '+1        ; Not a delimiter?
  3000.     JNC    GFILE2
  3001. ;
  3002. GFQUES:    INX    D        ; Fill with ???
  3003.     MVI    B,11        ; 11 bytes
  3004.     MVI    A,'?'
  3005. ;
  3006. GFFILL:    STAX    D        ; Put?
  3007.     INX    D        ; Point to next
  3008.     DCR    B        ; Count down
  3009.     JNZ    GFFILL
  3010. ;
  3011. FNDONE:    LDA    DISK        ; Get disk number
  3012.     MOV    B,A        ; In 'b'
  3013.     LDA    USER        ; Get user number
  3014.     MOV    C,A        ; In 'c'
  3015.     POP    D        ; Restore registers
  3016.     MVI    A,0FFH        ; No error
  3017.     ORA    A        ; Set flags
  3018.     RET
  3019. ;.....
  3020. ;
  3021. ;
  3022. ; Get file name fields
  3023. ;
  3024. GFILE2:    MVI    B,8        ; At most, 8 bytes for filename
  3025.     CALL    SCANF        ; Scan and fill
  3026.     MVI    B,3        ; At most, 3 bytes for filetype
  3027.     MOV    A,M        ; Get delimiter
  3028.     CPI    '.'        ; Filename ending in '.'?
  3029.     JNZ    GFILE3
  3030.     INX    H        ; Point to character after '.'
  3031.     CALL    SCANF        ; Scan and fill
  3032.     JMP    FNDONE        ; Done...return to 'args'
  3033. ;...
  3034. ;
  3035. ;
  3036. GFILE3:    CALL    SCANF4        ; Fill with spaces
  3037.     JMP    FNDONE
  3038. ;.....
  3039. ;
  3040. ;
  3041. ; Scanner routine
  3042. ;
  3043. SCANF:    CALL    DELCK        ; Check for delimiter
  3044.     JZ    SCANF4        ; Fill with spaces if found
  3045.     INX    D        ; Point to next byte in filename
  3046.     CPI    '*'        ; Question mark fill ?
  3047.     JNZ    SCANF1
  3048.     MVI    A,'?'        ; Place '?'
  3049.     STAX    D
  3050.     JMP    SCANF2
  3051. ;
  3052. SCANF1:    STAX    D        ; Place character
  3053.     INX    H        ; Point to next position
  3054. ;
  3055. SCANF2:    DCR    B        ; Count down
  3056.     JNZ    SCANF        ; Continue loop
  3057. ;
  3058. SCANF3:    CALL    DELCK        ; "b" chars or more - skip to delimiter
  3059.     RZ
  3060.     INX    H        ; Point to next
  3061.     JMP    SCANF3
  3062. ;
  3063. SCANF4:    INX    D        ; Point to next filename or filetype
  3064.     MVI    A,' '        ; Fill with spaces
  3065.     STAX    D
  3066.     DCR    B        ; Count down
  3067.     JNZ    SCANF4
  3068.     RET
  3069. ;.....
  3070. ;
  3071. ;
  3072. ; Buffers
  3073. ;
  3074. DISK:    DB    0        ; Disk number
  3075. USER:    DB    0        ; User number
  3076. ;
  3077. ;
  3078. ; Check character pointed to by 'HL' for a delimiter, return with Zero
  3079. ; flage set if the character is a delimiter
  3080. ;
  3081. DELCK:    MOV    A,M        ; Get the character
  3082.     CALL    CAPS        ; Capitalize
  3083.     ORA    A        ; 0=delimiter
  3084.     RZ
  3085.     CPI    ' '+1        ; Space character+1
  3086.     JC    DELCK1        ; Space character or less
  3087.     CPI    '='
  3088.     RZ
  3089.     CPI    5FH        ; Underscore
  3090.     RZ
  3091.     CPI    '.'
  3092.     RZ
  3093.     CPI    ':'
  3094.     RZ
  3095.     CPI    ';'
  3096.     RZ
  3097.     CPI    ','
  3098.     RZ
  3099.     CPI    '<'
  3100.     RZ
  3101.     CPI    '>'
  3102.     RET
  3103. ;...
  3104. ;
  3105. ;
  3106. DELCK1:    CMP    M        ; Compare with self for ok
  3107.     RET
  3108. ;...
  3109. ;
  3110. ;
  3111. CAPS:    CPI    'a'
  3112.     RC
  3113.     CPI    'z'+1
  3114.     RNC
  3115.     SUI    20H
  3116.     RET
  3117.      ENDIF            ; Duopt
  3118. ;.....
  3119. ;            end of FNAME routine
  3120. ;
  3121. ;=======================================================================
  3122. ;
  3123. ;         SUBROUTINES to read library file directory
  3124. ;
  3125. ;=======================================================================
  3126. ;            start of LOPT routine
  3127. ;
  3128.      IF    LOPT
  3129. PRTLMEM:LXI    H,ORDER        ; Initialize order table pointer
  3130.     SHLD    NEXTL
  3131.     XRA    A
  3132.     STA    LNCNT
  3133. ;
  3134. ENTRYL:    LHLD    LCOUNT        ; Get fcb count
  3135.     DCX    H        ; Decrement it
  3136.     SHLD    LCOUNT
  3137.     MOV    A,H        ; Is this the last file?
  3138.     ORA    L
  3139.     JZ    LBRTST        ; If count=0, last file skip compare
  3140.     PUSH    B
  3141.     CALL    CKABRT        ; Check for abort code from keyboard
  3142.     LHLD    NEXTL
  3143.     MVI    A,11
  3144.     CALL    COMPR        ; Does this entry match next one?
  3145.     POP    B
  3146.     JNZ    LBRTST        ; No, print it
  3147.     INX    H
  3148.     INX    H        ; Skip, highest extent comes last in list
  3149.     SHLD    NEXTL
  3150.     JMP    ENTRYL        ; Loop back for next lowest extent
  3151. ;
  3152. ;
  3153. ; Exit Library member printing
  3154. ;
  3155. LBEXIT:    LHLD    LMTOTL
  3156.     MOV    A,H
  3157.     ORA    L
  3158.     RZ
  3159.     PUSH    H        ; Save member count
  3160.     XRA    A        ; Get a zero to...
  3161.     STA    SUPSPC        ; Suppress leading spaces in totals
  3162.     LXI    H,MNPL        ; If last line is full, don't turn
  3163.     LDA    LNCNT        ; Up extra line
  3164.     CMP    M
  3165.     CNZ    CRLF        ; If partial line, extra line needed
  3166.      ENDIF            ; Lopt
  3167. ;
  3168.      IF    PRBRDR AND LOPT
  3169.     CALL    BDRCH2
  3170.     LXI    D,CONTM1    ; Print "There are "
  3171.      ENDIF            ; Prbrdr and lopt
  3172. ;
  3173.      IF    NOT PRBRDR AND LOPT
  3174.     LXI    D,CONTM2
  3175.      ENDIF            ; Not prbrdr and lopt
  3176. ;
  3177.      IF    LOPT
  3178.     CALL    PRINT
  3179.     POP    H        ; Get total member count back
  3180.     CALL    DECPRT
  3181.     LXI    D,MFILES    ; Print "Members in "
  3182.     CALL    PRINT
  3183.     LHLD    LBTOTL
  3184.     CALL    DECPRT
  3185.     LXI    D,LIBR
  3186.     JMP    PRINT
  3187. ;.....
  3188. ;
  3189. ;
  3190. ; Valid entry obtained - spit it out.
  3191. ;
  3192. LBRTST:    LHLD    NEXTL        ; Get order table pointer
  3193.     MOV    E,M        ; Get low order address
  3194.     INX    H
  3195.     MOV    D,M        ; Get high order address
  3196.     INX    H
  3197.     SHLD    NEXTL        ; Save updated table pointer
  3198.     LXI    H,8
  3199.     DAD    D
  3200.     CALL    CKLBR
  3201.     JNZ    LBRNEX
  3202.     PUSH    D
  3203.     LXI    H,MNPL
  3204.     LDA    LNCNT        ; Old code here
  3205.     CMP    M
  3206.     CNZ    CRLF
  3207.     PUSH    PSW        ; Just in case
  3208.     LDA    MNPL        ; Load a with # of names per line
  3209.     CPI    4        ; Is it 4?
  3210.     JZ    LBMS        ; If so then jump to long lbr message
  3211.     CPI    3        ; Is it 3?
  3212.     JZ    LBMS        ; If so then jump to long lbr message
  3213.      ENDIF            ; Lopt
  3214. ;
  3215.      IF    PRBRDR AND LOPT
  3216.     LXI    D,LFMSP3    ; Set up short "LBR members" message
  3217.      ENDIF            ; Prbrdr and lopt
  3218. ;
  3219.      IF    NOT PRBRDR AND LOPT
  3220.     LXI    D,LFMSP4
  3221.      ENDIF            ; Not prbrdr and lopt
  3222. ;
  3223.      IF    LOPT
  3224.     CALL    PRINT        ; Print it
  3225.     JMP    SKLBMS        ; Skip past long message
  3226.      ENDIF            ; Lopt
  3227. ;
  3228. LBMS:     IF    PRBRDR AND LOPT
  3229.     LXI    D,LFMSP1    ; Set up long "Library directory" message
  3230.      ENDIF            ; Prbrdr and lopt
  3231. ;
  3232.      IF    NOT PRBRDR AND LOPT
  3233.     LXI    D,LFMSP2
  3234.      ENDIF            ; Not prbrdr and lopt
  3235. ;
  3236.      IF    LOPT
  3237.     CALL    PRINT        ; Print it
  3238. ;
  3239. SKLBMS:    POP    PSW        ; Put it back
  3240.     LDA    FCB        ; Get current drive
  3241.     ADI    'A'-1        ; Convert to ascii
  3242.     CALL    TYPE        ; Print it
  3243.      ENDIF            ; Lopt
  3244. ;
  3245.      IF    REPUSR AND LOPT
  3246.     CALL    TYPUSR        ; Print user # after it
  3247.      ENDIF            ; Repusr and lopt
  3248. ;
  3249.      IF    LOPT
  3250.     MVI    A,':'        ; And colon
  3251.     CALL    TYPE
  3252.     POP    H
  3253.     PUSH    H
  3254.     MVI    B,8        ; File name length
  3255.     CALL    TYPEIT
  3256.     MVI    A,'.'        ; Period after fn
  3257.     CALL    TYPE
  3258.     MVI    B,3        ; Display 3 characters of filetype
  3259.     CALL    TYPEIT
  3260.     CALL    DOIT        ; Compute size of library in k
  3261.     XCHG
  3262.     CALL    DECPRT
  3263.     MVI    A,'k'
  3264.     CALL    TYPE
  3265.     CALL    CRLF
  3266.     POP    H
  3267. ;
  3268. ;
  3269. ; Saves the library file name into LBRFCB
  3270. ;
  3271.     LDA    FCB
  3272.     LXI    D,LBRFCB    ; To
  3273.     STAX    D
  3274.     INX    D
  3275.     MVI    B,11        ; Len
  3276.     CALL    MOVE        ; Do the move
  3277.     XCHG
  3278.     MVI    B,25
  3279. ;
  3280. CLMFCB:    MVI    M,0
  3281.     INX    H
  3282.     DCR    B
  3283.     JNZ    CLMFCB
  3284.     CALL    SETLDMA
  3285.     LXI    D,LBRFCB    ; Point to file
  3286.     MVI    C,OPEN        ; Get function
  3287.     CALL    CPM        ; Open it
  3288.     MVI    C,READ
  3289.     LXI    D,LBRFCB
  3290.     CALL    CPM
  3291.     CALL    SETFOP
  3292.     LXI    H,LBBUF
  3293.     MOV    A,M
  3294.     ORA    A
  3295.     JZ    CKLDIR        ; Check directory present?
  3296. ;
  3297. BADLBR:    LXI    H,NLBRF
  3298.     MVI    B,25
  3299.     CALL    TYPEIT
  3300. ;
  3301. LMLEXI:    CALL    LBCLOSE
  3302. ;
  3303. ;
  3304. ; Do next library file
  3305. ;
  3306. LBRNEX:    LHLD    LCOUNT        ; Check count
  3307.     MOV    A,H
  3308.     ORA    L
  3309.     JZ    LBEXIT        ; No more, all done
  3310.     JMP    ENTRYL        ; Else, get next .lbr file
  3311. ;
  3312. NLBRF:    DB    '++ Not a LIBRARY file ++',CR,LF
  3313. ;
  3314. ;
  3315. ; Close the library file
  3316. ;
  3317. LBCLOSE:LXI    D,LBRFCB
  3318.     MVI    C,CLOSE
  3319.     CALL    CPM
  3320.     RET
  3321. ;.....
  3322. ;
  3323. ;
  3324. ; Set the Library file DMA adderss
  3325. ;
  3326. SETLDMA:CALL    CKVER        ; Set carry if pre-cp/m 2
  3327.     LDA    NEWUSR        ; Get user area for directory
  3328.     MOV    E,A
  3329.     MVI    C,CURUSR    ; Get the user function
  3330.     CNC    CPM        ; And set new user number if cp/m 2
  3331.     LXI    D,LBBUF
  3332.     MVI    C,SETDMA
  3333.     CALL    CPM
  3334.     RET
  3335. ;.....
  3336. ;
  3337. ;
  3338. ; Check to see if there indeed is a LBR file directory and barf if not!
  3339. ;
  3340. CKLDIR:    MVI    B,11        ; Length of file name
  3341.     MVI    A,' '        ; Space
  3342.     INX    H
  3343. ;
  3344. CKDLP:    CMP    M
  3345.     JNZ    BADLBR
  3346.     DCR    B
  3347.     INX    H
  3348.     JNZ    CKDLP
  3349. ;
  3350. ;
  3351. ; The first entry in the LBR directory is indeed blank.  Now see if the
  3352. ; directory size is >0
  3353. ;
  3354.     MOV    E,M        ; File starting location low
  3355.     INX    H        ; Must be zero here
  3356.     MOV    A,M        ; File starting location high
  3357.     ORA    E        ; Must be zero here also
  3358.     JNZ    BADLBR
  3359.     INX    H
  3360.     MOV    E,M        ; Get library size low
  3361.     INX    H        ; Point to library size high
  3362.     MOV    D,M        ; Get library size high
  3363.     MOV    A,D
  3364.     ORA    E        ; Library must have some size
  3365.     JZ    BADLBR
  3366.     DCX    D
  3367.     XCHG
  3368.     SHLD    SLFILE
  3369.     LHLD    LBTOTL
  3370.     INX    H
  3371.     SHLD    LBTOTL
  3372.     LDA    MNPL
  3373.     STA    LNCNT        ; Reset names per line counter
  3374.     MVI    B,3
  3375.     LXI    H,17
  3376.     DAD    D
  3377.     JMP    LMTEST
  3378. ;
  3379. LFMLOP:    LHLD    SLFILE        ; Get
  3380.     MOV    A,L
  3381.     ORA    H
  3382.     JZ    LMLEXI
  3383.     DCX    H
  3384.     SHLD    SLFILE
  3385.     CALL    SETLDMA
  3386.     MVI    C,READ
  3387.     LXI    D,LBRFCB
  3388.     CALL    CPM
  3389.     CALL    SETFOP
  3390.     MVI    B,4        ; Get file count per sector
  3391.     LXI    H,LBBUF        ; Get buffer starting address
  3392. ;
  3393. LMTEST:    MOV    A,M        ; Get member open flag
  3394.     ORA    A        ; Test for open
  3395.     JZ    PRMNAM
  3396. ;
  3397. LMTESA:    LXI    D,32        ; Member not open get offset
  3398.     DAD    D        ; To next and add it in.
  3399.     DCR    B        ; Is buffer empty ?
  3400.     JNZ    LMTEST        ; No so test next entry
  3401.     JMP    LFMLOP        ; Yes get next buffer...
  3402. ;
  3403. PRMNAM:    PUSH    H        ; Print member name and size
  3404.     PUSH    B
  3405.     CALL    CKABRT        ; Check for abort code from keyboard
  3406.     LXI    H,LNCNT
  3407.     LDA    MNPL
  3408.     CMP    M
  3409.     JNZ    PRMNA1
  3410.      ENDIF            ; Lopt
  3411. ;
  3412.      IF    PRBRDR AND LOPT
  3413.     MVI    A,'*'        ; Load a reg with border character
  3414.     CALL    TYPE        ; Print it
  3415.     MVI    A,' '        ;
  3416.     CALL    TYPE        ; Print space between border & text
  3417.      ENDIF            ; Prbrdr and lopt
  3418. ;
  3419.      IF    PRDI AND PRLIBD    AND LOPT
  3420.     LDA    LBRFCB        ; Precede new line with drive name
  3421.     ADI    'A'-1
  3422.     CALL    TYPE
  3423.      ENDIF            ; Prdi and prlibd and lopt
  3424.  
  3425. ;
  3426.      IF    (PRDI AND PRLIBD) AND (REPUSR AND PRUS)    AND LOPT
  3427.     CALL    CKVER        ; Under cp/m 2, output the user number
  3428.     CNC    TYPUSR        ; Too
  3429.      ENDIF            ; (prdi and prlibd) and (repusr and prus) and lopt
  3430. ;
  3431.      IF    PRDI AND PRLIBD    AND LOPT
  3432.     MVI    A,':'        ; Tag header with a colon and a space
  3433.     CALL    FPAD        ; And exit back to entry
  3434.      ENDIF            ; Prdi and prlibd and lopt
  3435. ;
  3436.      IF    LOPT
  3437. PRMNA1:    POP    B
  3438.     POP    H
  3439.     PUSH    H
  3440.     PUSH    B
  3441.     INX    H
  3442.     MVI    B,8        ; File name length
  3443.     CALL    TYPEIT
  3444.     MVI    A,'.'        ; Period after fn
  3445.     CALL    TYPE
  3446.     MVI    B,3        ; Display 3 characters of filetype
  3447.     CALL    TYPEIT
  3448.     INX    H
  3449.     INX    H
  3450.     MOV    E,M
  3451.     INX    H
  3452.     MOV    D,M
  3453.     XCHG
  3454. ;
  3455. ;
  3456. ; Output the size of the individual file.
  3457. ;
  3458.     PUSH    D
  3459.     PUSH    H
  3460.     PUSH    H
  3461.     LHLD    LLENLOC
  3462.     PUSH    H
  3463.     POP    D
  3464.     POP    H
  3465.     DAD    D
  3466.     SHLD    LLENLOC
  3467.     POP    H
  3468. ;
  3469. ;
  3470. ; New code added to convert lib members from sectors to 'k'
  3471. ;
  3472. ; Upon entry member's size in sectors is in HL
  3473. ;
  3474. ; Begin "0K" library bug fix here.  The problem was a single byte add
  3475. ; when a double byte add was required.
  3476.  
  3477.     LXI    D,7        ; Round up to nearest 1k
  3478.     DAD    D
  3479.     XCHG
  3480.     LXI    H,0
  3481.     MOV    A,E        ; Put low byte of sector count in a
  3482. ;
  3483.     RRC
  3484.     RRC
  3485.     RRC
  3486.     ANI    1FH
  3487.     MOV    E,A        ; And put it back
  3488.     MOV    L,D        ; Get the high byte if any
  3489.     MVI    D,0        ; Clean out the old resting place
  3490.     DAD    H        ; Multiply it by 32 to convert to
  3491.     DAD    H        ; Number
  3492.     DAD    H        ; Of
  3493.     DAD    H        ; K
  3494.     DAD    H        ; Bytes
  3495.     DAD    D        ; And add in the low byte
  3496.     POP    D
  3497.     CALL    FDECPRT        ; Go print it
  3498.     MVI    A,'k'        ; And follow with size
  3499.     CALL    TYPE
  3500. ;
  3501. ;
  3502. ; At least one more file to output - can we put it on the current line?
  3503. ;
  3504.     LHLD    LMTOTL
  3505.     INX    H
  3506.     SHLD    LMTOTL
  3507.     LDA    LNCNT
  3508.     DCR    A
  3509.     STA    LNCNT
  3510.     PUSH    PSW
  3511.     CNZ    FENCE        ; If room left, output the fence char.
  3512.     POP    PSW
  3513.     POP    B
  3514.     POP    H
  3515.     JNZ    LMTESA        ; And go output another file
  3516. ;
  3517. ;
  3518. ; Current line full, start a new one.
  3519. ;
  3520.     LDA    MNPL
  3521.     STA    LNCNT        ; Reset names per line counter
  3522.     CALL    CRLF        ; Space down to next line
  3523.     JMP    LMTESA
  3524. ;.....
  3525. ;
  3526. ;
  3527. ; Move characters from 'HL' to 'DE' length in 'B'
  3528. ;
  3529. MOVE:    MOV    A,M        ; Get a character
  3530.     STAX    D        ; Store it
  3531.     INX    H        ; To next 'from'
  3532.     INX    D        ; To next 'to'
  3533.     DCR    B        ; More?
  3534.     JNZ    MOVE        ; Yes, loop
  3535.     RET            ; No, return
  3536. ;.....
  3537. ;
  3538. ;
  3539. ; Test file extent for LBR
  3540. ;
  3541. CKLBR:    PUSH    H
  3542.     PUSH    D
  3543.     PUSH    B
  3544.     XCHG
  3545.     LXI    H,LBRTYP
  3546.     MVI    C,3
  3547. ;
  3548. CKLBL:    LDAX    D
  3549.     ANI    7FH
  3550.     CMP    M
  3551.     JNZ    CKLBX
  3552.     INX    H
  3553.     INX    D
  3554.     DCR    C
  3555.     JNZ    CKLBL
  3556. ;
  3557. CKLBX:    POP    B
  3558.     POP    D
  3559.     POP    H
  3560.     RET
  3561. ;.....
  3562. ;
  3563. ;
  3564. BDRCH2:    MVI    A,'*'
  3565.     CALL    TYPE
  3566.     POP    PSW
  3567. ;
  3568. BDRCH1:    MVI    A,'*'
  3569.     CALL    TYPE
  3570.     POP    PSW
  3571.     RET
  3572. ;.....
  3573. ;
  3574. ;
  3575. LFMSP1:    DB    CR,LF,'** Library Directory for ',0
  3576. LFMSP2:    DB    CR,LF,'Library Directory for ',0
  3577. LFMSP3:    DB    CR,LF,'** Lbr Members in ',0
  3578. LFMSP4:    DB    CR,LF,'Lbr Members in ',0
  3579. LBRTYP:    DB    'LBR'
  3580.      ENDIF            ; Lopt    (from waaaaay back in pgm)
  3581. ;
  3582. ;            end of LOPT routine
  3583. ;***********************************************************************
  3584. ;
  3585. ;        TIME:  Report users Time on system
  3586. ;
  3587. ;***********************************************************************
  3588. ;
  3589.      IF    TIMEON
  3590. ;
  3591. ; Go through a search to see if (M)BYE(+) is active.
  3592. ;
  3593. TIME:    LHLD    0001H        ; Point to warm boot again
  3594.     DCX    H        ; If BYE active,
  3595.     MOV    D,M        ; Pick up pointer to BYE variables
  3596.     DCX    H        ; (COVECT) followed by 'BYE'
  3597.     MOV    E,M
  3598.     LXI    H,15        ; Calculate address of BYE variable
  3599.     DAD    D        ; Where ptr to orig BIOS vector stored
  3600.     MOV    E,M        ; Load that address
  3601.     INX    H        ; Into DE.  If BIOS active, DE now points
  3602.     MOV    D,M        ; To original BIOS console output vector
  3603.     INX    H        ; Point to BYE signon message
  3604. ;
  3605.     MOV    A,M        ; Get letter
  3606.     ANI    05FH        ; Convert to upper case if needed
  3607.     CPI    'B'        ; Try to match 'BYE'
  3608.     RNZ            ; Out if BYE not active
  3609.     INX    H
  3610.     MOV    A,M
  3611.     ANI    05FH        ; Convert to upper case if needed
  3612.     CPI    'Y'
  3613.     RNZ
  3614.     INX    H
  3615.     MOV    A,M
  3616.     ANI    05FH        ; Convert to upper case if needed
  3617.     CPI    'E'
  3618.     RNZ
  3619. ;
  3620.     LXI    D,6        ; Bye is running, so point to RTCBUF
  3621.     DAD    D
  3622.     MOV    E,M        ; Get RTCBUF address
  3623.     INX    H        ; And
  3624.     MOV    D,M        ; Stuff in DE
  3625.     XCHG            ; Then put in HL (RTCBUF address)
  3626.     LXI    D,7
  3627.     DAD    D        ; Further offset to time-on-system byte
  3628.     MOV    A,M        ; (A) now has time-on
  3629.     LXI    H,TONMS1    ; Where to store it in ascii
  3630.     CALL    DEC8        ; Convert binary to ascii
  3631.     LXI    D,TONMSG
  3632.     CALL    PRINT        ; Print the message
  3633.     RET            ; And return
  3634. ;
  3635. ; DEC8 will convert an 8 bit binary number in A to 3 ASCII bytes.
  3636. ; HL points to the MSB location where the ASCII bytes will be stored.
  3637. ; Leading zeros are suppressed, so store spaces in your buffer before calling.
  3638. ;
  3639. DEC8:    PUSH    B
  3640.     PUSH    D
  3641.     MVI    E,0        ; Leading zero flag
  3642.     MVI    D,100
  3643. DEC81:    MVI    C,'0'-1
  3644. DEC82:    INR    C
  3645.     SUB    D        ; 100 or 10
  3646.     JNC    DEC82        ; Still +
  3647.     ADD    D        ; Now add it back
  3648.     MOV    B,A        ; Remainder
  3649.     MOV    A,C        ; Get 100/10
  3650.     CPI    '1'        ; Zero?
  3651.     JNC    DEC84        ; Yes
  3652.     MOV    A,E        ; Check flag
  3653.     ORA    A        ; Reset?
  3654.     MOV    A,C        ; Restore byte
  3655.     JZ    DEC85        ; Leading zeros are skipped
  3656. DEC84:    MOV    M,A        ; Store it in buffer pointed at by HL
  3657.     INX    H        ; Increment storage location
  3658.     MVI    E,0FFH        ; Set zero flag
  3659. DEC85:    MOV    A,D
  3660.     SUI    90        ; 100 to 10
  3661.     MOV    D,A
  3662.     MOV    A,B        ; Remainder
  3663.     JNC    DEC81        ; Do it again
  3664.     ADI    '0'        ; Make ascii
  3665.     MOV    M,A        ; And store it
  3666.     POP    D
  3667.     POP    B
  3668.     RET
  3669. ;
  3670. TONMSG:    DB    CR,LF,'Time on system is '
  3671. TONMS1:    DB    '    minutes',0
  3672.      ENDIF            ; TIMEON
  3673. ;
  3674. ;               end of TIMEON routine
  3675. ;======================================================================
  3676. ;
  3677.      IF    HELP
  3678. ;
  3679. ; SD options help menu when $? option entered
  3680. ;
  3681. HELPME:
  3682.     LXI    D,OPTMSG    ; Point at message
  3683.     CALL    PRINT        ; Print it
  3684.     JMP    EXIT        ; And exit
  3685. ;
  3686. OPTMSG:
  3687.     DB    CR,LF,LF
  3688.     DB    ' Options (precede with a $):',CR,LF,LF
  3689.     DB    ' A - all user areas             C - Clear screen',CR,LF
  3690.     DB    ' D - all drives                *F - file output (SD.DIR)',CR,LF
  3691.     DB    ' L - list .LBR members          N - no page pause',CR,LF
  3692.     DB    '*P - printer output             R - reset disk',CR,LF
  3693.     DB    '*S - include $SYS files         U - user area to start',CR,LF
  3694.     DB    ' V - display version #          4 - 40 col display (2-wide)',CR,LF
  3695.     DB    ' 6 - 64 col display (3-wide)    8 - 80 col display (default)',CR,LF,LF
  3696.     DB    ' Example:  A0>sd $adn    List all users & drives with no pauses'
  3697.     DB    CR,LF,LF
  3698.     DB    ' Options marked with a "*" are usually not available',CR,LF
  3699.     DB    ' to remote users.'
  3700.     DB    CR,LF,0
  3701. ;
  3702.      ENDIF            ; Help
  3703. ;
  3704. ;
  3705. ;-----------------------------------------------------------------------
  3706. ;
  3707. ;            end of program code
  3708. ;
  3709. ;-----------------------------------------------------------------------
  3710. ;
  3711. ; Initialized data area
  3712. ;
  3713. DRUMSG:    DB    'Drive/User',0
  3714. ;
  3715.      IF    PGPAWS
  3716. EOSMSG:    DB    '   [more]',CR,'$'
  3717. MORERA:    DB    '         ',CR,'$'
  3718.      ENDIF            ; Pgpaws
  3719. ;
  3720. ERRMS1:    DB    ' '
  3721. ERRMS2:    DB    'Error',0
  3722. ;
  3723.      IF    REPERR
  3724. ERRTAG:    DB    ' ->',0
  3725.      ENDIF            ; Reperr
  3726. ;
  3727. NOFMS1:    DB    CR,LF,CR,LF
  3728. ;
  3729.      IF    REVIDEO
  3730. REVMS1:    DB    LEADIN,INTOREV
  3731.      ENDIF            ; Revideo
  3732. ;
  3733.      IF    REVIDEO    AND THREBYT
  3734.     DB    TBYTE
  3735.      ENDIF
  3736. ;
  3737.     DB    ' ',0
  3738. ;
  3739. NOFLM:    DB    '>> No detectable file(s) on ',0
  3740. NOFSM:    DB    '>> No file(s) on ',0
  3741. NOFMS2:    DB    ':  ',0
  3742. TOTMS1:    DB    CR,LF
  3743. ;
  3744.      IF    REVIDEO
  3745. REVMS2:    DB    LEADIN,INTOREV
  3746.      ENDIF            ; Revideo
  3747. ;
  3748.      IF    REVIDEO    AND THREBYT
  3749.     DB    TBYTE
  3750.      ENDIF
  3751. ;
  3752.     DB    '      Drive ',0
  3753. ;
  3754. TOTMS3:    DB    '     ',CR,LF,0
  3755. TOTMS4:    DB    '  space used: ',0
  3756. TOTMS5:    DB    'k  ',0
  3757. TOTMS6:    DB    ':  files: ',0
  3758. TOTMS7:    DB    '(',0
  3759. TOTMS8:    DB    'k free)      '
  3760. ;
  3761.      IF    REVIDEO
  3762. REVMS3:    DB    LEADIN,OUTAREV
  3763.      ENDIF            ; Revideo
  3764. ;
  3765.      IF    REVIDEO    AND THREBYT
  3766.     DB    TBYTE
  3767.      ENDIF
  3768. ;
  3769.     DB    ' ',0        ; Eliminate double lf
  3770. ;
  3771.      IF    LOPT
  3772. CONTM1:    DB    CR,LF,'*** There are ',0
  3773. CONTM2:    DB    CR,LF,'There are ',0
  3774. MFILES:    DB    ' member files in ',0
  3775. LIBR:    DB    ' library(s)',0
  3776.      ENDIF            ; Lopt
  3777. ;
  3778. ;
  3779. ;=======================================================================
  3780. ;
  3781. ;        Permanently initialized data area
  3782. ;
  3783. ;=======================================================================
  3784.  
  3785.      IF    DOPT
  3786. VECTBL:    DW    DSKERR        ; Bdos sector error intercept vector
  3787.     DW    DSKERR        ; Bdos select error intercept vector
  3788.      ENDIF            ; Dopt
  3789. ;
  3790. ;
  3791. ;=======================================================================
  3792. ;
  3793. ;    Template of initialization data for when SD is run or rerun
  3794. ;
  3795. ;    The values here are copied by initialization code into
  3796. ;    the area in which they are actually used by the program
  3797. ;
  3798. ;=======================================================================
  3799. ;
  3800. TMPLT0    EQU    $        ; Mark start of initialization template
  3801. ;
  3802. ; Option field lookup table.  Note that you can force any of these op-
  3803. ; tions as a DEFAULT by changing the letter for the option into a zero
  3804. ; (assuming that its enabling equate is true).    Each option that you
  3805. ; hard-wire in this manner will no longer be recognized as a command
  3806. ; line OPTION, and if you redundantly key it in, SD will flag it as un-
  3807. ; recognized.
  3808. ;
  3809. OTBL0:     IF    NOT WHLA AND AOPT
  3810.     DB    'A'        ; Axl users option flag
  3811.      ENDIF            ; Not whla and aopt
  3812. ;
  3813.      IF    WHLA AND AOPT
  3814.     DB    'a'
  3815.      ENDIF            ; Whla and aopt
  3816. ;
  3817.      IF    NOT WHLC AND COPT
  3818.     DB    'C'        ; Clear screen option flag
  3819.      ENDIF            ; Not whlc and copt
  3820. ;
  3821.      IF    WHLC AND COPT
  3822.     DB    'c'
  3823.      ENDIF            ; Whlc and copt
  3824. ;
  3825.      IF    NOT WHLCL AND CLOPT
  3826.     DB    '4'
  3827.      ENDIF            ; Not whlcl and clopt
  3828. ;
  3829.      IF    WHLCL AND CLOPT
  3830.     DB    '4'+40H
  3831.      ENDIF            ; Whlcl and clopt
  3832. ;
  3833.      IF    NOT WHLCL AND CLOPT
  3834.     DB    '6'
  3835.      ENDIF            ; Not whlcl and clopt
  3836. ;
  3837.      IF    WHLCL AND CLOPT
  3838.     DB    '6'+40H
  3839.      ENDIF            ; Whlcl and clopt
  3840. ;
  3841.      IF    NOT WHLCL AND CLOPT
  3842.     DB    '8'
  3843.      ENDIF            ; Not whlcl and clopt
  3844. ;
  3845.      IF    WHLCL AND CLOPT
  3846.     DB    '8'+40H
  3847.      ENDIF            ; Whlcl and clopt
  3848. ;
  3849.      IF    NOT WHLD AND DOPT
  3850.     DB    'D'        ; Multi-disk option flag
  3851.      ENDIF            ; Not whld and dopt
  3852. ;
  3853.      IF    WHLD AND DOPT
  3854.     DB    'd'
  3855.      ENDIF            ; Whld and dopt
  3856. ;
  3857.      IF    NOT WHLF AND FOPT
  3858.     DB    'F'        ; Sd.dir file output option
  3859.      ENDIF            ; Not whlf and fopt
  3860. ;
  3861.      IF    WHLF AND FOPT
  3862.     DB    'f'
  3863.      ENDIF            ; Whlf and fopt
  3864. ;
  3865.      IF    NOT WHLL AND LOPT
  3866.     DB    'L'        ; Display library members flag
  3867.      ENDIF            ; Not whll and lopt
  3868. ;
  3869.      IF    WHLL AND LOPT
  3870.     DB    'l'
  3871.      ENDIF            ; Whll and lopt
  3872. ;
  3873.      IF    NOPT AND PGPAWS    ; No page-pause option flag
  3874.     DB    'N'
  3875.      ENDIF            ; Nopt and pgpaws
  3876. ;
  3877.      IF    NOT WHLP AND POPT
  3878.     DB    'P'        ; Printer output option
  3879.      ENDIF            ; Not whlp and popt
  3880. ;
  3881.      IF    WHLP AND POPT
  3882.     DB    'p'
  3883.      ENDIF            ; Whlp and popt
  3884. ;
  3885.      IF    NOT WHLR AND ROPT
  3886.     DB    'R'        ; If not auto reset and not wheel restr.
  3887.      ENDIF            ; Not whlf and ropt
  3888. ;
  3889.      IF    WHLR AND ROPT
  3890.     DB    'r'        ; If not auto reset and is wheel restr.
  3891.      ENDIF            ; Whlr and ropt
  3892. ;
  3893.      IF    NOT WHLS AND SOPT
  3894.     DB    'S'
  3895.      ENDIF            ; Not whls and sopt
  3896. ;
  3897.      IF    WHLS AND SOPT
  3898.     DB    's'
  3899.      ENDIF            ; Whls and sopt
  3900. ;
  3901.      IF    VOPT        ; Display version number flag
  3902.     DB    'V'
  3903. OEND0:     ENDIF            ; Vopt
  3904. ;
  3905. ;
  3906. ; End of option lookup table
  3907.  
  3908.      IF    FOPT
  3909. BUFPN0:    DW    OUTBUF        ; Ptr to next location in output buffer
  3910. BUFCN0:    DB    128        ; Number of bytes left in output buffer
  3911. OUTFC0:    DB    0,'SD      DIR'
  3912.      ENDIF            ; Fopt
  3913.  
  3914. TMPLT1    EQU    $        ; Mark end of initialization data template
  3915.  
  3916. ; THIS IS THE END OF THE CODE THAT MUST BE STORED ON DISK IN THE COM FILE
  3917. ;
  3918. ;=======================================================================
  3919. ;
  3920. ;    data area reinitialized by code when SD is run or rerun
  3921. ;
  3922. ;=======================================================================
  3923.  
  3924. DATA0    EQU    $        ; Mark beginning of area to initialize
  3925.  
  3926.  
  3927. OTBL    EQU    $        ; Mark start of option table
  3928. ;
  3929.      IF    AOPT
  3930. AOPFLG:    DS    1
  3931.      ENDIF            ; Aopt
  3932. ;
  3933.      IF    COPT
  3934. COPFLG:    DS    1
  3935.      ENDIF            ; Copt
  3936. ;
  3937.      IF    CLOPT
  3938. CL4FLG:    DS    1
  3939. CL6FLG:    DS    1
  3940. CL8FLG:    DS    1
  3941.      ENDIF            ; Clopt
  3942. ;
  3943.      IF    DOPT
  3944. DOPFLG:    DS    1
  3945.      ENDIF            ; Dopt
  3946. ;
  3947.      IF    FOPT
  3948. FOPFLG:    DS    1
  3949.      ENDIF            ; Fopt
  3950. ;
  3951.      IF    LOPT
  3952. LOPFLG:    DS    1
  3953.      ENDIF            ; Lopt
  3954. ;
  3955.      IF    NOPT AND PGPAWS    ; No page-pause option flag
  3956. NOPFLG:    DS    1
  3957.      ENDIF            ; Nopt and pgpaws
  3958. ;
  3959.      IF    POPT
  3960. POPFLG:    DS    1
  3961.      ENDIF            ; Popr
  3962. ;
  3963.      IF    ROPT
  3964. ROPFLG:    DS    1
  3965.      ENDIF            ; Autor or ropt
  3966. ;
  3967.      IF    SOPT
  3968. SOPFLG:    DS    1
  3969.      ENDIF            ; Sopt
  3970. ;
  3971.      IF    VOPT        ; Display version number flag
  3972. VOPFLG:    DS    1
  3973.      ENDIF            ; Vopt
  3974. ;
  3975. OEND    EQU    $        ; Mark end of option table
  3976. ;
  3977. ;
  3978. ; End of option lookup table
  3979.  
  3980.      IF    FOPT
  3981. BUFPNT:    DS    2        ; Ptr to next location in output buffer
  3982. BUFCNT:    DS    1        ; Number of bytes left in output buffer
  3983. OUTFCB:    DS    1 + 8 +    3    ; Space for user #, filename, and filetype
  3984.      ENDIF            ; Fopt
  3985. ;-----------------------------------------------------------------------
  3986. ;
  3987. ; BEGINNING OF AREA REINITIALIZED TO ZERO EACH TIME SD IS RUN
  3988. ;
  3989.      IF    FOPT
  3990.     DS    21        ; Rest of sd.dir fcb
  3991. OPNFLG:    DS    1        ; File open flag for all user file output
  3992.      ENDIF            ; Fopt
  3993. ;
  3994. AFLAG:    DS    1        ; If a option check for prior u option
  3995. DFLAG:    DS    1        ; If d option check for prior drive spec.
  3996. FNDFLG:    DS    1        ; Flag whether any files matched
  3997. ;
  3998.      IF    PGPAWS
  3999. LINCNT:    DS    1        ; Count of lines printed on screen
  4000.      ENDIF            ; Pgpaws
  4001. ;
  4002. ;
  4003.      IF    LOPT
  4004. LLENLOC:DS    2        ; Running total of .lbr length
  4005. LMTOTL:    DS    2
  4006. LBTOTL:    DS    2
  4007. LNCNT:    DS    1
  4008. LCOUNT:    DS    2
  4009. NEXTL:    DS    2
  4010. SLFILE:    DS    2
  4011.      ENDIF            ; Lopt
  4012. ;
  4013.      IF    VCODE
  4014. LINES:    DS    1        ; Number of lines to be printed out.
  4015.      ENDIF            ; Vcode
  4016. ;
  4017.      IF    VOPT
  4018. FIRSTT:    DS    1        ; First time flag for version # display
  4019.      ENDIF            ; Vopt
  4020.  
  4021.  
  4022. DATA1    EQU    $        ; Mark end of area to initialize
  4023.  
  4024. ;
  4025. ;=======================================================================
  4026. ;
  4027. ;            Uninitialized data area
  4028. ;
  4029. ;=======================================================================
  4030.  
  4031.      IF    FOPT
  4032. OUTBUF:    DS    128        ; Output file buffer
  4033.      ENDIF            ; Vopt
  4034. ;
  4035. BASUSR:    DS    1        ; Dupe of original dir. user # to search
  4036. BLKMAX:    DS    2        ; Highest block # on drive
  4037. BLKMSK:    DS    1        ; Sec/blk - 1
  4038. BLKSHF:    DS    1        ; # shifts to mult by sec/blk
  4039. COUNT:    DS    2        ; Entry count
  4040. DIRMAX:    DS    2        ; Highest file # in directory
  4041. FREEBY:    DS    2        ; Contains number of k left on dir. drive
  4042. GAP:    DS    2        ; Sort routine storage
  4043. HITRAP:    DS    1        ; Highlit trap (previously typed char)
  4044. I:    DS    2        ; Sort routine storage
  4045. J:    DS    2        ; Sort routine storage
  4046. JG:    DS    2        ; Sort routine storage
  4047. LZFLG:    DS    1        ; 0 when printing leading zeros
  4048. MAXUSR:    DS    1        ; Max user # for drive from lookup table
  4049. NEWUSR:    DS    1        ; Contains user # selected by "$U" option
  4050. NEXTT:    DS    2        ; Next table entry
  4051. OLDDSK:    DS    1        ; Holder for currently logged-in drive
  4052. OLDUSR:    DS    1        ; Contains user number upon invocation
  4053. SCOUNT:    DS    2        ; # to sort
  4054. SUPSPC:    DS    1        ; Leading space flag for decimal routine
  4055. TBLOC:    DS    2        ; Pointer to start of name table
  4056. TEMP:    DS    2        ; Save dir entry
  4057. TOTFIL:    DS    2        ; Total number of files
  4058. TOTSIZ:    DS    2        ; Total size of all files
  4059. VERFLG:    DS    1        ; Cx/m version number (0=pre-cp/m 2)
  4060. ZRDFLG:    DS    1        ; Zrdos version number
  4061. ;
  4062.      IF    LOPT
  4063. LBRFCB:    DS    36
  4064. LBBUF:    DS    80H
  4065.      ENDIF            ; Lopt
  4066. ;
  4067.      IF    VCODE
  4068. NEWPTR:    DS    2        ; Pointer to start of second table
  4069. XPOINT:    DS    2        ; Ditto
  4070. JUMPER:    DS    2        ; Amount to increment by in second table
  4071.                 ; To keep vertical file alignment
  4072.      ENDIF            ; Vcode
  4073. ;
  4074.     DS    60        ; Stack area
  4075. STACK:    DS    2        ; Save old stack pointer here
  4076. ;
  4077. ORDER    EQU    $        ; Order table starts here
  4078. ;
  4079. ;
  4080.     END
  4081.