home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / BEEHIVE / UTILITYS / SDZD-138.ARC / SDZD#138.ASM < prev    next >
Assembly Source File  |  1991-02-10  |  124KB  |  5,513 lines

  1.  
  2.  
  3. ;              SUPER DIRECTORY PROGRAM
  4. ;
  5. ;             SDZD+138  1 FEB 89
  6. ;
  7. ;    Read SDZD+.INF for detailed instructions on configuring SD for your
  8. ;    system.  For information regarding this utility's modification
  9. ;    history, read SDZD+.HIS.
  10. ;
  11. ;        This program is being distributed ready
  12. ;        to use on a CP/M v2.2 computer with two
  13. ;        disk drives , no Z80DOS, no CPM3, and no ZCPR in use.
  14. ;
  15. ;        (Options often changed for RCPM use are
  16. ;        marked with an asterisk.)  The typical
  17. ;        RCPM Sysop might change only these:
  18. ;
  19. ;            a)    3 options starting at MAXDRV
  20. ;            b)    how many drives at LODRV and
  21. ;            c)    6 options starting at USEF
  22. ;            d)    USELCW needs wheel to prevent
  23. ;               showing archive bits
  24. ;
  25. ;
  26. ;         NOTE:  This version can be assembled with
  27. ;            ASM, LASM, M80, MAC or SLRMAC.
  28. ;
  29. ; SD displays the directory of a CP/M disk, sorted alphabetically, with
  30. ; the file size in k, rounded to the nearest CP/M block size.  It also
  31. ; displays library and archive files with the file size in k, if the $L
  32. ; option is selected.
  33. ;
  34. ; Current versions of SD automatically adjust for any block size and di-
  35. ; rectory length under CP/M 2.2,  3.0 or MP/M.    They can also handle any
  36. ; number of disk drives or skip those not available.  Current features:
  37. ;
  38. ;     1) Automatic pauses when the screen fills up except when the
  39. ;        F, N, or P options are specified
  40. ;     2) Searching individual or multiple drives and/or user areas
  41. ;     3) Unconditional or optional disk system reset before execution
  42. ;        begins
  43. ;     4) Directing output to a disk file called DISK.DIR and append-
  44. ;        ing to that file on subsequent runs
  45. ;     5) Summary line output giving drive and user information, num-
  46. ;        ber of files matched, how much space they consume and free
  47. ;        space remaining on the disk
  48. ;     6) Displaying or suppressing "system" files
  49. ;     7) Accepting ambiguous filenames with or without a drive name
  50. ;     8) Printer output (automatically suppresses the [more] pauses)
  51. ;     9) Optional help menu with '?'
  52. ;    10) Displaying number of records used by files
  53. ;    11) Alphabetization of files sorted by type (extent)
  54. ;    12) Selecting alternate list format - vertical if horizontal
  55. ;        is default, and vice versa.
  56. ;    13) Shows contents of .ARC, .ARK or .LBR files with $L option
  57. ;    14) Summary line output optionally contains name of ZCPR3 named
  58. ;        directory, if selected
  59. ;    15) ZCPR3 named directory may be used in command line instead
  60. ;        of DU: if selected
  61. ;    16) ZCPR3 Public user areas may be displayed with or without
  62. ;        WHEEL byte
  63. ;    17) Z80DOS or CPM3 time stamping and SETD22 type stamping of .LBR's
  64. ;        supported via Z80DOS or CPM3 equate.
  65. ;    18) Normal multi-page vertical sort or single page vertical sort
  66. ;    19) Choose files based upon attributes 1-4
  67. ;    20) Z33 ENViorment support of wheel, maxdrv, maxusr location
  68. ;    21) Summary totals now supplied if /A,/D,/H (or combo).
  69. ;    22) Greatly expanded date math capabilities
  70. ;    23) Support for CPM3 date stamping
  71. ;
  72. ;-----------------------------------------------------------------------
  73. ;
  74. ;    ASEG            ; Needed for M80 and RMAC, ignore error
  75. ;
  76.     ORG    0100H
  77. ;
  78.     JMP    START
  79. ;
  80. NO    EQU    0
  81. YES    EQU    NOT NO        ; (Some assemblers don't like 0FFh)
  82. ;
  83. ; Define version number
  84. ;
  85. MAIN    EQU    1        ; Main block number
  86. VER    EQU    38        ; Current version
  87. MONTH    EQU    02        ; Month
  88. DAY    EQU    01        ; Day
  89. YEAR    EQU    89        ; Year
  90. ;
  91. ;-----------------------------------------------------------------------
  92. ;                 options
  93. ;
  94. MAXDRV    EQU    NO        ; *Yes if MAXD byte is supported
  95. MAXUR    EQU    NO        ; *Yes if MAXU byte is supported
  96. WHEEL    EQU    NO        ; *Yes if using ZCPR wheel byte
  97.  
  98. ; If using equate ZCPR33 set to YES, then the following 3 will be
  99. ; taken from the ENV descriptor automaticaly if the corresponding
  100. ; MAXDRV, MAXUR, or WHEEL equate is set YES
  101. MXDRV    EQU    3DH        ; *Set to max drive address if MAXDRV=Yes
  102. MXUSR    EQU    3FH        ; *Set to max user  address if MAXUR=Yes
  103. WHLOC    EQU    3EH        ; *Set to wheel location if WHEEL=Yes
  104.  
  105. MXZUSR    EQU    15        ; Maximum user # allowed with WHEEL set
  106.  
  107. PRBRDR    EQU    NO        ; Yes = print quasi-borders for libraries
  108. WMBOOT    EQU    NO        ; If warmboot is needed on exit
  109. VLIST    EQU    YES        ; Yes for vertical alphabetization
  110. VSPAGE    EQU    YES        ; If Vertical sort is to be by page
  111.  
  112.     DB    'Z3ENV'        ; For ZCPR3 Environment ID
  113.     DB    1        ; Class 1, External
  114. Z3ENV:    DW    0        ; Environment Address.    If using ZCPR33
  115.                 ; This can be left as is.
  116. ;-------------------------------
  117. ;
  118. ; Drive/User area lookup table:
  119. ; ----------------------------
  120. ; Change the following table as appropriate for your version of CP/M.
  121. ; You can limit the maximum user area without wheel byte independently
  122. ; for any drive available.  Use 0FFh for drives that are not available.
  123. ;
  124. ;        CP/M  v2.2 has 16 user areas, 0-15
  125. ;        CP/M  v3.0 has 32 user areas, 0-31
  126. ;
  127. ; NOTE: Use your editor to move the "HIDRV" line below the correct
  128. ; number of drives for your system.  This not only saves time when the
  129. ; highest drive has been reached, but will display a drive/user error
  130. ; message which otherwise will not be shown.
  131. ;
  132. LODRV    EQU    $        ; Mark beginning of drive/user table
  133.  
  134.     DB    15        ; Maximum user area for drive A
  135.     DB    15        ; "      "    "    "    "     B
  136. HIDRV    EQU    $        ; Mark end of drive/user table
  137.     DB    0FFH        ; "      "    "    "    "     C
  138.     DB    0FFH        ; "      "    "    "    "     D
  139.     DB    0FFH        ; "      "    "    "    "     E
  140.     DB    0FFH        ; "      "    "    "    "     F
  141.     DB    0FFH        ; "      "    "    "    "     G
  142.     DB    0FFH        ; "      "    "    "    "     H
  143.     DB    0FFH        ; "      "    "    "    "     I
  144.     DB    0FFH        ; "      "    "    "    "     J
  145.     DB    0FFH        ; "      "    "    "    "     K
  146.     DB    0FFH        ; "      "    "    "    "     L
  147.     DB    0FFH        ; "      "    "    "    "     M
  148.     DB    0FFH        ; "      "    "    "    "     N
  149.     DB    0FFH        ; "      "    "    "    "     O
  150.     DB    0FFH        ; "      "    "    "    "     P
  151. ;
  152. ;-------------------------------
  153. ;
  154. ; Command line options:
  155. ; --------------------
  156. ; If any of the following equates are set NO, it prevents their use by
  157. ; any user (including the SYSOP) unless the wheel byte has been set for
  158. ; SYSOP use.  If running an RCPM, you may wish to say NO for those with
  159. ; an asterisk, such as USEF, USERO, USEP and USES to prevent others from
  160. ; using them - the wheel byte makes them available for SYSOP use.
  161. ;
  162. ; NOTE:  For RCPM use, all 5 would normally be set to "NO" to prevent
  163. ; remote use, but would be available to the Sysop with the WHEEL byte.
  164. ;
  165. USEF    EQU    YES        ; *Allow making a local disk copy?
  166. USEO    EQU    YES        ; *Allow showing only $SYS files?
  167. USEP    EQU    YES        ; *Allow making local printer listing?
  168. USER    EQU    YES        ; *Allow disk system reset?
  169. USES    EQU    YES        ; *Allow showing all, and $SYS files?
  170.  
  171. ; Above note goes for the following
  172. USEA    EQU    NO        ; *Allow specifying attributes 1-4?
  173.  
  174. ;
  175. ;-------------------------------
  176. ;
  177. ; Showing tagged attributes
  178. ; -------------------------
  179. ; Displaying files with tagged attributes ($R/O, $SYS, $ARC etc.) in an
  180. ; in an unique manner so they are easy to find, if present.
  181. ;
  182. ;    Example:
  183. ;        FILENAME.SyS    -  $SYS attribute set
  184. ;        FILENAME.doC    -  $SYS and $R/O both set
  185. ;        FILENAME.com    -  $SYS, $R/O and $ARC all set
  186. ;
  187. ; The following equates will permit SD to display the files with tagged
  188. ; attributes in lower case letters (a-z) as in example above.
  189. ;
  190. USELC    EQU    NO        ; Allow lower case letters (a-z)
  191. USELCW    EQU    NO        ; *Allow lower case without wheel byte?
  192. ;
  193. ;-----------------------------------------------------------------------
  194. ;
  195. ; Reverse video options
  196. ; ---------------------
  197. ; The following equate will permit SD to display the files with tagged
  198. ; attributes in either reverse video or bright/dim modes.  This will al-
  199. ; low any character tagged to be visible, as opposed to the USELD method.
  200. ; Up to 7 bytes for enter and exit video modes are provided.  These can
  201. ; be easily patched with DDT, etc.
  202. ;
  203. REVID    EQU    NO        ; Yes = inverse or bright/dim display
  204. ;
  205. ; The following equate will highlight/underline the summary line
  206. ;
  207. ULINE    EQU    NO        ; Yes = highlight/underline summary
  208. ;
  209. ;
  210. ; Reverse video control bytes
  211. ; ---------------------------
  212. ; If byte at RVON is 0, simple lower case will be used to display file
  213. ; attributes.
  214. ;
  215.      IF    REVID
  216. RVON:    DB    0,0,0,0,0,0,0    ; Up to 7 characters for ENTER REVERSE
  217.     DB    0        ; String Terminator MUST BE 0
  218. ;
  219. RVOFF:    DB    0,0,0,0,0,0,0    ; Up to 7 characters for EXIT REVERSE
  220.     DB    0        ; String Terminator MUST BE 0
  221.      ENDIF            ; REVID
  222. ;
  223. ; If byte at ULON is 0, no highlighting/underlining will be used in the
  224. ; banner line.
  225. ;
  226.      IF    ULINE
  227. ULON:    DB    0,0,0,0,0,0,0    ; Up to 7 characters for ENTER ULINE
  228.     DB    0        ; String Terminator, MUST BE 0
  229. ;
  230. ULOFF:    DB    0,0,0,0,0,0,0    ; Up to 7 characters for EXIT ULINE
  231.     DB    0        ; String Terminator MUST BE 0
  232.      ENDIF            ; ULINE
  233. ;
  234. ;-------------------------------
  235. ;
  236. ; Time/date options
  237. ; -----------------
  238. ; The following equate will get the TIMEON from BYE, if BYE is active.
  239. ; The message "Time on system is xx Minutes" will be displayed.
  240. ;
  241. TIMEON    EQU    NO        ; Yes, gets TIMEON from BYE5
  242. ;
  243. ; The following equate will permit the date to be displayed using the
  244. ; European system DD/MM/YY or the American system MM/DD/YY.  This only
  245. ; shows when using Z80DOS, CPM3 or 'V' to display version number.
  246. ;
  247. EDATE    EQU    NO        ; Yes = European, No = American
  248. ;
  249. ;-------------------------------
  250. ;
  251. ; If using Z80DOS and you want date stamping support, set to YES.
  252. ;
  253. Z80DOS    EQU    NO
  254. ;
  255. ;-------------------------------------
  256. ;
  257. ; If using CPM3 that supports DATE/TIME stamps & you want date stamping
  258. ; support, then set to YES
  259. ;
  260. CPM3    EQU    NO
  261. ;
  262. ; Set to YES if you want to have the date default to UPDATE else set
  263. ; to NO for CREATE/ACCESS default.
  264. ;
  265. UPDATE    EQU    YES        ; Default to update if YES else access/create
  266. ;
  267. ;-------------------------------
  268. ;
  269. ; If want to be able to specify files to be displayed based upon attribute
  270. ;    1 thru 4 , set the following to yes
  271. ;
  272. FATTRIB EQU    YES
  273. ;
  274. ;-------------------------------
  275. ;
  276. ; Z3CPR options
  277. ; -------------
  278. ; for ZCPR33 users - leave all set to NO if not using ZCPR3
  279. ;
  280. ZCPR33    EQU    NO        ; Allow named dir's and ENV support
  281. ZCPR3    EQU    NO        ; Allow named directory in command line
  282. NDIRS    EQU    NO        ; To display directory names
  283. SHOPUB    EQU    NO        ; To display ZRDOS Public Directories
  284. WHLPUB    EQU    NO        ; To make SHOPUB wheel dependent
  285. ZRDOS    EQU    NO        ; Set to yes if using ZRDOS
  286. Z3DRV    EQU    44        ; Offset from ENV location to find drive max
  287. Z3USR    EQU    45        ; Offset from ENV location to find user max
  288. Z3WHL    EQU    41        ; Offset from ENV location to find wheel address
  289. Z3NDR    EQU    21        ; Offset from ENV location to find NDIR address
  290. ;
  291. ;            end of options
  292. ;-----------------------------------------------------------------------
  293. ;
  294. ; Reference items
  295. ; ---------------
  296. RECORD    EQU    36
  297. FRN    EQU    33
  298. FCR    EQU    32
  299. READRN    EQU    33
  300. HDRSIZ    EQU    27
  301. ARCMAR    EQU    26
  302. SBCDE    EQU    52EDH        ; Z80's SBC HL,DE
  303. ZMOVE    EQU    0B0EDH        ; Z80's LDIR 
  304. TMPLT0    EQU    $        ; Start of initialization template
  305.  
  306.      IF    VLIST
  307.     DB    0
  308.      ENDIF            ; VLIST
  309.  
  310.      IF    NOT VLIST
  311.     DB    0FFH
  312.      ENDIF            ; NO VLIST
  313.  
  314.     DB    'A'        ; All-users option flag
  315.     DB    'C'        ; File size in records option
  316.     DB    'D'        ; Multi-disk option flag
  317.  
  318.      IF    USEF
  319.     DB    'F'        ; DISK.DIR file output option
  320.      ENDIF            ; USEF
  321.  
  322.      IF    NOT USEF
  323.     DB    'F'+80H
  324.      ENDIF            ; NOT USEF
  325.  
  326.     DB    'H'        ; Show areas from current to highest
  327.     DB    'L'        ; Display library members flag
  328.     DB    'N'        ; No page-pause option flag
  329.  
  330.      IF    USEO
  331.     DB    'O'        ; To show $SYS files only
  332.      ENDIF            ; USEO
  333.  
  334.      IF    NOT USEO
  335.     DB    'O'+80H
  336.      ENDIF            ; NOT USEO
  337.  
  338.      IF    USEP
  339.     DB    'P'        ; Printer output option
  340.      ENDIF            ; USEP
  341.  
  342.      IF    NOT USEP
  343.     DB    'P'+80H
  344.      ENDIF            ; NOT USEP
  345.  
  346.     DB    'Q'        ; To show only non-$ARC files
  347.  
  348.      IF    USER
  349.     DB    'R'        ; Optional reset of disk system
  350.      ENDIF            ; USER
  351.  
  352.      IF    NOT USER
  353.     DB    'R'+80H
  354.      ENDIF            ; NOT USER
  355.  
  356.      IF    USES
  357.     DB    'S'        ; Include $SYS files
  358.      ENDIF            ; USES
  359.  
  360.      IF    NOT USES
  361.     DB    'S'+80H
  362.      ENDIF            ; NOT USES
  363.  
  364.     DB    'T'        ; Primary sort by file type
  365.     DB    'V'        ; Show SD version
  366.     DB    'X'        ; Alternate alphabetization
  367.  
  368.      IF    Z80DOS OR CPM3
  369.     DB    '='        ; Look for exact match of date given
  370.     DB    '+'        ; Look for files of date GE date given
  371.     DB    '-'        ; Look for files of date LT date given
  372.      ENDIF            ; Z80DOS/CPM3
  373.  
  374.      IF    Z80DOS
  375.     DB    '!'        ; Match with creation date
  376.      ENDIF            ; Z80DOS
  377.  
  378.      IF    Z80DOS OR CPM3
  379.     DB    '%','%'        ; Match with alteration date
  380.     DB    '@'        ; Match with access date
  381.     DB    'Z'        ; Show dates
  382.      ENDIF            ; Z80DOS/CPM3
  383.  
  384. ;     IF    FATTRIB        ; Allow spec of file attributes 1-4?
  385.      IF    USEA AND FATTRIB
  386.     DB    '1'        ; Only files with attrib 1
  387.      ENDIF            ; USEA
  388.  
  389.      IF    NOT USEA AND FATTRIB
  390.     DB    80H+'1'
  391.      ENDIF            ; NOT USEA
  392.  
  393.      IF    USEA AND FATTRIB
  394.     DB    '2'        ; Only files woth attrib 2
  395.      ENDIF            ; USEA
  396.  
  397.      IF    NOT USEA AND FATTRIB
  398.     DB    80H+'2'
  399.      ENDIF            ; NOT USEA
  400.  
  401.      IF    USEA AND FATTRIB
  402.     DB    '3'        ; Only files with attrib 3
  403.      ENDIF            ; USEA
  404.  
  405.      IF    NOT USEA AND FATTRIB
  406.     DB    80H+'3'
  407.      ENDIF            ; NOT USEA
  408.  
  409.      IF    USEA AND FATTRIB
  410.     DB    '4'        ; Only files with attrib 4
  411.      ENDIF            ; USEA
  412.  
  413.      IF    NOT USEA AND FATTRIB
  414.     DB    80H+'4'
  415.      ENDIF            ; NOT USEA
  416.  
  417. ;     ENDIF        ;FATTRIB
  418. ;
  419. ; End of option lookup table
  420. ;
  421.     DW    OUTBUF        ; Next location in output buffer
  422.     DB    128        ; # of bytes left in output buffer
  423.     DB    0,'DISK    DIR'    ; Output Filename.typ
  424. ;
  425. TMPLT1    EQU    $        ; End of initialization data template
  426.  
  427. VERNAME:DB    13,10,'SDZD+',MAIN+'0'
  428.     DB    VER/10+'0',VER MOD 10+'0',' -- '
  429.  
  430.      IF    NOT EDATE
  431.     DB    MONTH/10+'0',MONTH MOD 10+'0','/'
  432.      ENDIF            ; NOT EDATE
  433.  
  434.     DB    DAY/10+'0',DAY MOD 10+'0','/'
  435.  
  436.      IF    EDATE
  437.     DB    MONTH/10+'0',MONTH MOD 10+'0','/'
  438.      ENDIF            ; EDATE
  439.  
  440.     DB    YEAR/10+'0',YEAR MOD 10+'0'
  441.  
  442.      IF    CPM3
  443.     DB    ', CP/M 3.0'
  444.      ENDIF
  445.  
  446.      IF    Z80DOS
  447.     DB    ', Z80DOS'
  448.      ENDIF
  449.  
  450.      IF    ZCPR3        ; 
  451.     DB    ', ZCPR3/ARC/ARK Version'
  452.      ENDIF            ; ZCPR3 
  453.  
  454.      IF    ZCPR33        ; 
  455.     DB    ', ZCPR33/ARC/ARK Version'
  456.      ENDIF            ; ZCPR33
  457.  
  458.     DB    0
  459. ;
  460. ;-----------------------------------------------------------------------
  461. ;             Program starts here
  462. ;-----------------------------------------------------------------------
  463. ;
  464. START:    LXI    H,0
  465.     DAD    SP        ; HL=old stack
  466.     SHLD    STACK        ; Save it
  467.     LXI    SP,STACK    ; Get new stack
  468.  
  469.      IF    ZCPR33
  470.     LHLD    Z3ENV        ; Get ENV address
  471.     PUSH    H
  472.     LXI    D,Z3DRV        ; Point to max drv byte
  473.     DAD    D
  474.     SHLD    Z3DRVL        ; Save location away
  475.     POP    H
  476.     PUSH    H
  477.     LXI    D,Z3USR        ; Point to maxuser byte
  478.     DAD    D
  479.     SHLD    Z3USRL        ; Save location away
  480.     POP    H
  481.     PUSH    H
  482.     LXI    D,Z3WHL        ; Point to address pointer of wheel
  483.     DAD    D
  484.     MOV    E,M        ; Get address of wheel byte
  485.     INX    H
  486.     MOV    D,M
  487.     XCHG
  488.     SHLD    Z3WHLL        ; Save it away
  489.     POP    H
  490.      ENDIF            ; ZCPR33
  491.  
  492.      IF    NDIRS
  493.     LHLD    Z3ENV        ; Get Environment Address
  494.     LXI    D,Z3NDR        ; Point to named directory space
  495.     DAD    D
  496.     MOV    E,M
  497.     INX    H
  498.     MOV    D,M        ; DE Now contains NDR Address
  499.     INX    H
  500.     MOV    A,M
  501.     ADI    1
  502.     STA    NUMDIR        ; Maximum number of entries plus 1
  503.     XCHG
  504.     SHLD    NAMADR        ; Keep Address for later
  505.      ENDIF            ; NDIRS
  506. ;
  507. ; Clear Public User Areas so they can be displayed
  508. ;
  509.      IF    SHOPUB
  510.     LHLD    0109H        ; Get Environment Address
  511.     MVI    D,0
  512.     MVI    E,07EH
  513.     DAD    D        ; HL Points to Public Drive Byte
  514.     MOV    A,M        ; Get public DRV byte
  515.     STA    PUBDRV
  516.     INX    H
  517.     MOV    A,M        ; Get public USR byte
  518.     STA    PUBUSR
  519.      ENDIF            ; SHOPUB
  520.  
  521. ;     IF    WHLPUB
  522.  
  523.      IF    ZCPR33 AND WHLPUB
  524.     PUSH    H
  525.     LHLD    Z3WHLL        ; Point to ENV
  526.     MOV    A,M        ; Get wheel
  527.     POP    H
  528.      ENDIF            ; ZCPR33
  529.  
  530.      IF    NOT ZCPR33 AND WHLPUB
  531.     LDA    WHLOC        ; Load wheel byte
  532.      ENDIF            ; NOT ZCPR33
  533.  
  534.      IF    WHLPUB
  535.     ORA    A
  536.     JZ    NOPUB
  537.      ENDIF            ; WHLPUB
  538.  
  539.      IF    SHOPUB
  540.     DCX    H
  541.     MVI    A,0        ; Clear Public Areas temporarily
  542.     MOV    M,A
  543.     INX    H
  544.     MOV    M,A
  545.      ENDIF            ; SHOPUB
  546.  
  547.      IF    WHLPUB AND SHOPUB
  548. NOPUB:    DS    0
  549.      ENDIF            ; WHLPUB
  550. ;
  551. ; (WHLPUB enabled, the R option is redundant)
  552. ;
  553. ;     ENDIF            ; SHOPUB
  554. ;
  555. ; See if help is wanted
  556. ;
  557.     LXI    H,FCB+1        ; Filename
  558.     MOV    A,M        ; 1st Character
  559.  
  560.      IF    NOT ZCPR33
  561.     CPI    '?'        ; Is it "?"
  562.     JNZ    INIT        ; No, Continue
  563.     INX    H        ; Yes, Next Char
  564.     MOV    A,M        ; 2nd Character
  565.     CPI    ' '        ; Is it " "
  566.     JNZ    INIT        ; If not, did not want help guide
  567.     LDA    FCB+9        ; Check for any extent
  568.     CPI    ' '
  569.     JZ    HELPME        ; If none, wanted help
  570.      ENDIF            ; NOT ZCPR33
  571.  
  572.      IF    ZCPR33
  573.     CPI    '?'        ; Is it "?"
  574.     JNZ    CHKSLH        ; No, Continue
  575.     INX    H        ; Yes, Next Char
  576.     MOV    A,M        ; 2nd Character
  577.     CPI    ' '        ; Is it " "
  578.     JNZ    INIT        ; If not, did not want help guide
  579.     LDA    FCB+9        ; Check for any extent
  580.     CPI    ' '
  581.     JZ    HELPME        ; If none, wanted help
  582.     JMP    INIT
  583. CHKSLH:    CPI    '/'        ; Is it a slash?
  584.     JNZ    INIT
  585.     INX    H
  586.     MOV    A,M        ; two slashes gets help
  587.     CPI    '/'
  588.     JZ    HELPME
  589.      ENDIF            ; ZCPR33
  590.  
  591. ;
  592. ; Zero out the entire initialization data area
  593. ;
  594. INIT:    LXI    H,DATA0        ; Point to start of initialized data area
  595.     PUSH    H        ; Save for non-zero filling later
  596.     MVI    C,DATA1-DATA0    ; Data area length
  597.     XRA    A        ; Clear the "A" register
  598.  
  599. ZFILL:    MOV    M,A        ; Null the address
  600.     INX    H        ; Pointer+1
  601.     DCR    C        ; One less to go
  602.     JNZ    ZFILL
  603.  
  604.      IF    SHOPUB        ; In order for the Public Directories
  605.     MVI    A,0FFH        ; To be displayed, Option 'R' must be
  606.     STA    ROPFLG        ; Forced true.
  607.      ENDIF            ; SHOPUB
  608. ;
  609. ; Now copy non-zero initialization data from the template area
  610. ;
  611.     POP    H        ; Load A(DATA0)
  612.  
  613.      IF    Z80DOS OR CPM3
  614.     XCHG
  615.     LXI    H,TMPLT0    ; Load A(TMPLT0)
  616.     LXI    B,TMPLT1-TMPLT0    ; Template area length
  617.     DW    ZMOVE        ; Z80's LDIR
  618.      ENDIF            ; Z80DOS/CPM3
  619.  
  620.      IF    NOT (Z80DOS OR CPM3)
  621.     LXI    D,TMPLT0    ; Load A(TMPLT0)
  622.     MVI    C,TMPLT1-TMPLT0    ; Template area length
  623. NZFILL:    LDAX    D        ; Load template byte
  624.     MOV    M,A        ; Move to data area
  625.     INX    D        ; Next location to store data
  626.     INX    H        ; Next location to get data
  627.     DCR    C        ; One less to go
  628.     JNZ    NZFILL
  629.      ENDIF            ; NOT Z80DOS/CPM3
  630.  
  631.     LXI    H,0        ; Clear HL
  632.  
  633.      IF    ZRDOS
  634.     MVI    C,ZRDVER    ; Get ZRDOS version
  635.     CALL    BDOS
  636.     MOV    A,L        ; ZRDOS Version #
  637.     STA    ZRDFLG        ; Save it
  638.      ENDIF            ; ZRDOS
  639.  
  640.     MVI    C,CPMVER    ; Get CP/M  version
  641.     CALL    BDOS
  642.     MOV    A,L        ; CP/M Version number
  643.     STA    VERFLG        ; Save it
  644.     STA    SOHFLG        ; Prevents initial unwanted CRLF
  645.     CPI    20H        ; Set carry if CP/M 1.4
  646.     PUSH    PSW        ; Save for BYE test
  647.     MVI    E,0FFH        ; Load current user number if CP/M 2
  648.     MVI    C,STUSER    ; Fall through with A=0 if not
  649.     CNC    CPM        ; Only if CP/M 2.0 or ZRDOS
  650.     STA    OLDUSR        ; Initial user number
  651.     STA    NEWUSR        ; New user = Initial user
  652.     STA    BASUSR        ; Directories
  653.     POP    PSW        ; Recover Version Flag
  654.     MVI    E,241        ; Special BYE5xx Call
  655.     MVI    C,STUSER    ; Returns 77 if BYE5xx active
  656.     CNC    CPM        ; BYE5nn not on CP/M 1.4 system
  657.     SUI    77        ; Return code expected
  658.     STA    BYEACT        ; BYEACT = 0, BYE5nn active
  659.  
  660.      IF    TIMEON
  661.     CALL    TIME
  662.      ENDIF            ; TIMEON
  663.  
  664.      IF    ZCPR3 OR ZCPR33
  665.     LDA    FCB+13        ; Point to command line buffer (CLB)
  666.     STA    NEWUSR
  667.      ENDIF            ; ZCPR3
  668.  
  669.      IF    NOT ZCPR3 AND NOT ZCPR33
  670.     LXI    H,TBUF+1    ; Point to command line buffer (CLB)
  671.     MOV    A,M        ; CLB Character
  672.     CPI    '['        ; CP/M 3.0 style delimiter
  673.     JZ    CLOK        ; (may follow command in CP/M 3.0)
  674.     INX    H        ; CLB pointer +1
  675.     ORA    A        ; Terminator?
  676.     JNZ    CLOK        ; No, continue
  677.     MOV    M,A        ; Yes, set 2nd terminator
  678.  
  679. CLOK:    LXI    D,FCB        ; A(file control block)
  680.     CALL    FNAME        ; Process filename.typ
  681.     MOV    A,B        ; Disk specification
  682.     CPI    0FFH        ; Current?
  683.     JZ    CLUS        ; Yes
  684.     STAX    D        ; No, set disk specification
  685.  
  686. CLUS:    MOV    A,C        ; User specification
  687.     CPI    0FFH        ; Current?
  688.     JZ    CLNON        ; Yes
  689.     STA    NEWUSR        ; No, set user specification
  690.     STA    BASUSR
  691.      ENDIF            ; NOT ZCPR3 AND NOT ZCPR33
  692.  
  693. CLNON:    MVI    C,CURDSK
  694.     CALL    CPM        ; Load current disk number
  695.     STA    OLDDSK        ; Save for reset if needed
  696.     INR    A        ; Adjust
  697.     STA    OUTFCB        ; Save directory file drive
  698.     LXI    H,FCB        ; A(file control block)
  699.     MOV    A,M        ; Load directory search drive
  700.     ORA    A        ; Any specified?
  701.     JNZ    START1        ; Yes, skip next routine
  702.     LDA    OLDDSK        ; Otherwise, get default disk
  703.     INR    A        ; Adjust
  704.     JMP    START2
  705.  
  706. START1:    PUSH    PSW        ; Save status
  707.     MVI    A,1
  708.     STA    DRVFLG        ; Set DRVFLG = 1
  709.     POP    PSW        ; Load status
  710.  
  711. START2:    MOV    M,A        ; Absolute drive code in directory FCB
  712. ;
  713. ; If at least one option is allowed,  scan command line for the option
  714. ; field delimiter. The option field delimiter is considered valid only
  715. ; if it is preceded by at least 1 space  (otherwise may be part of the
  716. ; directory filename).     Any unrecognized options/illegal user numbers
  717. ; will be flagged.(We scan the command line buffer rather than the 2nd
  718. ; default FCB because all 8 options + 2 digit user number will not fit
  719. ; in the 2nd FCB name field).
  720. ;
  721.     LXI    H,TBUF        ; CLB pointer
  722.     MOV    B,M        ; CLB length
  723. ;
  724. ; Search for valid command line delimiter, if not found, assume no
  725. ; options.  Show help menu if single "?" entered.
  726. ;
  727. SCNDOL:    INX    H        ; CLB PTR+1
  728.     DCR    B        ; CLB LEN-1
  729.     JM    DOPTN        ; Exit if command line buffer empty
  730.     MOV    A,M        ; CLB Character
  731.     CPI    '['        ; CPM+ style delimiter?
  732.     JZ    OPTDLM        ; Yes
  733.     CPI    '$'        ; CPM2 style delimiter?
  734.     JZ    SPB4        ; Yes
  735.     CPI    '/'        ; ZCPR style delimiter?
  736.     JNZ    SCNDOL        ; No
  737.  
  738. SPB4:    DCX    H        ; '$' found, space must precede
  739.     MOV    A,M        ; Previous character
  740.     INX    H
  741.     CPI    ' '
  742.     JNZ    SCNDOL        ; No space, ignore '$'
  743. ;
  744. ; Valid delimiter found.  Scan the rest of the buffer for options.
  745. ; Errors past this point cause an abort.
  746. ;
  747. OPTDLM:    XCHG            ; DE = CLB pointer (swap pointers)
  748.  
  749. SCNOPT:    INX    D        ; CLB PRT+1
  750.     DCR    B        ; CLB LEN-1
  751.     JM    DOPTN        ; If option field exhausted, exit
  752.  
  753. SCNAGN:    LDAX    D        ; Load option character
  754.     CPI    ' '        ; Is it " "?
  755.  
  756.      IF    Z80DOS OR CPM3
  757.     JZ    LOKDAT        ; Space, go look for date info
  758.      ENDIF            ; Z80DOS/CPM3
  759.  
  760.      IF    NOT (Z80DOS OR CPM3)
  761.     JZ    SCNOPT        ; Yes, Ignore it
  762.      ENDIF            ; NOT Z80DOS
  763.  
  764.     CPI    ']'        ; CPM+ style terminator?
  765.     JZ    SCNOPT        ; Options may follow terminator
  766.     LXI    H,OTBL-1    ; OTBL pointer
  767.     MVI    C,OEND-OTBL+1    ; OTLB length
  768.  
  769. NOMACH:    INX    H        ; OTLB pointer+1
  770.     DCR    C        ; OTLB length-1
  771.     JZ    CLERR        ; Error if option table end
  772.  
  773.      IF    WHEEL        ; ZCMD/ZCPR2/ZCPR3?
  774.     PUSH    PSW        ; Save "A" value
  775.      ENDIF            ; WHEEL
  776.  
  777.      IF    ZCPR33 AND WHEEL
  778.     PUSH    H
  779.     LHLD    Z3WHLL        ; Point to ENV
  780.     MOV    A,M        ; Get wheel
  781.     POP    H
  782.      ENDIF            ; ZCPR33
  783.  
  784.      IF    NOT ZCPR33 AND WHEEL
  785.     LDA    WHLOC        ; Load wheel byte
  786.      ENDIF            ; NOT ZCPR33
  787.  
  788.      IF    WHEEL
  789.     ORA    A        ; Set Flags
  790.     JZ    NOMAC1        ; Not set, so forget it
  791.     MOV    A,M        ; Load the table option
  792.      ENDIF            ; WHEEL
  793.  
  794.      IF    FATTRIB AND WHEEL
  795.     ANI    7FH
  796.      ENDIF            ; FATTRIB
  797.  
  798.      IF    NOT (FATTRIB AND WHEEL) AND (NOT CPM3)
  799.     ANI    5FH        ; Allow the option
  800.      ENDIF            ; NOT FATTRIB
  801.  
  802.      IF    WHEEL
  803.     MOV    M,A        ; Stuff back in table
  804.  
  805. NOMAC1:    POP    PSW        ; Restore "A" value
  806.      ENDIF            ; WHEEL
  807.  
  808.     CMP    M        ; Compare with table entry
  809.     JNZ    NOMACH        ; If no match, check next
  810.     MVI    M,0        ; Else, activate the option
  811.     JMP    SCNOPT        ; Continue scan
  812. ;.....
  813. ;
  814. ; Playback the command line up to the character that stopped the scan
  815. ; and exit
  816. ;
  817. CLERR:    XRA    A        ; Clear "A" register
  818.     INX    D        ; Tag end of CLB
  819.     STAX    D        ; With terminator
  820.     CALL    CRLF        ; New line
  821.     LXI    D,ERRMS2    ; 'Error'
  822.     CALL    PUTS
  823.     LXI    D,ERRTAG    ; '->'
  824.     CALL    PUTS
  825.     LXI    H,TBUF+1    ; Playback CLB to error point
  826.  
  827. CLELP:    MOV    A,M        ; Character
  828.     ORA    A        ; Zero?
  829.     JZ    CLEX        ; Yes, exit
  830.     CALL    PUTCHR        ; No, output to console
  831.     INX    H        ; CLB pointer+1
  832.     JMP    CLELP        ; Continue
  833.  
  834. CLEX:    MVI    A,'?'        ; Tag line with a '?' field
  835.     CALL    PUTCHR
  836.     CALL    CRLF        ; New Line
  837.  
  838.      IF    SHOPUB
  839.     CALL    RSTPUB
  840.      ENDIF            ; SHOPUB
  841.  
  842. ;;;;;    RST    0        ; And reset CCP, all finished
  843.     JMP    EXIT2
  844.  
  845.      IF    Z80DOS OR CPM3
  846. LOKDAT:    INX    D
  847.     LDAX    D        ; Check to see if * was entered meaning
  848.     CPI    '*'        ; use current system time
  849.     JNZ    LOKDAT1        ; NZ=no
  850.     CALL    SYSTIM        ; Get the current system time
  851.     JMP    LOKDAT2        ; And continue
  852.  
  853. LOKDAT1:CALL    EVAL10        ; convert month to binary
  854.  
  855.      IF    (Z80DOS OR CPM3) AND NOT EDATE
  856.     ORA    A        ; month can't be 0
  857.     JZ    BADDATE
  858.     CPI    13        ; can't be >12
  859.     JNC    BADDATE
  860.     STA    MONTHS        ; store month
  861.     LDAX    D        ; End of input line?
  862.     ORA    A
  863.     JZ    BADDATE        ; Z=yes, a no-no
  864.     INX    D        ; Skip /
  865.     CALL    EVAL10        ; convert
  866.     ORA    A        ; day can't be 0
  867.     JZ    BADDATE
  868.     CPI    32        ; or >31
  869.     JNC    BADDATE
  870.     STA    DAYS1        ; store day
  871.     LDAX    D        ; End of input line?
  872.     ORA    A
  873.     JZ    BADDATE        ; Z=yes, a no-no
  874.      ENDIF            ; Z80DOS/CPM3
  875.  
  876.      IF    (Z80DOS OR CPM3) AND EDATE
  877.     ORA    A        ; day can't be 0
  878.     JZ    BADDATE
  879.     CPI    32        ; or >31
  880.     JNC    BADDATE
  881.     STA    DAYS1        ; store day
  882.     LDAX    D        ; End of input line?
  883.     ORA    A
  884.     JZ    BADDATE        ; Z=yes, a no-no
  885.     INX    D        ; Skip /
  886.     CALL    EVAL10        ; convert
  887.     ORA    A
  888.     JZ    BADDATE        ; month can' be 0
  889.     CPI    13        ; can't be >12
  890.     JNC    BADDATE
  891.     STA    MONTHS        ; store month
  892.      ENDIF            ; Z80DOS/CPM3
  893.  
  894.     INX    D        ; Skip /
  895.     CALL    EVAL10
  896.     STA    YEARS1        ; store year
  897.     PUSH    D
  898.     LXI    H,YEARS1    ; pt at date
  899.     CALL    BIN2JUL        ; get jul date in hl
  900.     POP    D
  901.  
  902. LOKDAT2:CALL    DOPLMI        ; Process any + or - operators
  903.     SHLD    DATCHK
  904.     LDAX    D
  905.     CPI    ' '        ; Next char a space?
  906.     JNZ    DOPTN        ; NZ=no, continue
  907. ;    LHLD    DATCH1
  908. ;    MOV    A,H
  909. ;    ORA    L
  910. ;    JZ    CLERR
  911.     LHLD    DATCHK        ; set last input date=first input date
  912.     SHLD    DATCH1
  913.     JMP    LOKDAT        ; And go try to get some more dates
  914.  
  915. SYSTIM:    PUSH    D        ; Save pointer to input line
  916.     LXI    D,ASCII        ; Tell Z80DOS/CPM3 to put time here
  917.     MVI    C,105
  918.     CALL    BDOS        ; Go get the time
  919.     LXI    D,ASCII
  920.     LDAX    D        ; Get LSB of JDAY
  921.     MOV    L,A
  922.     INX    D
  923.     LDAX    D        ; Get MSB of JDAY
  924.     MOV    H,A
  925.     POP    D        ; Get input pointer back
  926.     INX    D        ; Point ot next
  927. DOPLMI:    LDAX    D
  928.     CPI    '-'        ; Does operator want a subtraction?
  929.     JZ    SUBDAT
  930.     CPI    '+'        ; an add?
  931.     RNZ            ; NZ=no
  932.     MVI    A,1
  933.     STA    DATPLS
  934.     JMP    OPDAT
  935. SUBDAT:    XRA    A
  936.     STA    DATPLS
  937. OPDAT:    INX    D
  938.     CALL    EVAL10        ; Yes go get number
  939.     PUSH    D
  940.     MOV    E,A
  941.     XRA    A
  942.     MOV    D,A
  943.     LDA    DATPLS        ; Chec if adding
  944.     ORA    A
  945.     JNZ    DTIPLS        ; NZ=yes
  946.     MOV    A,L
  947.     SBB    E
  948.     MOV    L,A
  949.     MOV    A,H
  950.     SBB    D
  951.     MOV    H,A
  952.     POP    D
  953.     RET
  954.  
  955. DTIPLS:    DAD    D
  956.     POP    D
  957.     RET
  958.  
  959. EVAL10:    XRA    A
  960.     MOV    B,A        ; B holds current number input
  961. EVAL1:    LDAX    D        ; Get input
  962.     CPI    '/'        ; / is seperator
  963.     JZ    DEVAL10        ; Z= done
  964.     CPI    ' '
  965.     JZ    DEVAL10
  966.     CPI    '+'
  967.     JZ    DEVAL10
  968.     CPI    '-'
  969.     JZ    DEVAL10
  970.     ORA    A
  971.     JZ    DEVAL10        ; Z= at end of line
  972.     SUI    '0'        ; Verify ascii 0-9
  973.     JC    BADDATE
  974.     CPI    10
  975.     JNC    BADDATE
  976.     INX    D
  977.     MOV    C,A        ; Old*10+new
  978.     MOV    A,B
  979.     ADD    A
  980.     ADD    A
  981.     ADD    B
  982.     ADD    A
  983.     ADD    C
  984.     MOV    B,A        ; B has current
  985.     JMP    EVAL1
  986.  
  987. DEVAL10:MOV    A,B
  988.     RET
  989.  
  990. BADDATE:PUSH    D
  991.     LXI    D,BDTMES
  992.     CALL    PUTS
  993.     POP    D
  994.     JMP    CLERR
  995.  
  996. BDTMES:    DB    13,10,13,10
  997.  
  998.      IF    (Z80DOS OR CPM3) AND NOT EDATE
  999.     DB    ' *** Illegal Date Entered, form MM/DD/YY or MM/D/YY or M/DD/YY'
  1000.      ENDIF
  1001.  
  1002.      IF    (Z80DOS OR CPM3) AND EDATE
  1003.     DB    ' *** Illegal Date Entered, form DD/MM/YY or D/MM/YY or DD/M/YY'
  1004.      ENDIF
  1005.  
  1006.     DB    13,10,13,10,0
  1007. ;
  1008. ;    Binary to Julian Date routine.
  1009. ;
  1010. ; >>    hl -> yr,mo,da in bin
  1011. ; <<     hl = Julian date
  1012. ;
  1013. ;    Convert to 8080 code from the original BCD2JUL
  1014. ;
  1015. ;    by Bridger Mitchel and Howard Goldstein - 4/16/88
  1016. ;
  1017. BIN2JUL:PUSH    PSW
  1018.     PUSH    B
  1019.     PUSH    D
  1020.     MOV    A,M        ; A=yr
  1021.     INX    H
  1022.     MOV    C,M        ; C = mo
  1023.     INX    H
  1024.     PUSH    H        ; Save ptr to day
  1025.     PUSH    PSW        ; Save year
  1026. ;
  1027. ; set hl= initial julian value of 77/12/31 or if CPM3 78/1/1
  1028. ;
  1029.     LXI    H,0
  1030.     SUI    78
  1031.     JZ    B2JUL3
  1032.     JNC    B2JUL0
  1033.     ADI    100        ; <78, assume next century
  1034. B2JUL0:    MOV    B,A        ; B = # yrs > 78
  1035.     MVI    A,1        ; Init modulo 4 counter
  1036.     LXI    D,365        ; Days/yr
  1037. B2JUL1:    DAD    D        ; Calc julian val. of  (yr/01/01 - 1)
  1038.     INR    A
  1039.     ANI    3        ; Every 4 yrs,
  1040.     JNZ    B2JUL2
  1041.     INX    H        ; ..add 1 for leap year
  1042. B2JUL2:    DCR    B
  1043.     JNZ    B2JUL1
  1044. ;
  1045. ;     hl now = # days in years before current year
  1046. ;
  1047. B2JUL3:    POP    PSW
  1048.     ANI    3        ; If current yr == leap year
  1049.     JNZ    B2JUL5
  1050.     MOV    A,C
  1051.     CPI    3        ; ..and mo >= march
  1052.     JC    B2JUL5
  1053.     INX    H        ; ..add the extra day (Feb 29)
  1054. ;
  1055. B2JUL5:    MOV    B,C        ; b = month = # months +1 to sum
  1056.     LXI    D,DPERMO    ; Point at table
  1057.     JMP    B2JUL7
  1058. ;
  1059. B2JUL6:    CALL    ADDHL        ; Add # days in this month
  1060.     INX    D        ; Bump tbl ptr
  1061. B2JUL7:    DCR    B
  1062.     JNZ    B2JUL6
  1063. ;
  1064.     POP    D        ; Ptr to day
  1065.     CALL    ADDHL
  1066.     POP    D
  1067.     POP    B
  1068.     POP    PSW
  1069.     RET
  1070.  
  1071. ADDHL:    LDAX    D        ; Add day of current month
  1072. ;
  1073. ADDA2HL:ADD    L
  1074.     MOV    L,A
  1075.     RNC
  1076.     INR    H
  1077.     RET
  1078. ;
  1079. ; table of days per month (non-leap year)
  1080. ;
  1081. DPERMO:    DB    31        ; Jan
  1082.     DB    28        ; Feb
  1083.     DB    31        ; Mar
  1084.     DB    30        ; Apr
  1085.     DB    31        ; May
  1086.     DB    30        ; Jun
  1087.     DB    31        ; Jul
  1088.     DB    31        ; Aug
  1089.     DB    30        ; Sep
  1090.     DB    31        ; Oct
  1091.     DB    30        ; Nov
  1092.     DB    31        ; Dec
  1093.      ENDIF            ; Z80DOS/CPM3
  1094. ;.....
  1095. ;
  1096. ; Options input or not specified, and associated flags set.
  1097. ;
  1098. ; If D-option, swap error vectors, then start at drive A if no
  1099. ; drive specified on command line.
  1100. ;
  1101. DOPTN:
  1102.      IF    Z80DOS OR CPM3
  1103.     LHLD    DATCH1
  1104.     MOV    A,H
  1105.     ORA    L
  1106.     JZ    DOPTN1
  1107.     XCHG
  1108.     LHLD    DATCHK
  1109.     ORA    A
  1110.     DW    SBCDE
  1111.     JZ    CLERR
  1112.     JNC    DOPTN1
  1113.     LHLD    DATCHK
  1114.     SHLD    DATCH1
  1115.     XCHG
  1116.     SHLD    DATCHK
  1117. DOPTN1:
  1118.      ENDIF            ; Z80DOS/CPM3
  1119.  
  1120.     LDA    DOPFLG        ; If multi-disk flag set,
  1121.     ORA    A        ; Need to set error traps
  1122.     JNZ    AOPTN        ; If not, go check A-option
  1123.     CALL    SWAPEM        ; Swap BDOS error vector tables
  1124.     LDA    DRVFLG        ; Directory drive specified?
  1125.     ORA    A
  1126.     JNZ    AOPTN        ; No, don't reset
  1127.     MVI    A,1        ; Yes, Set FCB to A:
  1128.     STA    FCB
  1129. ;
  1130. ; Start user at 0 if A-option selected without U-option
  1131. ;
  1132. AOPTN:    LDA    AOPFLG        ; Check All-users option
  1133.     ORA    A
  1134.     JNZ    COPTN        ; Jump if not
  1135.     LDA    HOPFLG        ; Asking to show all from current?
  1136.     ORA    A
  1137.     JZ    COPTN        ; If yes, do not reset "A" to zero
  1138.     XRA    A        ; No, Start at user 0
  1139.     STA    NEWUSR
  1140.     STA    BASUSR
  1141. ;
  1142. ; Test if C-option and set indicator character 'r', else 'k'
  1143. ;
  1144. COPTN:    LDA    COPFLG        ; File sizes wanted in records?
  1145.     ORA    A
  1146.     MVI    A,'k'
  1147.     JNZ    COPTN1        ; Jump if not
  1148.     MVI    A,'r'
  1149.  
  1150. COPTN1:    STA    FSIZEC        ; Indicator char after size
  1151. ;
  1152. ; Determine whether horizontal or vertical alphabetization.
  1153. ; If X-option selected, use alternate format.
  1154. ; Set flag and fence character accordingly.
  1155. ;
  1156.     LDA    XOPFLG        ; Check for X option
  1157.     ORA    A
  1158.     LDA    VFLAG        ; Get vertical flag
  1159.     JNZ    XOPTN1        ; Jump if no X option
  1160.     CMA            ; Else swap vertical/horizontal indicator
  1161.     STA    VFLAG        ; And change VFLAG other way
  1162.  
  1163. XOPTN1:    DS    0
  1164. ;
  1165. ; The following optionally resets the disk system.  The reset must
  1166. ; be done OUTSIDE of the multiple drive loop if the $F option is
  1167. ; enabled because CP/M 1.4 will clobber the DMA buffer on reset.
  1168. ;
  1169.     LDA    ROPFLG        ; Reset Disk?
  1170.     ORA    A
  1171.     JNZ    NOOPT
  1172. ;
  1173. ; Disk reset if R option entered on command line
  1174. ;
  1175.     MVI    C,RESET
  1176.     CALL    CPM
  1177. ;
  1178. ; Validate drive code and user area numbers from the drive table
  1179. ;
  1180. NOOPT:    LXI    D,DRUMSG    ; Get drive/user error message
  1181.     PUSH    D
  1182.     LDA    FCB        ; Get directory drive code
  1183.     DCR    A        ; Normalize to range of 0-31
  1184.     CPI    HIDRV-LODRV    ; Compare with max drives on-line
  1185.     JNC    ERXIT        ; Drive error exit if out of range
  1186.  
  1187. ;     IF    MAXDRV        ; Look for MXDRV
  1188.  
  1189.      IF    ZCPR33 AND MAXDRV
  1190.     LHLD    Z3DRVL        ; Point to ENV as loaded
  1191.      ENDIF            ; ZCPR33
  1192.  
  1193.      IF    NOT ZCPR33 AND MAXDRV
  1194.     LXI    H,MXDRV        ; A(MXDRV) to HL
  1195.      ENDIF            ; NOT ZCPR33
  1196.  
  1197.      IF    MAXDRV
  1198.     MOV    L,M        ; (MXDRV) to L
  1199.      ENDIF            ; MAXDRV
  1200.  
  1201. ;     IF    MAXDRV
  1202.  
  1203.      IF    NOT ZCPR33 AND MAXDRV
  1204.     INX    H        ; +1
  1205.      ENDIF            ; NOT ZCPR33
  1206.  
  1207.      IF    MAXDRV
  1208.     CMP    L        ; Check it
  1209.     JNC    ERXIT        ; Oops if not bigger
  1210.      ENDIF            ; MAXDRV
  1211. ;
  1212. ; Skips any drives marked 0FFh, some computers do not have contiguous
  1213. ; drives, such as Heath H89, etc.
  1214. ;
  1215.     MOV    E,A        ; Drive code = table index
  1216.     MVI    D,0
  1217.     LXI    H,LODRV        ; DUTBL Pointer
  1218.     DAD    D        ; DUTBL Pointer+INDEX
  1219.     MOV    A,M        ; User Number
  1220.     ORA    A        ; Set Status
  1221.     JM    NDSK        ; If negative, ignore drive
  1222.  
  1223. ;     IF    WHEEL
  1224.  
  1225.      IF    ZCPR33 AND WHEEL
  1226.     PUSH    H
  1227.     LHLD    Z3WHLL        ; Point to enviorment
  1228.     MOV    A,M        ; Get it
  1229.     POP    H
  1230.      ENDIF            ; ZCPR33
  1231.  
  1232.      IF    NOT ZCPR33 AND WHEEL
  1233.     LDA    WHLOC        ; Get wheel byte
  1234.      ENDIF            ; NOT ZCPR33
  1235.  
  1236.      IF    WHEEL
  1237.     ORA    A        ; Check it
  1238.     JZ    USRCK        ; If reset, restrict user
  1239.     MVI    A,MXZUSR    ; If set, max user = MXZUSR
  1240.     JMP    USRCK1
  1241.      ENDIF            ; WHEEL
  1242.  
  1243. USRCK:    LXI    H,LODRV        ; DUTBL PTR
  1244.     DAD    D        ; DUTLB PTR+INDEX
  1245.     MOV    A,M        ; Load max user for this drive
  1246.  
  1247.      IF    MAXUR        ; Use low memory values if smaller
  1248.     MOV    H,A        ; Current value of MAXUSR
  1249.      ENDIF            ; MAXUR
  1250.  
  1251.      IF    ZCPR33 AND MAXUR
  1252.     PUSH    H
  1253.     LHLD    Z3USRL        ; Point to ENV
  1254.     MOV    A,M        ; Get user
  1255.     POP    H
  1256.      ENDIF            ; ZCPR33
  1257.  
  1258.      IF    NOT ZCPR33 AND MAXUR
  1259.     LDA    MXUSR        ; Alternate value
  1260.      ENDIF            ; NOT ZCPR33
  1261.  
  1262. ;     ENDIF            ; MAXUR
  1263.  
  1264.      IF    ( MAXUR AND NOT ZCPR3 ) AND NOT ZCPR33
  1265.     SBI    1        ; MAXUSR is really maximum user+1
  1266.      ENDIF            ; MAXUR AND NOT ZCPR3 AND NOT ZCPR33
  1267.  
  1268.      IF    MAXUR
  1269.     CMP    H        ; Compare the two
  1270.     JNC    USRCK1        ; OK if MAXU <= table value
  1271.     STA    MAXUSR        ; Else replace it
  1272.      ENDIF            ; MAXUR
  1273.  
  1274. USRCK1:    MOV    B,A        ; Save max user for later testing
  1275.     ANI    1FH        ; Insure in range 0-31
  1276.     STA    MAXUSR        ; Save it for later
  1277.     LXI    H,NEWUSR    ; Point to directory user area
  1278.     CMP    M        ; Compare with the maximum
  1279.     JC    ERXIT        ; User number illegal, error exit
  1280.     POP    D        ; Destroy error message pointer
  1281.     MOV    A,B        ; Check to see if this drive
  1282.     ORA    A        ; Has been mapped out
  1283.     JM    NDSK        ; Yes, skip this drive
  1284.     LXI    H,FCB+1        ; No, point to name
  1285.     MOV    A,M        ; Any name specified?
  1286.     CPI    '$'        ; Delimiter?
  1287.     JZ    WCD        ; Yes, All files
  1288.     CPI    '/'        ; Unix/ZCPR3 delimiter?
  1289.     JZ    WCD        ; Yes, All files
  1290.     CPI    '['        ; CP/M+ delimiter?
  1291.     JZ    WCD
  1292.     CPI    ' '        ; No, Filename specified
  1293.     JNZ    GOTFCB
  1294. ;
  1295. ; No FCB - make FCB all '?'
  1296. ;
  1297. WCD:    MVI    B,11        ; Filename+typ length
  1298.  
  1299. QLOOP:    MVI    M,'?'        ; Store "?" in FCB
  1300.     INX    H        ; FCB pointer+1
  1301.     DCR    B        ; FCB length-1
  1302.     JNZ    QLOOP        ; Continue
  1303.  
  1304. GOTFCB:    MVI    A,'?'        ; Force wild extent
  1305.     STA    FCB+12
  1306.     CALL    SETSRC        ; Set DMA for BDOS media change check
  1307.     LXI    H,FCB        ; Point to FCB drive code for directory
  1308.     MOV    E,M        ; Load drive code from FCB
  1309.     DCR    E        ; Normalize drive code for select
  1310.     MVI    C,SELDSK    ; Select directory drive to retrieve
  1311.     CALL    CPM        ; The proper allocation vector
  1312.     CALL    CKVER        ; Check version
  1313.     JC    V14        ; Pre-2.x...get parameters the 1.4 way
  1314.     MVI    C,DSKPAR    ; If 2.2 or MP/M...request DPB
  1315.     CALL    BDOS
  1316.     INX    H
  1317.     INX    H
  1318.     MOV    A,M        ; Load block shift
  1319.     STA    BLKSHF        ; Block Shift
  1320.     INX    H        ; Bump to block mask
  1321.     MOV    A,M        ; Load block mask
  1322.     STA    BLKMSK        ; Block Mask
  1323.     INX    H
  1324.     INX    H
  1325.     MOV    E,M        ; Get maximum block #
  1326.     INX    H
  1327.     MOV    D,M
  1328.     XCHG
  1329.     SHLD    BLKMAX        ; Maximum Block #
  1330.     XCHG
  1331.     INX    H
  1332.     MOV    E,M        ; Load directory size
  1333.     INX    H
  1334.     MOV    D,M
  1335.     XCHG
  1336.     JMP    FREE
  1337.  
  1338. V14:    LHLD    BDOS+1        ; Get parameters 1.4 style
  1339.     MVI    L,3BH        ; Point to directory size
  1340.     MOV    E,M        ; Get it
  1341.     MVI    D,0        ; Force high order to 0
  1342.     PUSH    D        ; Save for later
  1343.     INX    H        ; Point to block shift
  1344.     MOV    A,M        ; Fetch
  1345.     STA    BLKSHF        ; Save
  1346.     INX    H        ; Point to block mask
  1347.     MOV    A,M        ; Fetch it
  1348.     STA    BLKMSK        ; And save it
  1349.     INX    H
  1350.     MOV    E,M        ; Get maximum block #
  1351.     MVI    D,0
  1352.     XCHG
  1353.     SHLD    BLKMAX        ; Save it
  1354.     POP    H        ; Restore directory size
  1355.     JMP    FREE20        ; Calculate free space from alloc vector
  1356. ;
  1357. ; Calculate number of K free on selected drive now so the FREE figure
  1358. ; will not reflect either creation or additions to the DISK.DIR file.
  1359. ; Note: This routine will not always function correctly as coded.  To
  1360. ; insure the proper calculation when the $F option is specified and
  1361. ; cataloging multiple disks on a single drive, you should do a CTL-C
  1362. ; AFTER the disk to be cataloged has been readied.
  1363. ;
  1364. FREE:    SHLD    DIRMAX        ; Save max number of directory entries
  1365.     LDA    VERFLG        ; Check version number
  1366.     CPI    30H        ; CP/M 3.0?
  1367.     JC    FREE20        ; No, Use old method
  1368.     LDA    FCB        ; Load drive number
  1369.     DCR    A        ; Normalize
  1370.     MOV    E,A        ; Use compute free space BDOS call
  1371.     MVI    C,46        ; Calculate free space
  1372.     CALL    CPM
  1373.     MVI    C,3        ; Answer is a 24-bit integer
  1374.  
  1375. FRE3L1:    LXI    H,TBUF+2    ; Answer in 1st 3 bytes of TBUF
  1376.     MVI    B,3        ; Convert from records to k
  1377.     ORA    A        ; By dividing by 8
  1378.  
  1379. FRE3L2:    MOV    A,M        ; LS byte record count
  1380.     RAR            ; /2
  1381.     MOV    M,A        ; Replace
  1382.     DCX    H        ; Next byte record count
  1383.     DCR    B        ; 
  1384.     JNZ    FRE3L2        ; Loop for 3 bytes
  1385.     DCR    C
  1386.     JNZ    FRE3L1        ; Shift 3 times
  1387.     LHLD    TBUF        ; Now get result in k
  1388.     JMP    SAVFRE        ; Save Free Space
  1389.  
  1390. FREE20:    MVI    C,DSKALL    ; Allocation vector address
  1391.     CALL    BDOS
  1392.     XCHG
  1393.     LHLD    BLKMAX        ; Max Block Number
  1394.     INX    H
  1395.     LXI    B,0        ; Init block count = 0
  1396.  
  1397. GSPBYT:    PUSH    D        ; Save allocation address
  1398.     LDAX    D
  1399.     MVI    E,8        ; Set to process 8 blocks
  1400.  
  1401. GSPLUP:    RAL            ; Test bit
  1402.     JC    NOTFRE
  1403.     INX    B
  1404.  
  1405. NOTFRE:    MOV    D,A        ; Save bits
  1406.     DCX    H        ; Count down blocks
  1407.     MOV    A,L
  1408.     ORA    H
  1409.     JZ    ENDALC        ; Quit if out of blocks
  1410.     MOV    A,D        ; Restore bits
  1411.     DCR    E        ; Count down 8 bits
  1412.     JNZ    GSPLUP        ; Do another bit
  1413.     POP    D        ; Bump to next byte of allocation vector
  1414.     INX    D
  1415.     JMP    GSPBYT        ; Process it
  1416.  
  1417. ENDALC:    POP    D        ; Clear stack of allocation vector pointer
  1418.     MOV    L,C        ; Copy blocks to HL
  1419.     MOV    H,B
  1420.     LDA    BLKSHF        ; Load block shift factor
  1421.     SUI    3        ; Convert from records to k
  1422.     JZ    SAVFRE        ; Skip shifts if 1k blocks return free in HL
  1423.  
  1424. FREKLP:    DAD    H        ; Multiply blocks by k/block
  1425.     DCR    A
  1426.     JNZ    FREKLP
  1427. ;
  1428. SAVFRE:    SHLD    FREEBY        ; Save free space for output later
  1429.     XCHG
  1430.     LHLD    TOTFRE
  1431.     DAD    D
  1432.     SHLD    TOTFRE
  1433. ;
  1434. ; Reenter here on subsequent passes while in the all-users mode
  1435. ;
  1436. SETTBL:    LHLD    DIRMAX        ; Load directory maximum size
  1437.     INX    H        ; Directory size is DIRMAX+1
  1438.     DAD    H        ; Double directory size
  1439.     LXI    D,ORDER        ; Too get order table size
  1440.     DAD    D        ; Allocate order table
  1441.     SHLD    TBLOC        ; Name tbl begins where order tbl ends
  1442.     SHLD    NEXTT
  1443.     XCHG
  1444.     LHLD    BDOS+1        ; Insure we have room to continue
  1445.     MOV    A,E
  1446.     SUB    L
  1447.     MOV    A,D
  1448.     SBB    H
  1449.     JNC    OUTMEM
  1450.     CALL    CKVER        ; Set carry if pre-CP/M 2
  1451.     LDA    NEWUSR        ; Load directory user area
  1452.     MOV    E,A
  1453.     MVI    C,STUSER    ; Get the user function
  1454.     CNC    CPM        ; Set new user number if CP/M 2
  1455. ;
  1456. ; Look up the FCB in the directory
  1457. ;
  1458.     MVI    A,'?'        ; Check for wild FCB extent
  1459.     LXI    H,FCB+12
  1460.     MOV    M,A        ; Match all extents
  1461.     INX    H
  1462.     MOV    M,A        ; Match all S1 bytes
  1463.     INX    H
  1464.     MOV    M,A        ; Match all S2 bytes
  1465.     LXI    H,0
  1466.     SHLD    COUNT        ; Initialize match counter
  1467.     SHLD    TOTFIL        ; "  total file counter
  1468.     SHLD    TOTSIZ        ; "  total size counter
  1469.     CALL    SETSRC        ; Set DMA for directory search
  1470.     MVI    C,SRCHF        ; Load 'search first' function
  1471.     JMP    LOOK        ; Go search for 1st match
  1472. ;
  1473. ; Read more directory entries
  1474. ;
  1475. MORDIR:    MVI    C,SRCHN        ; Search next function
  1476.  
  1477. LOOK:    LXI    D,FCB        ; A(file control block)
  1478.     CALL    CPM        ; Read directory entry
  1479.     INR    A        ; End (0FFH)?
  1480.     JZ    SPRINT        ; Yes, sort & print what we have
  1481. ;
  1482. ; Point to directory entry
  1483. ;
  1484.     DCR    A        ; Undo previous INC A
  1485.     ANI    3        ; Make modulus 4
  1486.     ADD    A        ; Multiply
  1487.     ADD    A        ; By 32 because
  1488.     ADD    A        ; Each directory
  1489.     ADD    A        ; Entry is 32
  1490.     ADD    A        ; Bytes long
  1491.     LXI    H,TBUF+1    ; Point to buffer (skip to FN/FT)
  1492.     ADD    L        ; Point to entry
  1493.  
  1494.      IF    FATTRIB
  1495.     MOV    L,A        ; HL now point to file name
  1496.     LDA    ONEFLG        ; Looking for only attribute 1?
  1497.     ORA    A
  1498.     JNZ    NOTONE        ; NZ=no
  1499.     MOV    A,M
  1500.     ORA    A
  1501.     JP    MORDIR        ; P=not attr 1
  1502. NOTONE:    INX    H
  1503.     LDA    TWOFLG        ; Only attribute 2?
  1504.     ORA    A
  1505.     JNZ    NOTTWO        ; NZ=no
  1506.     MOV    A,M
  1507.     ORA    A
  1508.     JP    MORDIR        ; P=not attr 2
  1509. NOTTWO:    INX    H
  1510.     LDA    THRFLG        ; Only attrib 3?
  1511.     ORA    A
  1512.     JNZ    NOTTHR        ; NZ=no
  1513.     MOV    A,M
  1514.     ORA    A
  1515.     JP    MORDIR        ; P= not attr 3
  1516. NOTTHR:    INX    H
  1517.     LDA    FORFLG        ; Only attr 4?
  1518.     ORA    A
  1519.     JNZ    NOTFOR        ; NZ=no
  1520.     MOV    A,M
  1521.     ORA    A
  1522.     JP    MORDIR        ; P= not attr 4
  1523. NOTFOR:    MOV    A,L
  1524.     ADI    6
  1525.      ENDIF            ; FATTRIB
  1526.  
  1527.      IF    NOT FATTRIB
  1528.     ADI    9        ; Point to sys byte
  1529.      ENDIF            ; NOT FATTRIB
  1530.  
  1531.     MOV    L,A        ; Save (can't carry to H)
  1532.     LDA    QOPFLG        ; Find only non-$ARC files?
  1533.     ORA    A
  1534.     JNZ    OSYS        ; No, check for only $SYS files
  1535.     INX    H        ; Yes, get the archive byte
  1536.     MOV    A,M
  1537.     DCX    H
  1538.     ORA    A        ; Check bit 7 for $ARC file
  1539.     JM    MORDIR        ; If set, ignore this filename
  1540.  
  1541. OSYS:    LDA    OOPFLG        ; Find only $SYS files?
  1542.     ORA    A
  1543.     JNZ    CKSYS
  1544.     MOV    A,M        ; Yes, get system byte
  1545.     ORA    A        ; Check bit 7 for $SYS file
  1546.     JP    MORDIR        ; If not set, ignore this filename
  1547.     JMP    SYSFOK        ; Else check for a match
  1548.  
  1549. CKSYS:    LDA    SOPFLG        ; Did user request $SYS files?
  1550.     ORA    A
  1551.     JZ    SYSFOK        ; If yes, exit
  1552.     MOV    A,M        ; Get system byte back
  1553.     ORA    A        ; Check bit 7 for $SYS file
  1554.     JM    MORDIR        ; Skip that file
  1555.  
  1556. SYSFOK:    MOV    A,L        ; Go back now
  1557.     SUI    10        ; Back to user number (allocation flag)
  1558.     MOV    L,A        ; HL points to entry now
  1559.     LDA    NEWUSR        ; Get current user
  1560.     CMP    M
  1561.     JNZ    MORDIR        ; Ignore if different
  1562.  
  1563.      IF    Z80DOS OR CPM3
  1564.     PUSH    D        ; 
  1565.     PUSH    H        ; 
  1566.      ENDIF            ; Z80DOS/CPM3
  1567.  
  1568. ; CPM3 does not support BDOS function 54 as does Z80DOS, so we must check
  1569. ; if the filename in the DMA buffer has a ZERO extent [and if not fall
  1570. ; through the routine] so as to obtain the correct DATE/TIME stamp.
  1571. ; Also we have to locate the correct file in the DMA buffer and point to
  1572. ; the relevent DATE/TIME stamp in the SFCB for that filename.
  1573. ; It also checks to see if DATE/TIME stamping has been initilised.
  1574. ; CREATE & ACCESS are mutually exclusive. Either one or the other, but NOT
  1575. ; both.
  1576. ;
  1577. ; Bytes 0-3: Create or Access Date and Time stamp field
  1578. ; Bytes 4-7: Update and Time stamps field
  1579. ;
  1580. ; Offset =DMA+97+(A*10)
  1581.  
  1582.      IF    CPM3
  1583.     MOV    C,L        ; Save 'L' for later
  1584.     MVI    A,12        ; Offset to get the extent
  1585.     ADD    L        ; Add offset to point to the extent
  1586.     MOV    L,A        ; Update pointer
  1587.     XRA    A        ; Zero 'A'
  1588.     CMP    M        ; Is it a zero extent?
  1589.     MOV    L,C        ; Retreive 'L'
  1590.     JNZ    NODATA        ; NZ=no
  1591.     MVI    L,0E0H        ; Address of init byte if date/time stamp is
  1592.     MVI    A,21H        ; in use.
  1593.     CMP    M        ; Is there DATE/TIME stamps?
  1594.     MOV    L,C        ; Restore 'L'
  1595.     JNZ    NODATA        ; Not using date stamps, so exit this routine.
  1596.     MVI    A,80H        ; Is this the 1st' entry in the DMA buffer
  1597.     CMP    L        ; that we are after?
  1598.     JNZ    SECOND        ; Nope, might be the 2nd time through
  1599.     MVI    L,0E1H        ; Point to the address of the date stamp
  1600.     JMP    CONT        ; in the SFCB for the 1st entry.
  1601. SECOND:    MVI    A,0A0H        ; Is this the 2nd' entry in the DMA buffer
  1602.     CMP    L        ; that we are after?
  1603.     JNZ    THIRD        ; Nope, try for a 3rd time through
  1604.     MVI    L,0EBH        ; Point to the address of the date stamp
  1605.     JMP    CONT        ; in the SFCB for the 2nd entry.
  1606. THIRD:    MVI    L,0F5H        ; Point to the address of the date stamp
  1607.                 ; in the SFCB for the 3rd entry
  1608.      ENDIF            ; CPM3
  1609. CONT:
  1610.      IF    CPM3 AND UPDATE
  1611.     LXI    D,0        ; Point to Access/Create field
  1612.     LDA    DGOPFL
  1613.     ORA    A
  1614.     JZ    ACCESS
  1615.     LXI    D,4        ; Default to Update field
  1616.      ENDIF            ; UPDATE
  1617.  
  1618.      IF    CPM3 AND NOT UPDATE
  1619.     LXI    D,4        ; Point to Update field
  1620.     LDA    DNOPFL
  1621.     ORA    A
  1622.     JZ    ACCESS        ; Z=what is wanted
  1623.     LXI    D,0        ; Default to Access/Create field
  1624.      ENDIF            ; NOT UPDATE
  1625.  
  1626.      IF    Z80DOS
  1627.     MVI    C,54        ; Get time stamp from last search
  1628.     CALL    BDOS        ; 
  1629.     LXI    D,6        ; Point to last access field
  1630.     LDA    DGOPFL
  1631.     ORA    A
  1632.     JZ    ACCESS        ; Z=what is wanted
  1633.     LXI    D,2        ; Point to last alteration field
  1634.     LDA    DAOPFL
  1635.     ORA    A
  1636.     JZ    ACCESS        ; Z=what is wanted
  1637.     LXI    D,0        ; Point to creation field
  1638.     LDA    DNOPFL
  1639.     ORA    A
  1640.     JZ    ACCESS        ; Z=what is wanted
  1641.     LXI    D,2        ; Didn't say, so give him alteration date
  1642.      ENDIF            ; Z80DOS
  1643.  
  1644.      IF    Z80DOS OR CPM3
  1645. ACCESS:    PUSH    H
  1646.     DAD    D        ; Point to right field in returned database
  1647.     MOV    E,M        ; Get the date in Julian
  1648.     INX    H
  1649.     MOV    D,M
  1650.     MOV    A,D        ; Is requested date 0 for the file?
  1651.     ORA    E
  1652.     JNZ    ACCESS1        ; NZ=no, use it
  1653.     POP    H
  1654.     MOV    E,M        ; Was zero, use creation date
  1655.     INX    H
  1656.     MOV    D,M
  1657.     PUSH    H
  1658. ACCESS1:
  1659.     XCHG
  1660.     SHLD    DATMOD
  1661.     POP    H
  1662. ;////
  1663. NODATA:    POP    H
  1664.     POP    D
  1665.      ENDIF            ; Z80DOS/CPM3
  1666. ;
  1667. ; Move entry to table
  1668. ;
  1669.     INX    H
  1670.     XCHG            ; Entry to DE
  1671.     LHLD    NEXTT        ; Next table entry to HL
  1672.     MVI    B,11        ; Entry length (name, type, extent)
  1673.  
  1674. TMOVE:    LDAX    D        ; Get entry character
  1675.  
  1676.      IF    NOT (USELC OR REVID)
  1677.     ANI    7FH        ; Remove attributes
  1678.      ENDIF            ; NOT (USELC OR REVID)
  1679.  
  1680.     MOV    M,A        ; Store in table
  1681.     INX    D
  1682.     INX    H
  1683.     DCR    B        ; More?
  1684.     JNZ    TMOVE
  1685.     INX    D        ; DE->> S1
  1686.     INX    D        ; DE->> S2
  1687.     LDAX    D        ; Get S2 byte, oflo=int(extents/32)
  1688.     PUSH    H        ; Save HL
  1689.     MOV    L,A        ; Set up 16-bit multiply
  1690.     MVI    H,0
  1691.     MVI    B,5
  1692.     CALL    SHLL        ; HL is now # of oflo extents
  1693.     DCX    D        ; DE->> S1
  1694.     DCX    D        ; DE->> extent
  1695.     LDAX    D        ; Get extent
  1696.     ADD    L
  1697.     MOV    L,A
  1698.     MOV    A,H
  1699.     ACI    0
  1700.     MOV    H,A        ; HL has total extents
  1701.     MVI    B,7
  1702.     CALL    SHLL        ; HL has total records less last ext
  1703.     INX    D        ; DE->> S1
  1704.     INX    D        ; DE->> S2
  1705.     INX    D        ; Point to sector count
  1706.     LDAX    D        ; Get it
  1707.     ADD    L
  1708.     MOV    L,A
  1709.     MOV    A,H
  1710.     ACI    0
  1711.     MOV    H,A        ; HL has total records
  1712.     XTHL            ; Do some fancy shuffling
  1713.     XCHG
  1714.     XTHL
  1715.     XCHG
  1716.     MOV    M,D
  1717.     INX    H
  1718.     MOV    M,E
  1719.     POP    D        ; All back to normal
  1720.     INX    H
  1721.  
  1722.      IF    Z80DOS OR CPM3
  1723.     LDA    DATMOD        ; Get LSB of last modified date
  1724.     MOV    M,A        ; 
  1725.     INX    H        ; 
  1726.     LDA    DATMOD+1    ; Get MSB of last modified date
  1727.     MOV    M,A        ; 
  1728.     INX    H        ; 
  1729.      ENDIF            ; Z80DOS/CPM3
  1730.  
  1731.     SHLD    NEXTT        ; Save updated table address
  1732.     XCHG
  1733.     LHLD    COUNT        ; Bump the # of matches made
  1734.     INX    H
  1735.     SHLD    COUNT
  1736.  
  1737.      IF    Z80DOS OR CPM3
  1738.     LXI    H,15        ; Size of entry include date
  1739.      ENDIF            ; Z80DOS/CPM3
  1740.  
  1741.      IF    NOT (Z80DOS OR CPM3)
  1742.     LXI    H,13        ; Size of next entry
  1743.      ENDIF            ; NOT Z80DOS
  1744.  
  1745.     DAD    D
  1746.     XCHG            ; Future NEXTT is in DE
  1747.     LHLD    BDOS+1        ; Pick up TPA end
  1748.     MOV    A,E
  1749.     SUB    L        ; Compare NEXTT-TPA end
  1750.     MOV    A,D
  1751.     SBB    H
  1752.     JC    MORDIR        ; If TPA end > NEXTT, loop back for more
  1753.  
  1754. OUTMEM:    CALL    ERXIT        ; Exit if directory too large
  1755.     DB    'Memory',0
  1756. ;
  1757. ; Shift HL left by B bits
  1758. ;
  1759. SHLL:    DAD    H
  1760.     DCR    B
  1761.     RZ
  1762.     JMP    SHLL
  1763. ;
  1764. ; Sort and print
  1765. ;
  1766. SPRINT:    CALL    SETFOP        ; Return to file output DMA & user #
  1767.     LHLD    COUNT        ; Get file name count
  1768.     MOV    A,L
  1769.     ORA    H        ; Any found?
  1770.     JZ    PRTOTL        ; Exit if no files found
  1771.     PUSH    H        ; Save file count
  1772.     STA    SUPSPC        ; Enable leading zero suppression
  1773. ;
  1774. ; Initialize the order table
  1775. ;
  1776.     LHLD    TBLOC        ; Get start of name table
  1777.     XCHG            ; Into DE
  1778.     LXI    H,ORDER        ; Point to order table
  1779.  
  1780.      IF    Z80DOS OR CPM3
  1781.     LXI    B,15        ; Entry length including date
  1782.      ENDIF            ; Z80DOS/CPM3
  1783.  
  1784.      IF    NOT (Z80DOS OR CPM3)
  1785.     LXI    B,13        ; Entry length
  1786.      ENDIF            ; NOT Z80DOS/CPM3
  1787.  
  1788. BLDORD:    MOV    M,E        ; Save low order address
  1789.     INX    H
  1790.     MOV    M,D        ; Save high order address
  1791.     INX    H
  1792.     XCHG            ; Table address to HL
  1793.     DAD    B        ; Point to next entry
  1794.     XCHG
  1795.     XTHL            ; Save table address, load loop counter
  1796.     DCX    H        ; Count down loop
  1797.     MOV    A,L
  1798.     ORA    H        ; More?
  1799.     XTHL            ; Load table address, save loop counter
  1800.     JNZ    BLDORD        ; Yes, go do another one
  1801.     POP    H        ; Clean loop counter off stack
  1802.     LHLD    COUNT        ; Get count
  1803.     SHLD    SCOUNT        ; Save as # to sort
  1804.     DCX    H        ; Only 1 entry?
  1805.     MOV    A,L
  1806.     ORA    H
  1807.     JZ    DONE        ; Yes, so skip sort
  1808. ;
  1809. ; This sort routine is adapted from SOFTWARE TOOLS
  1810. ;
  1811.     LHLD    SCOUNT        ; Number of entries
  1812.  
  1813. L1:    ORA    A        ; Clear carry
  1814.     MOV    A,H        ; GAP=GAP/2
  1815.     RAR
  1816.     MOV    H,A
  1817.     MOV    A,L
  1818.     RAR
  1819.     MOV    L,A
  1820.     ORA    H        ; Is it zero?
  1821.     JZ    DONE        ; Then none left
  1822.     MOV    A,L        ; Make gap odd
  1823.     ORI    1
  1824.     MOV    L,A
  1825.     SHLD    GAP
  1826.     INX    H        ; I=GAP+1
  1827.  
  1828. L2:    SHLD    I
  1829.     XCHG
  1830.     LHLD    GAP
  1831.     MOV    A,E        ; J=I-GAP
  1832.     SUB    L
  1833.     MOV    L,A
  1834.     MOV    A,D
  1835.     SBB    H
  1836.     MOV    H,A
  1837.  
  1838. L3:    SHLD    J
  1839.     XCHG
  1840.     LHLD    GAP        ; JG=J+GAP
  1841.     DAD    D
  1842.     SHLD    JG
  1843.     CALL    COMPARE        ; Compare (J) and (JG)
  1844.     JP    L4        ; If A(J)<=A(JG)
  1845.     LHLD    J
  1846.     XCHG
  1847.     LHLD    JG
  1848.     CALL    SWAP        ; Exchange a(J) and a(JG)
  1849.     LHLD    J        ; J=J-GAP
  1850.     XCHG
  1851.     LHLD    GAP
  1852.     MOV    A,E
  1853.     SUB    L
  1854.     MOV    L,A
  1855.     MOV    A,D
  1856.     SBB    H
  1857.     MOV    H,A
  1858.     JM    L4        ; If J>0 go to l3
  1859.     ORA    L        ; Check for zero
  1860.     JZ    L4
  1861.     JMP    L3
  1862.  
  1863. L4:    LHLD    SCOUNT        ; For later
  1864.     XCHG
  1865.     LHLD    I        ; I=I+1
  1866.     INX    H
  1867.     MOV    A,E        ; If I<=n go to l2
  1868.     SUB    L
  1869.     MOV    A,D
  1870.     SBB    H
  1871.     JP    L2
  1872.     LHLD    GAP
  1873.     JMP    L1
  1874. ;
  1875. ; Sort is all done - print entries
  1876. ;
  1877. DONE:    LDA    FOPFLG        ; File output flag
  1878.     ORA    A        ; Set?
  1879.     JNZ    NOOUT        ; No, skip open
  1880. ;
  1881. ; If all user option enabled, and we're not on the first pass, then the
  1882. ; output file is already open and positioned, so we can skip the open.
  1883. ;
  1884.     LXI    H,OPNFLG    ; Output file open flag
  1885.     CMP    M        ; A=0,set Z if OPNFLG=0 also
  1886.     JNZ    NOOUT        ; If OPNFLG not zero, skip open
  1887.     DCR    M        ; Else, set OPNFLG for next user #
  1888. ;
  1889. ; First pass on file append - prepare DISK.DIR to receive new
  1890. ; or appended output.
  1891. ;
  1892.     LXI    D,OUTFCB    ; Does output file exist?
  1893.     MVI    C,SRCHF
  1894.     CALL    CPM
  1895.     INR    A
  1896.     JNZ    OPENIT        ; Yes, open for processing
  1897.     MVI    C,MAKE        ; Else, create output file
  1898.     CALL    CPM
  1899.     INR    A        ; Successful?
  1900.     JNZ    NOOUT        ; Yes, Continue
  1901. ;
  1902. ; If make or open fails, declare error
  1903. ;
  1904. OPNERR:    CALL    ERXIT
  1905.     DB    'Open',0
  1906. ;
  1907. WRTERR:    CALL    ERXIT
  1908.     DB    'Write',0
  1909. ;
  1910. ; Output file already exists - open it and position
  1911. ; it to the last record of the last extent.
  1912. ;
  1913. OPENIT:    MVI    C,OPEN        ; Open 1st extent of output file
  1914.     CALL    CPM
  1915.     INR    A
  1916.     JZ    OPNERR        ; Bad deal if 1st won't open
  1917.  
  1918. OPNMOR:    LDA    OUTFCB+15    ; Record count (RC)
  1919.     CPI    128
  1920.     JC    LSTEXT        ; If RC<128, this is last extent
  1921.     LXI    H,OUTFCB+12
  1922.     INR    M        ; Else, increment to next extent
  1923.     MVI    C,OPEN        ; Try to open it
  1924.     CALL    CPM
  1925.     INR    A
  1926.     JNZ    OPNMOR        ; Continue opening extents to end
  1927.     DCR    M        ; Then, reopen preceding extent
  1928.     MVI    C,OPEN
  1929.     CALL    CPM
  1930.     LDA    OUTFCB+15    ; Get RC for the last extent
  1931. ;
  1932. ; At this point, OUTFCB is opened to the last extent of the file, so
  1933. ; read in the last record in the last extent.
  1934. ;
  1935. LSTEXT:    ORA    A        ; Is this extent empty?
  1936.     JZ    NOOUT        ; Yes, starting a clean slate
  1937.     DCR    A        ; Normalize record count
  1938.     STA    OUTFCB+32    ; Set record number to read
  1939.     MVI    C,READ        ; Read last record of file
  1940.     CALL    CPM
  1941.     ORA    A        ; Successful read?
  1942.     JZ    RDOK        ; Yes, scan for EOF mark
  1943.  
  1944. APERR:    CALL    ERXIT
  1945.     DB    'Append',0
  1946. ;
  1947. ; We now have the last record in the file in the buffer. Scan the last
  1948. ; record for the EOF mark, indicate where we can start adding data.
  1949. ;
  1950. RDOK:    LXI    H,OUTBUF    ; Point to output buffer start
  1951.     MVI    B,128        ; Output buffer length
  1952.  
  1953. SCAN:    MOV    A,M        ; Character
  1954.     CPI    'Z'-40H        ; End of file?
  1955.     JZ    RESCR        ; Yes, save pointers and reset CR
  1956.     INX    H        ; Pointer+1
  1957.     DCR    B        ; Length-1
  1958.     JNZ    SCAN        ; Continue to end of buffer
  1959. ;
  1960. ; If an explicit EOF mark or an implied EOF (last record is full) in
  1961. ; the last buffer, move the FCB record and extent pointer back to cor-
  1962. ; rect for the read operation so the first write operation will replace
  1963. ; the last record of the DISK.DIR file.
  1964. ;
  1965. RESCR:    PUSH    H        ; Save EOF buffer pointer
  1966.     PUSH    B        ; Save EOF buffer remaining
  1967.     LXI    H,OUTFCB+32    ; Load current record again
  1968.     DCR    M        ; Record-1
  1969.     JP    SAMEXT        ; If CR>=0, still in same extent
  1970.     LXI    H,OUTFCB+12    ; Else, move to previous extent
  1971.     DCR    M
  1972.     MVI    C,OPEN        ; Then, reopen previous extent
  1973.     CALL    CPM
  1974.     INR    A
  1975.     JZ    APERR        ; Append error if can not reopen
  1976.     LDA    OUTFCB+15    ; Else,
  1977.     DCR    A        ; Position to last record of
  1978.     STA    OUTFCB+32    ; The extent
  1979.  
  1980. SAMEXT:    POP    PSW        ; Recall EOF location in buffer
  1981.     STA    BUFCNT        ; Set buffer counter
  1982.     POP    H        ; Recall next buffer pointer
  1983.     SHLD    BUFPNT        ; Set pointer for first addition
  1984.  
  1985. NOOUT:    LDA    FIRSTT        ; First time through?
  1986.     ORA    A
  1987.     JNZ    NOVOPT        ; No, we've been here before
  1988.     MVI    A,0FFH        ; Yes,
  1989.     STA    FIRSTT        ; Set first time flag
  1990.     LDA    VOPFLG        ; Version display flag
  1991.     ORA    A        ; Set?
  1992.     JNZ    NOVOPT        ; No, skip version print
  1993.     LXI    D,VERNAME    ; Yes, print version
  1994.     CALL    PUTS        ; Print the string
  1995.     CALL    CRLF
  1996.  
  1997. NOVOPT:    LHLD    COUNT
  1998.     SHLD    LCOUNT
  1999.     LXI    H,0
  2000.     SHLD    LBTOTL
  2001.     SHLD    LMTOTL
  2002.     LXI    H,ORDER        ; Initialize order table pointer
  2003.     SHLD    NEXTL
  2004.     SHLD    NEXTT
  2005.     LDA    VFLAG        ; Check display form
  2006.     ORA    A
  2007.     JNZ    NEWLIN        ; Jump if not vertical
  2008.     LHLD    COUNT        ; Code computes end of name table
  2009.     CALL    MULT13        ; (or start of second table
  2010.     XCHG            ; where files to be stored after
  2011.     LHLD    TBLOC        ; redundant extents removed)
  2012.     DAD    D
  2013.     SHLD    NEWPTR        ; Save it twice
  2014.     SHLD    XPOINT        ; For later
  2015.  
  2016. ENTRY:
  2017.      IF    CPM3
  2018.  
  2019. ; We need to check that we have the first extent of the filename, as it is the
  2020. ; only extent that contains a valid DATE
  2021.     LHLD    NEXTT        ; Address of filename
  2022.     MOV    E,M
  2023.     INX    H
  2024.     MOV    D,M
  2025.     XCHG
  2026.     LXI    D,11
  2027.     DAD    D        ; Point to the extent field
  2028.     XRA    A
  2029.     CMP    M        ; Is it zero? 
  2030.     JNZ    NOEXTZ        ; Nope, then we don't want to know about it
  2031.     INX    H
  2032.     MVI    A,81H
  2033.     CMP    M        ; Is it > than 129?
  2034.     JC    NOEXTZ        ; If it is, than it's not the first extent
  2035.     INX    H        ; Got this far, must be the first extent
  2036.     MOV    E,M        ; Get the DATE
  2037.     INX    H        ; into the
  2038.     MOV    D,M        ; DE regester pair
  2039.     XCHG
  2040.     SHLD    LATDAT        ; Save the DATE for latter on
  2041.      ENDIF            ; CPM3
  2042. ;
  2043. ; Output directory files we've matched
  2044. ;
  2045. NOEXTZ:    LHLD    COUNT        ; Files matched count
  2046.     DCX    H        ; Count-1
  2047.     SHLD    COUNT
  2048.     MOV    A,H        ; Is this the last file?
  2049.     ORA    L
  2050.     JZ    OKPRNT        ; Yes, last file so skip compare
  2051. ;
  2052. ; Compare each entry to make sure that it isn't part of a multiple
  2053. ; extent file.    Go only when we have the last extent of the file.
  2054. ;
  2055.     PUSH    B        ; Save number of columns
  2056.     LDA    VFLAG        ; Check display form
  2057.     ORA    A
  2058.     CNZ    CKABRT        ; If horiz, check for abort from keyboard
  2059.     LHLD    NEXTT
  2060.     MVI    A,11
  2061.     CALL    COMPR        ; Does this entry match next one?
  2062.     POP    B        ; Restore number of columns
  2063.     JNZ    OKPRNT        ; No, print it
  2064. NOKPRN:    INX    H
  2065.     INX    H        ; Skip, highest extent last in list
  2066.     SHLD    NEXTT
  2067.     JMP    ENTRY        ; Loop back for next lowest extent
  2068. ;
  2069. ; VLIST substitution. If VLIST option chosen, OKPRINT moves unique
  2070. ; filenames and sizes in "k" to a second table above the first for
  2071. ; use later.
  2072. ;
  2073. OKPRNT:    
  2074.      IF    CPM3
  2075.     PUSH    H
  2076.     PUSH    D
  2077.     PUSH    B
  2078.     MOV    E,M        ; Get the address of
  2079.     INX    H        ; the filename
  2080.     MOV    D,M        ; into the DE regester pair
  2081.     LHLD    LATDAT        ; Recover the DATE
  2082.     XCHG
  2083.     LXI    B,13
  2084.     DAD    B        ; Point to the DATE field
  2085.     MOV    M,E        ; Replace the now corrupted DATE
  2086.     INX    H        ; with the real DATE into the
  2087.     MOV    M,D        ; now new DATE field
  2088.      ENDIF            ; CPM3
  2089.  
  2090.      IF    Z80DOS
  2091.     PUSH    H
  2092.     PUSH    D
  2093.     PUSH    B
  2094.      ENDIF            ; Z80DOS
  2095.  
  2096.      IF    Z80DOS OR CPM3
  2097.     LHLD    NEXTT        ; Get order table pointer
  2098.     MOV    E,M        ; Get low order address
  2099.     INX    H
  2100.     MOV    D,M        ; Get high order address
  2101.     LXI    H,13
  2102.     DAD    D
  2103.     MOV    E,M
  2104.     INX    H
  2105.     MOV    D,M
  2106.     LHLD    DATCHK        ; Get the date we are looking for
  2107.     MOV    A,H
  2108.     ORA    L
  2109.     JZ    GDTMTC        ; Z=not looking
  2110.     LHLD    DATCH1
  2111.     MOV    A,H
  2112.     ORA    L
  2113.     JZ    ONEDAT        ; Z=only 1 date on input line
  2114.     DW    SBCDE
  2115.     JZ    GDTMTC        ; Z=file date=low date
  2116.     JNC    NDTMTC        ; NC=file date < low date, no output
  2117.     LHLD    DATCHK
  2118.     ORA    A
  2119.     DW    SBCDE
  2120.     JZ    GDTMTC        ; Z=file date=high date
  2121.     JNC    GDTMTC        ; NC=file date < high date
  2122.     JMP    NDTMTC        ; File date > high date
  2123. ONEDAT:    LHLD    DATCHK
  2124.     MOV    A,H
  2125.     CMP    D        ; Check if given date >,=,< the files date
  2126.     JZ    CHDLOW        ; High EQ, check low
  2127.     JC    DATLT        ; C=LT
  2128.     JMP    DATGE        ; Given date GT file date
  2129. CHDLOW:    MOV    A,L        ; Check low byte of date vs. file date
  2130.     CMP    E
  2131. DATGE:    MVI    A,0        ; Assume EQ
  2132.     JC    DATLT        ; C= given LT files date
  2133.     JZ    DATFLG        ; Z= they are EQ
  2134.     MVI    A,2        ; Given GT files date
  2135.     JMP    DATFLG
  2136. DATLT:    MVI    A,1        ; Given was less than files
  2137. DATFLG:    STA    DTMTCH
  2138.     LDA    DEOPFL        ; What kind of date match?
  2139.     ORA    A
  2140.     JZ    DTEXAC        ; Z=exact
  2141.     LDA    DPOPFL
  2142.     ORA    A
  2143.     JZ    DTABVE        ; Z=GE
  2144.     LDA    DMOPFL        ; LT wanted?
  2145.     ORA    A
  2146.     JNZ    DTEXAC        ; NZ=no, didn't tell us so do anything but gave
  2147.                 ; us a date so assume want exact match
  2148.     LDA    DTMTCH
  2149.     CPI    2
  2150.     JZ    GDTMTC        ; Date was below and they wanted below
  2151. NDTMTC:
  2152.     POP    B
  2153.     POP    D
  2154.     POP    H
  2155.     PUSH    H
  2156.     LHLD    COUNT
  2157.     MOV    A,L
  2158.     ORA    H
  2159.     POP    H
  2160.     JZ    PRTOTL
  2161.     JMP    NOKPRN
  2162.  
  2163. DTEXAC:    LDA    DTMTCH        ; They wanted exact, was it?
  2164.     ORA    A
  2165.     JZ    GDTMTC        ; Z=yes
  2166.     JMP    NDTMTC
  2167. DTABVE:    LDA    DTMTCH        ; They wanted GE
  2168.     CPI    1
  2169.     JZ    GDTMTC        ; Z=G
  2170.     ORA    A
  2171.     JNZ    NDTMTC        ; Must be 2, so not equal
  2172. GDTMTC:    POP    B
  2173.     POP    D
  2174.     POP    H
  2175.      ENDIF            ; Z80DOS/CPM3
  2176.     
  2177.     LHLD    NEXTT        ; Get order table pointer
  2178.     MOV    E,M        ; Get low order address
  2179.     INX    H
  2180.     MOV    D,M        ; Get high order address
  2181.     INX    H
  2182.     SHLD    NEXTT        ; Save updated table pointer
  2183.     XCHG            ; Table entry to HL
  2184.     LDA    VFLAG        ; Check display form
  2185.     ORA    A
  2186.     JNZ    OKPR1        ; Jump if not vertical
  2187.     PUSH    H        ; Save address of byte to be moved
  2188.     LHLD    NEWPTR        ; Address in new table to put byte
  2189.     PUSH    H        ; Save address
  2190.  
  2191.      IF    Z80DOS OR CPM3
  2192.     LXI    D,15        ; Update address including date
  2193.      ENDIF            ; Z80DOS/CPM3
  2194.  
  2195.      IF    NOT (Z80DOS OR CPM3)
  2196.     LXI    D,13        ; Update address
  2197.      ENDIF            ; NOT Z80DOS/CPM3
  2198.  
  2199.     DAD    D
  2200.     SHLD    NEWPTR        ; Save for later (end of table)
  2201.     POP    H        ; Set current move  to    address
  2202.     XCHG            ; Swap pointers
  2203.     POP    H        ; Set current move from address
  2204.  
  2205.      IF    Z80DOS OR CPM3
  2206.     LXI    B,11
  2207.     DW    ZMOVE        ; Z80's LDIR
  2208.      ENDIF            ; Z80DOS/CPM3
  2209.  
  2210.      IF    NOT (Z80DOS OR CPM3)
  2211.     MVI    B,11        ; Filename.typ length
  2212.     CALL    MOVE        ; Move it
  2213.      ENDIF            ; NOT Z80DOS/CPM3
  2214.  
  2215.      IF    Z80DOS OR CPM3
  2216.     PUSH    H
  2217.      ENDIF            ; Z80DOS
  2218.  
  2219.     PUSH    D
  2220.     JMP    OKPR2
  2221.  
  2222. OKPR1:    MVI    B,8        ; Filename length
  2223.     CALL    PUTSB        ; Output
  2224.     MVI    A,'.'        ; Period after filename
  2225.     CALL    PUTCHR        ; Output
  2226.     MVI    B,3        ; Filetype length
  2227.     CALL    PUTSB        ; Output
  2228.  
  2229.      IF    Z80DOS OR CPM3
  2230.     LDA    NODFLG
  2231.     ORA    A
  2232.     JNZ    NOD1
  2233.     CALL    DISDAT
  2234. NOD1:
  2235.      ENDIF            ; Z80DOS/CPM3
  2236.  
  2237. OKPR2:    
  2238.     CALL    SIZEFL
  2239.     LHLD    TOTSIZ        ; DE = rounded size in K
  2240.     DAD    D        ; Add to total used
  2241.     SHLD    TOTSIZ
  2242.     LHLD    TOTFIL        ; Increment filecount
  2243.     INX    H
  2244.     SHLD    TOTFIL
  2245.     XCHG
  2246.     LDA    COPFLG        ; Size wanted in records?
  2247.     ORA    A
  2248.     JNZ    OKPR3        ; Jump if not
  2249.     LHLD    FILERC        ; Else get record count
  2250.  
  2251. OKPR3:    LDA    VFLAG        ; Check display form
  2252.     ORA    A
  2253.     JNZ    OKPR4        ; Jump if not vertical
  2254.     POP    D        ; A(size to go)
  2255.     MOV    A,H        ; Move size to table two
  2256.     STAX    D
  2257.     INX    D
  2258.     MOV    A,L
  2259.     STAX    D
  2260.  
  2261.      IF    Z80DOS OR CPM3
  2262.     POP    H        ; Currently pointing to file size
  2263.     INX    H        ; Skip size
  2264.     INX    H
  2265.     INX    D
  2266.     MOV    A,M        ; Get LSB of date
  2267.     STAX    D        ; Save it away
  2268.     INX    D
  2269.     INX    H
  2270.     MOV    A,M        ; Ditto for MSB of date
  2271.     STAX    D
  2272.      ENDIF            ; Z80DOS/CPM3
  2273. ;
  2274. ; One File Moved - Test to see if we have to move another
  2275. ;
  2276.     LHLD    COUNT        ; Current file counter
  2277.     MOV    A,H
  2278.     ORA    L
  2279.     JZ    PRTOTL        ; Zero, output summary
  2280.     JMP    ENTRY
  2281. ;
  2282. ; Output the size of the individual file
  2283. ;
  2284. OKPR4:    CALL    DECPRT        ; Print it
  2285.     LDA    FSIZEC        ; Follow with 'k' or 'r'
  2286.     CALL    PUTCHR
  2287. ;
  2288. ; One file output - test to see if we have to output another one.
  2289. ;
  2290.     LHLD    COUNT        ; Current file counter
  2291.     MOV    A,H
  2292.     ORA    L        ; Zero?
  2293.     JZ    PRTOTL        ; Yes, exit to summary output
  2294. ;
  2295. ; At least one more file to output,
  2296. ; can we put it on the current line?
  2297. ;
  2298.     DCR    C
  2299.     PUSH    PSW
  2300.     CNZ    FENCE        ; If room left output fence character
  2301.     POP    PSW
  2302.     JNZ    ENTRY        ; Output another file
  2303. ;
  2304. ; Current line full, start a new one
  2305. ;
  2306. NEWLIN:
  2307.      IF    Z80DOS OR CPM3
  2308.     MVI    C,2        ; 2 names per line
  2309.     LDA    NODFLG
  2310.     ORA    A
  2311.     JZ    NOD2        ; WAS NZ,NOD2
  2312.     MVI    C,4
  2313. NOD2:
  2314.      ENDIF            ; Z80DOS/CPM3
  2315.  
  2316.      IF    NOT (Z80DOS OR CPM3)
  2317.     MVI    C,4        ; Reset names per line counter
  2318.      ENDIF            ; NOT Z80DOS/CPM3
  2319.  
  2320.     CALL    CRLF        ; Space down to next line
  2321.     JMP    ENTRY        ; Output another file
  2322. ;.....
  2323. ;
  2324. ; Compute the size of the file/library and update our summary datum.
  2325. ; This has been changed into a subroutine so that both the file size
  2326. ; computation and a library size (when printing out library members)
  2327. ; can be computed in K.
  2328. ;
  2329. SIZEFL:    MOV    D,M
  2330.     INX    H
  2331.     MOV    E,M        ; Size in DE (records)
  2332.     XCHG
  2333.     SHLD    FILERC        ; Save record count
  2334.     XCHG
  2335.     LDA    BLKMSK
  2336.     PUSH    PSW
  2337.     ADD    E
  2338.     MOV    E,A
  2339.     MOV    A,D
  2340.     ACI    0
  2341.     MOV    D,A
  2342.     POP    PSW
  2343.     CMA
  2344.     ANA    E
  2345.     MOV    E,A
  2346.     MVI    B,3
  2347.  
  2348. SHRR:    MOV    A,D
  2349.     ORA    A
  2350.     RAR
  2351.     MOV    D,A
  2352.     MOV    A,E
  2353.     RAR
  2354.     MOV    E,A
  2355.     DCR    B
  2356.     JNZ    SHRR
  2357.     RET
  2358. ;
  2359. ; Print HL in decimal with leading zero suppression
  2360. ;
  2361. DECPRT:    XRA    A        ; Clear leading zero flag
  2362.     STA    LZFLG
  2363.     LXI    D,-10000
  2364.     LDA    SUPSPC
  2365.     PUSH    PSW
  2366.     XRA    A
  2367.     STA    SUPSPC
  2368.     CALL    DIGIT
  2369.     POP    PSW
  2370.     STA    SUPSPC
  2371.     LXI    D,-1000        ; Print 1000's digit
  2372.     CALL    DIGIT
  2373.     LXI    D,-100        ; Etc.
  2374.     CALL    DIGIT
  2375.     LXI    D,-10
  2376.     CALL    DIGIT
  2377.     MVI    A,'0'        ; Get 1's digit
  2378.     ADD    L
  2379.     JMP    PUTCHR
  2380.  
  2381. DIGIT:    MVI    B,'0'        ; Start off with ASCII 0
  2382.  
  2383. DIGLP:    PUSH    H        ; Save current remainder
  2384.     DAD    D        ; Subtract
  2385.     JNC    DIGEX        ; Quit on overflow
  2386.     POP    PSW        ; Throw away remainder
  2387.     INR    B        ; Bump digit
  2388.     JMP    DIGLP        ; Loop back
  2389.  
  2390. DIGEX:    POP    H        ; Restore pointer
  2391.     MOV    A,B
  2392.     CPI    '0'        ; Zero digit?
  2393.     JNZ    DIGNZ        ; No, type it
  2394.     LDA    LZFLG        ; Leading zero?
  2395.     ORA    A
  2396.     MVI    A,'0'
  2397.     JNZ    PUTCHR        ; Print digit
  2398.     LDA    SUPSPC        ; Get space suppression flag
  2399.     ORA    A        ; See if printing file totals
  2400.     RZ            ; Yes, don't give leading spaces
  2401.     JMP    SPACE        ; Leading zero..print space
  2402. ;
  2403. DIGNZ:    STA    LZFLG        ; Leading zero flag set
  2404.     JMP    PUTCHR        ; Print leading zero & digit
  2405. ;.....
  2406. ;
  2407. ;-----------------------------------------------------------------------
  2408. ;          VLIST subroutines begin here
  2409. ;
  2410. ;Multiply contents of HL register by 13
  2411. ;
  2412. MULT13:    MOV    D,H
  2413.     MOV    E,L
  2414.     DAD    H
  2415.     DAD    D
  2416.     DAD    H
  2417.     DAD    H
  2418.     DAD    D
  2419.  
  2420.      IF    Z80DOS OR CPM3
  2421.     DAD    D        ; Actually by 15
  2422.     DAD    D        ; 
  2423.      ENDIF            ; Z80DOS/CPM3
  2424.  
  2425.     RET
  2426. ;.....
  2427. ;
  2428. ; Main VLIST subroutine to output a filename and column delimiter
  2429. ;
  2430. VENTRY:    STA    VSFRST
  2431.     CALL    PFILE1        ; Routine to print a filename
  2432.     RZ            ; If at end of line return with zero set
  2433.     CC    FENCE        ; Print column delimiter if more
  2434.     LHLD    JUMPER        ; Put the jumper back in DE
  2435.     XCHG
  2436.     ORI    1        ; Insure non zero return
  2437.     RET
  2438. ;.....
  2439. ;
  2440. PFILE1:    PUSH    H
  2441.     PUSH    D
  2442.     XCHG
  2443.     LHLD    NEWPTR
  2444.     MOV    A,H
  2445.     CMP    D
  2446.     JNC    PFILE2
  2447.     MOV    A,L
  2448.     CMP    E
  2449.     POP    D
  2450.     POP    H
  2451.     RZ
  2452.     JNC    PFILE3
  2453.     XRA    A
  2454.     RET
  2455. PFILE2:    POP    D
  2456.     POP    H
  2457. PFILE3:
  2458.     MOV    A,M        ; Let's see what we have
  2459.     CPI    0FEH
  2460.     RNC
  2461.     ANI    7FH        ; Strip parity bit
  2462.     PUSH    B        ; Save number of columns
  2463.     MVI    B,8        ; Print filename and type
  2464.     CALL    PUTSB
  2465.     MVI    A,'.'
  2466.     CALL    PUTCHR
  2467.     MVI    B,3
  2468.     CALL    PUTSB
  2469.     
  2470.      IF    Z80DOS OR CPM3
  2471.     LDA    NODFLG
  2472.     ORA    A
  2473.     JNZ    NOD3
  2474.     CALL    DISDAT        ; Display the date
  2475. NOD3:
  2476.      ENDIF            ; Z80DOS/CPM3
  2477.  
  2478.     MOV    D,M        ; Get it into DE
  2479.     INX    H
  2480.     MOV    E,M
  2481.     XCHG            ; HL <-> DE
  2482.     CALL    DECPRT        ; Print it out
  2483.     LDA    FSIZEC        ; Follow with 'k' or 'r'
  2484.     CALL    PUTCHR
  2485.     POP    B        ; Load number of columns
  2486.     LHLD    TOTFIL        ; Load number of files left
  2487.     DCX    H        ; # files-1
  2488.     SHLD    TOTFIL        ; Resave it
  2489.     MOV    A,H
  2490.     ORA    L        ; Zero yet?
  2491.     RZ            ; Yes, no more files
  2492.     DCR    C        ; No, decrement it
  2493.     STC            ; Force carry on
  2494.     RET            ; This return
  2495. ;.....
  2496. ;
  2497. ;              End of VLIST routines
  2498. ;-----------------------------------------------------------------------
  2499. ;
  2500. ; Show total space and files used
  2501. ;
  2502. PRTOTL:    XRA    A
  2503.     STA    VSFRST
  2504.     LDA    VFLAG        ; Check display form
  2505.     ORA    A
  2506.     JZ    PRTOT1        ; Jump if vertical
  2507.     LDA    LOPFLG
  2508.     ORA    A
  2509.     JNZ    PRTOT1
  2510.     LHLD    TOTFIL        ; How many files matched?
  2511.     MOV    A,H
  2512.     ORA    L
  2513.     CNZ    PRTLMEM        ; Skip .LBR check if none found
  2514.  
  2515. PRTOT1:    XRA    A        ; Get a zero to
  2516.     STA    SUPSPC        ; Suppress leading spaces in totals
  2517.     LHLD    TOTFIL        ; How many files matched?
  2518.     MOV    A,H
  2519.     ORA    L
  2520.     JZ    NXTUSR        ; Skip summary if none found
  2521.     PUSH    H        ; Save TOTFIL
  2522.     STA    FNDFLG        ; Set file found flag
  2523.     LDA    VFLAG        ; Check display form
  2524.     ORA    A
  2525.     JNZ    PRTOT3        ; Horizontal = 0FFh, exit if not zero
  2526.     LDA    SOHFLG
  2527.     ORA    A
  2528.     JZ    PRTOT2
  2529.     XRA    A
  2530.     STA    SOHFLG
  2531.     JMP    PRTOT3
  2532.  
  2533. PRTOT2:    CALL    CRLF
  2534.  
  2535. PRTOT3:    LXI    D,CRLSPC    ; CR,LF,'      ',0
  2536.     CALL    PUTS
  2537.  
  2538.      IF    ULINE
  2539.     LDA    BYEACT        ; Is BYE active
  2540.     ORA    A
  2541.     JZ    YODRIV        ; BYE active=Z
  2542.     LXI    D,ULON        ; Turn underline on
  2543.     CALL    COUTS        ; If not null
  2544.      ENDIF            ; ULINE
  2545.  
  2546. YODRIV:    LXI    D,TOTMS1    ; Print "' Drive '"
  2547.     CALL    PUTS
  2548.     LDA    FCB
  2549.     ADI    'A'-1
  2550.     CALL    PUTCHR        ; Output the drive code
  2551.     CALL    CKVER
  2552.     JC    NOUSER
  2553.     CALL    PUTUSR        ; Output user number
  2554.     MVI    A,':'
  2555.     CALL    PUTCHR
  2556.  
  2557.      IF    NDIRS
  2558.     MVI    A,' '
  2559.     CALL    PUTCHR
  2560.     CALL    NAMDIR
  2561.      ENDIF            ; NDIRS
  2562.  
  2563.     LDA    USRNR
  2564.     CPI    10
  2565.     LXI    D,NOFMS2
  2566.     JC    $+6
  2567.     LXI    D,NOFMS2+1    ; Print some spaces
  2568.     CALL    PUTS
  2569.  
  2570. NOUSER:    LXI    D,TOTMS6    ; Print " Files: "
  2571.     CALL    PUTS
  2572.     POP    H        ; Recall TOTFIL
  2573.     XCHG
  2574.     LHLD    TOTFL1        ; Get total number of files so far
  2575.     DAD    D        ; Add in number this DU
  2576.     SHLD    TOTFL1        ; And save it away
  2577.     XCHG
  2578.     CALL    DECPRT        ; Print # of files matched
  2579.     LXI    D,TOTMS4    ; No CRLF needed, display > 40
  2580.     CALL    PUTS
  2581.     LHLD    TOTSIZ        ; Total k used by matched files
  2582.     XCHG
  2583.     LHLD    TOTSZ1        ; Get running total of all files
  2584.     DAD    D
  2585.     SHLD    TOTSZ1        ; And put it back
  2586.     XCHG
  2587.     CALL    DECPRT        ; Print file size
  2588.     LXI    D,TOTMS5    ; Print "k"
  2589.     CALL    PUTS
  2590.     CALL    PRTFRE        ; Print free space remaining
  2591.  
  2592.      IF    ULINE
  2593.     LDA    BYEACT        ; Bye active?
  2594.     ORA    A        ; 
  2595.     JZ    NPRNT        ; Yes, skip ULINE off
  2596.     LXI    D,ULOFF        ; Turn off underline
  2597.     CALL    COUTS        ; If not null
  2598.      ENDIF            ; ULINE
  2599. ;
  2600. ; Summary line printed, now print detail files, first compute total
  2601. ; printout lines.
  2602. ;
  2603. NPRNT:    LDA    VFLAG        ; Check display form
  2604.     ORA    A
  2605.     JNZ    NXTUSR        ; Jump if horizontal
  2606.  
  2607.      IF    Z80DOS OR CPM3
  2608.     LXI    B,1
  2609.     LDA    NODFLG
  2610.     ORA    A
  2611.     JZ    NOD4
  2612.     LXI    B,3
  2613. NOD4:
  2614.      ENDIF            ; Z80DOS/CPM3
  2615.  
  2616.      IF    NOT (Z80DOS OR CPM3)
  2617.     LXI    B,3
  2618.      ENDIF            ; NOT Z80DOS/CPM3
  2619.  
  2620.     MOV    A,C        ; Get number of names per line
  2621.     CMA            ; Negative of number of columns
  2622.     MOV    E,A        ; Into DE
  2623.     MVI    D,0FFH
  2624.     LHLD    TOTFIL        ; Load total number of files
  2625.     DAD    B        ; Round up to a full line
  2626.     MVI    C,0FFH
  2627.  
  2628. NPRNT1:    INR    C        ; C-reg will hold number of
  2629.     DAD    D        ; Lines to be displayed
  2630.     JC    NPRNT1
  2631.     MOV    A,C
  2632.     STA    LINES        ; Done, save it for later
  2633.     STA    SUPSPC        ; Allow spaces preceding file sizes
  2634. ;
  2635. ; Number lines times entry size = the number of bytes to skip in the
  2636. ; second table when outputting files in vertical order.
  2637. ;
  2638.      IF    VSPAGE
  2639.     LDA    FOPFLG        ; Check File output
  2640.     ORA    A
  2641.     JZ    NVSORT
  2642.     LDA    POPFLG
  2643.     ORA    A
  2644.     JZ    NVSORT
  2645.     LDA    NOPFLG
  2646.     ORA    A
  2647.     JNZ    VSORT
  2648. NVSORT:    MOV    A,C
  2649.     JMP    OVSORT
  2650. VSORT:
  2651.     LDA    LINCNT        ; Get number of lines currently displayed
  2652.     MOV    B,A
  2653.     MVI    A,22        ; Calc number left
  2654.     SUB    B
  2655.     MOV    B,A
  2656.     MOV    A,C        ; Get how many lines this DU
  2657.     CMP    B
  2658.     JC    OVSORT        ; If C, then this DU will fit on the page whole
  2659.     MOV    A,B        ; This DU won't fit, so calc to fill up page
  2660.     ORA    A
  2661.     JNZ    OVSORT
  2662.     MOV    A,C
  2663.     CPI    23
  2664.     JC    OVSORT
  2665.     MVI    A,23
  2666. OVSORT:
  2667.      ENDIF            ; VSPAGE
  2668.  
  2669.     MOV    L,A        ; Put number of lines into HL
  2670.     MVI    H,0
  2671.     CALL    MULT13
  2672.     SHLD    JUMPER        ; Put it away
  2673.     XRA    A
  2674.     STA    WASHERE        ; Set flag for FENCE that says next calc
  2675.                 ; is for the next page of display
  2676. ;
  2677. ; Fill a record with FF at the end of table 2
  2678. ;
  2679.     LHLD    NEWPTR        ; Now points to end of table 2
  2680.     MVI    B,128
  2681.     MVI    A,0FFH
  2682.  
  2683. NPRNT2:    MOV    M,A
  2684.     INX    H
  2685.     DCR    B
  2686.     JNZ    NPRNT2
  2687. ;
  2688. ; Increment the number of files for use later in VENTRY.  This insures
  2689. ; that a column delimiter will be printed after the last filename, if
  2690. ; the file appears in other than the last column of the display.
  2691. ;
  2692.      IF    NOT (Z80DOS OR CPM3)
  2693.     LXI    H,TOTFIL
  2694.     INR    M
  2695.      ENDIF            ; NOT Z80DOS/CPM3
  2696. ;
  2697. ; Print out a line of files
  2698. ;
  2699. NPRNT3:    
  2700.      IF    Z80DOS OR CPM3
  2701.     MVI    C,2
  2702.     LDA    NODFLG
  2703.     ORA    A
  2704.     JZ    NOD5
  2705.     MVI    C,4
  2706. NOD5:
  2707.      ENDIF            ; Z80DOS/CPM3
  2708.  
  2709.      IF    NOT (Z80DOS OR CPM3)
  2710.     MVI    C,4        ; Reset number of columns
  2711.      ENDIF            ; NOT Z80DOS/CPM3
  2712.  
  2713.     CALL    CRLF        ; Start a new line
  2714.     MVI    A,1
  2715.     STA    VSFRST
  2716. ;
  2717. ; Print first filename
  2718. ;
  2719.     LHLD    XPOINT        ; XPOINT = to start of second table
  2720.     CALL    VENTRY        ; At entry. Below, it is incremented
  2721.                 ; For additional lines of printout
  2722.     JZ    NLINE        ; Either out of columns or out of files
  2723. ;
  2724. ; Print second filename
  2725. ;
  2726.     LHLD    XPOINT
  2727.     DAD    D
  2728.     CALL    VENTRY
  2729.     JZ    NLINE
  2730. ;
  2731. ; Print third filename
  2732. ;
  2733.     LHLD    XPOINT
  2734.     DAD    D
  2735.     DAD    D
  2736.     CALL    VENTRY
  2737.     JZ    NLINE
  2738. ;
  2739. ; Print fourth filename
  2740. ;
  2741.     LHLD    XPOINT
  2742.     DAD    D
  2743.     DAD    D
  2744.     DAD    D
  2745.     CALL    VENTRY
  2746.  
  2747. NLINE:    LHLD    XPOINT        ; Increment XPOINT to next file
  2748.  
  2749.      IF    Z80DOS OR CPM3
  2750.     LXI    D,15
  2751.      ENDIF            ; Z80DOS/CPM3
  2752.  
  2753.      IF    NOT (Z80DOS OR CPM3)
  2754.     LXI    D,13
  2755.      ENDIF            ; NOT Z80DOS/CPM3
  2756.  
  2757.     DAD    D
  2758.     SHLD    XPOINT
  2759.     LHLD    TOTFIL        ; Out of files?
  2760.     MOV    A,H
  2761.     ORA    L
  2762.     JZ    DOLIB        ; Yes, Check for libraries
  2763.     LXI    H,LINES        ; No, just need a new line
  2764.     DCR    M
  2765.     JNZ    NPRNT3
  2766.  
  2767. DOLIB:    LDA    LOPFLG
  2768.     ORA    A
  2769.     JNZ    NXTUSR
  2770.     LHLD    TOTFIL        ; How many files matched?
  2771.     MOV    A,H
  2772.     ORA    L
  2773.  
  2774.      IF    NOT (Z80DOS OR CPM3)
  2775.     CNZ    PRTLMEM        ; Skip library check if none found
  2776.      ENDIF
  2777.  
  2778.      IF    Z80DOS OR CPM3
  2779.     CALL    PRTLMEM
  2780.      ENDIF            ; ZRDOS/CPM3
  2781.  
  2782. ;
  2783. ; Directory for one user area completed.  If all users option is select-
  2784. ; ed, then go do another directory on the next user number until we ex-
  2785. ; ceed the maximum user # for the selected drive.
  2786. ;
  2787. NXTUSR:    LDA    AOPFLG        ; All user flag
  2788.     ORA    A        ; Set?
  2789.     JZ    NXTUSU        ; Set if zero, show all user areas
  2790.     LDA    HOPFLG        ; "H" flag to show remaining areas
  2791.     ORA    A
  2792.     JNZ    GOCLZ        ; Non-zero, not set, exit
  2793.  
  2794. NXTUSU:    CALL    CKVER        ; Running CP/M 2?
  2795.     JC    GOCLZ        ; No, Skip user increment
  2796.     CALL    CKABRT        ; Yes, Check for user abort
  2797.     LDA    MAXUSR        ; No abort - get maximum user #
  2798.     LXI    H,NEWUSR    ; Increment directory user number
  2799.     INR    M
  2800.     CMP    M        ; Next user # exceed maximum?
  2801.     JNC    SETTBL        ; No, more user areas to go
  2802.     LDA    BASUSR        ; Reset base user number for
  2803.     MOV    M,A        ; The next directory search
  2804. ;
  2805. ; We've finished all of our outputting. Flush the remainder of the out-
  2806. ; put buffer and close the file before going to exit routine.
  2807. ;
  2808. GOCLZ:    LXI    H,OPNFLG    ; Get file open status, reset flag
  2809.     MOV    A,M        ; To force reopen on next pass
  2810.     MVI    M,0
  2811.     ORA    A        ; File open?
  2812.     JZ    NXTDSK        ; No, Skip closing DISK.DIR
  2813.     LXI    H,BUFCNT
  2814.     MOV    A,M        ; Load # of unflushed characters in
  2815.     MVI    M,128        ; Buffer, force BUFCNT to empty status
  2816.     ORA    A        ; If BUFCNT=128, buffer empty set sign
  2817.     JM    DDCLOS        ; Close DISK.DIR if buffer is empty
  2818.     JZ    FLUSH        ; Write last record to DISK.DIR if full
  2819.     LHLD    BUFPNT        ; Else pad unused buffer with CTL-Z
  2820.  
  2821. PUTAGN:    MVI    M,'Z'-40H    ; EOF marker
  2822.     INX    H        ; Next buffer location
  2823.     DCR    A        ; Count-1
  2824.     JNZ    PUTAGN        ; Continue buffer padding fill
  2825.  
  2826. FLUSH:    LXI    D,OUTFCB    ; Flush the last output buffer
  2827.     MVI    C,WRITE
  2828.     CALL    CPM
  2829.     ORA    A
  2830.     JNZ    WRTERR
  2831.  
  2832. DDCLOS:    LXI    D,OUTFCB    ; Close DISK.DIR output file
  2833.     MVI    C,CLOSE
  2834.     CALL    CPM
  2835. ;
  2836. ; Directory for all user areas finished.  If the multi-disk option is
  2837. ; enabled and selected, reset to the base user area and repeat the
  2838. ; directory for next drive on-line until we either exceed the drives in
  2839. ; our LODRV-HIDRV table, or the BDOS shuts us down with a select or bad
  2840. ; record error, which will be intercepted back to the EXIT module.
  2841. ;
  2842. NXTDSK:    LXI    H,FNDFLG    ; Load file found flag
  2843.     MOV    A,M
  2844.     MVI    M,0        ; Clear found flag for next drive
  2845.     ORA    A
  2846.     JNZ    NDSK        ; Continue if at least 1 file found
  2847.     LXI    H,FOPFLG
  2848.     DCR    M
  2849.     PUSH    H
  2850.     LXI    D,NOFMS1    ; Print 1st part of no files message
  2851.     CALL    PUTS        ; Print it
  2852.     LXI    D,NOFLM
  2853.     CALL    PUTS        ; Print message
  2854.     LDA    FCB
  2855.     ADI    'A'-1
  2856.     CALL    PUTCHR        ; Output the drive
  2857.     CALL    CKVER
  2858.     JC    NOUSR1
  2859.     CALL    PUTUSR        ; Output the user number
  2860.  
  2861. NOUSR1:    LXI    D,NOFMS3    ; Print divider
  2862.     CALL    PUTS
  2863.     CALL    PRTFRE        ; Tag with free message
  2864.     LDA    VFLAG        ; Check display form
  2865.     ORA    A
  2866.     CNZ    CRLF        ; Need another CRLF in horizontal mode
  2867.     POP    H
  2868.     INR    M
  2869.  
  2870. NDSK:    LDA    DOPFLG        ; Multi-disk selected?
  2871.     ORA    A
  2872.     JNZ    NPRT        ; No, skip next check
  2873.     CALL    CKABRT        ; Check for user abort
  2874.     MVI    A,HIDRV-LODRV    ; Load max drive code to search
  2875.     LXI    H,FCB        ; Increment directory FCB drive code
  2876.     INR    M
  2877.     CMP    M        ; Does next disk exceed maximum?
  2878.     JC    NPRT
  2879.  
  2880. ;     IF    MAXDRV
  2881.  
  2882.      IF    ZCPR33 AND MAXDRV
  2883.     PUSH    H
  2884.     LHLD    Z3DRVL        ; Point to ENV
  2885.     MOV    A,M        ; Get it
  2886.     POP    H
  2887.      ENDIF            ; ZCPR33
  2888.  
  2889.      IF    NOT ZCPR33 AND MAXDRV
  2890.     LDA    MXDRV        ; Look at another value limit
  2891.     INR    A
  2892.      ENDIF            ; NOT ZCPR33
  2893.  
  2894.      IF    MAXDRV
  2895.     CMP    M        ; Is it lower?
  2896.     JC    NPRT        ; Bail out if too low
  2897.     JMP    NOOPT        ; Search next disk
  2898.      ENDIF            ; MAXDRV
  2899.  
  2900.     JNC    NOOPT        ; Search next disk if maxdr not true
  2901. ;
  2902. ; If no printer, fall through to EXIT
  2903. ;
  2904. NPRT:    LDA    POPFLG
  2905.     ORA    A        ; Printer active?
  2906.     JNZ    EXIT        ; No, just exit
  2907.     MVI    C,LIST
  2908.     MVI    E,13        ; Print a CRLF
  2909.     CALL    CPM
  2910.     MVI    E,10        ; Line feed
  2911.     CALL    CPM
  2912.     JMP    EXIT        ; All done - exit to CCP
  2913. ;.....
  2914. ;
  2915. ; Output the user number of the directory in decimal
  2916. ;
  2917. PUTUSR:    LDA    NEWUSR
  2918.     CPI    10        ; User no. < 10?
  2919.     JC    DUX        ; Yes, skip 10's digit
  2920.     STA    USRNR
  2921.     PUSH    B        ; No, process 10's digit
  2922.     MVI    C,'0'-1
  2923.  
  2924. DUY:    INR    C        ; Get tens digit
  2925.     SUI    10
  2926.     JNC    DUY        ; Loop until we've gone too far
  2927.     ADI    10
  2928.     MOV    B,A        ; Save units digit
  2929.     MOV    A,C        ; Print tens digit
  2930.     CALL    PUTCHR
  2931.     MOV    A,B        ; Recall units digit
  2932.     POP    B
  2933.  
  2934. DUX:    ADI    '0'        ; Make it ASCII
  2935.     JMP    PUTCHR
  2936.  
  2937. ;.....
  2938. ;
  2939. ; Force new line on output and check for page pause
  2940. ;
  2941. CRLF:    MVI    A,13        ; Send CR
  2942.     CALL    PUTCHR
  2943.     MVI    A,10        ; Send LF
  2944.     JMP    PUTCHR
  2945. ;.....
  2946. ;
  2947. ; Separate the directory output on a line with a space,
  2948. ; the delimiter, followed by another space.
  2949. ;
  2950. FENCE:    CALL    SPACE
  2951.  
  2952.      IF    Z80DOS OR CPM3
  2953.     LDA    NODFLG
  2954.     ORA    A
  2955.     JNZ    FENCE1
  2956.     CALL    SPACE
  2957.     CALL    SPACE
  2958. FENCE1:
  2959.      ENDIF            ; Z80DOS/CPM3
  2960.  
  2961.     MVI    A,':'        ; Fence character
  2962.     CALL    PUTCHR        ; Print it, then a space character
  2963.  
  2964.      IF    Z80DOS OR CPM3
  2965.     LDA    NODFLG
  2966.     ORA    A
  2967.     JNZ    NOD6
  2968.     CALL    SPACE
  2969.     CALL    SPACE
  2970. NOD6:
  2971.      ENDIF            ; Z80DOS/CPM3
  2972.  
  2973. SPACE:    MVI    A,' '
  2974. ;
  2975. ; Output character in A to console, and optionally to printer
  2976. ; and/or the output file.  Detects user abort request.
  2977. ;
  2978. PUTCHR:    PUSH    B
  2979.     PUSH    D
  2980.     PUSH    H
  2981.     PUSH    PSW        ; Save the character to output
  2982.     CALL    HITYPE        ; Send it to console
  2983.     POP    PSW        ; Restore the output character
  2984.     ANI    7FH        ; Strip parity bit on character
  2985. ;
  2986. ; Test file output mode and skip to page pause test if not active
  2987. ;
  2988.     MOV    B,A        ; Save stripped character to B
  2989.     CPI    10        ; At end of line?
  2990.     CZ    CKABRT        ; Check for user abort request
  2991.     LDA    FOPFLG        ; Is file output active?
  2992.     ORA    A
  2993.     JNZ    NOWRIT        ; Go check for page pause if not
  2994. ;
  2995. ; File output mode active - make sure we have room in buffer to add
  2996. ; the next character. If buffer full, write out current record first
  2997. ; and then start a new record with current character.
  2998. ;
  2999.     LHLD    BUFPNT        ; Load current buffer pointer
  3000.     LDA    BUFCNT        ; Load buffer capacity remaining
  3001.     ORA    A        ; Buffer full?
  3002.     JNZ    PUTBUF        ; No, Continue
  3003.     CALL    SETFOP        ; Yes, Set the DMA address
  3004.     LXI    D,OUTFCB    ; Else, write current buffer out
  3005.     MVI    C,WRITE
  3006.     CALL    CPM        ; (call must save character in B)
  3007.     ORA    A        ; Error?
  3008.     JNZ    WRTERR        ; Yes, exit if disk full or R/O
  3009.     LXI    H,OUTBUF    ; Reset buffer pointer
  3010.     MVI    A,128        ; Reset buffer capacity
  3011.  
  3012. PUTBUF:    MOV    M,B        ; Move char to next buffer position
  3013.     INX    H        ; Bump buffer pointer
  3014.     SHLD    BUFPNT        ; And save it
  3015.     DCR    A        ; Buffer char count-1
  3016.     STA    BUFCNT        ; And save it
  3017.  
  3018. NOWRIT:    MOV    A,B        ; Recall stripped character
  3019.     ANI    7FH        ; Strip parity bit on character
  3020.     MOV    E,A        ; Setup list output call
  3021.     MVI    C,LIST
  3022.     LDA    POPFLG        ; Load printer flag
  3023.     ORA    A        ; Set?
  3024.     CZ    CPM        ; Yes, print character
  3025.     MOV    A,E        ; Recall character
  3026.     CPI    10        ; Do we have a line feed?
  3027.     JNZ    PUTRET        ; Exit if not
  3028.     LDA    NOPFLG        ; Page pause function disabled?
  3029.     ORA    A
  3030.     JZ    PUTRET        ; Yes, exit
  3031.     LDA    POPFLG        ; Load, printer flag
  3032.     ORA    A        ; Set?
  3033.     JZ    PUTRET        ; Yes, skip page pause
  3034.     LDA    FOPFLG        ; File output flag
  3035.     ORA    A        ; Set?
  3036.     JZ    PUTRET        ; Yes, skip page pause
  3037.  
  3038.     LDA    LINCNT        ; Load line count
  3039.     INR    A        ; Bump it
  3040.     STA    LINCNT
  3041.     MVI    L,23        ; Allows use of [more] to finish display
  3042.     CMP    L        ; End of the screen?
  3043.     JC    PUTRET
  3044.  
  3045.     LXI    D,EOSMSG    ; Else, display pause message
  3046.     MVI    C,PRINT        ; Without checking for line feeds
  3047.     CALL    BDOS
  3048.     CALL    GETCH        ; Wait for character
  3049.     CPI    'C'-40H        ; Abort on CTL-C
  3050.     JZ    EXIT1
  3051.     CPI    'K'-40H        ; Or CTL-K
  3052.     JZ    EXIT1
  3053.     CPI    'X'-40H        ; Or CTL-X
  3054.     JZ    EXIT1
  3055.     CPI    ' '        ; See if printing character
  3056.     JC    NOTEOS        ; Exit if not
  3057.  
  3058.      IF    NOT VSPAGE
  3059.     JZ    NOTEOS1        ; If a space, exit to different place
  3060.      ENDIF
  3061.  
  3062.     ANI    5FH        ; Change to upper-case
  3063.     CPI    'C'        ; Can abort with c, C
  3064.     JZ    EXIT1
  3065.     CPI    'K'        ; Can abort with k, K
  3066.     JZ    EXIT1
  3067.     CPI    'X'        ; Can abort with x, X
  3068.     JZ    EXIT1
  3069.  
  3070. NOTEOS:    XRA    A        ; Reset line count
  3071.     STA    WASHERE        ; Say are starting over
  3072.  
  3073. NOTEOS1:STA    LINCNT
  3074.     LXI    D,MORERA    ; Overwrite the [more] display
  3075.     MVI    C,PRINT
  3076.     CALL    BDOS
  3077.  
  3078.      IF    VSPAGE
  3079.     LDA    VSFRST
  3080.     ORA    A
  3081.     JZ    DLINES1
  3082.     LDA    WASHERE        ; Were we here before?
  3083.     ORA    A
  3084.     JZ    WEWERE        ; Z=no
  3085.     CPI    23        ; Yes, must be moving by space bar, see how
  3086.                 ; many times
  3087.     JNZ    DLINES        ; NZ=not a full page worth yet
  3088.     XRA    A        ; A full page, move JUMPER up
  3089.     STA    WASHERE
  3090. WEWERE:    LHLD    JUMPER        ; Get current jumper
  3091.     XCHG
  3092.     LHLD    XPOINT        ; Get current position in array
  3093.     DAD    D        ; Skip the right number of files
  3094.      ENDIF
  3095.  
  3096.      IF    (Z80DOS OR CPM3) AND VSPAGE
  3097.     LDA    NODFLG
  3098.     ORA    A
  3099.     JZ    WEWERE1
  3100.     DAD    D
  3101.     DAD    D
  3102. WEWERE1:
  3103.      ENDIF            ; Z80DOS/CPM3
  3104.  
  3105.      IF    NOT (Z80DOS OR CPM3) AND VSPAGE
  3106.     DAD    D
  3107.     DAD    D
  3108.      ENDIF            ; NOT Z80DOS/CPM3
  3109.  
  3110.      IF    VSPAGE
  3111.     SHLD    XPOINT        ; New current poition in output array
  3112.     LXI    H,23        ; Calc new jumper, 23 lines/page
  3113.     LDA    LINES
  3114.     CPI    24
  3115.     JNC    MLINES
  3116.     MOV    L,A
  3117. MLINES:    CALL    MULT13
  3118.     SHLD    JUMPER
  3119. DLINES:
  3120.     LDA    WASHERE
  3121.     INR    A
  3122.     STA    WASHERE
  3123. DLINES1:
  3124.     MVI    A,1
  3125.     STA    VSFRST
  3126.      ENDIF            ; VSPAGE
  3127.  
  3128.     XRA    A        ; Reset the 'A' register
  3129. PUTRET:    POP    H        ; Exit from PUTCHR
  3130.     POP    D
  3131.     POP    B
  3132.     RET
  3133. ;.....
  3134. ;
  3135. ; Output character, with low-case or reverse-video highlighting if high
  3136. ; bit set and conditionals enabled.
  3137. ;
  3138. HITYPE:    DS    0
  3139.  
  3140.      IF    USELC OR REVID
  3141.     ORA    A        ; Check for attributes not set
  3142.     JP    CONOUT        ; No attribute..ignore this one
  3143.     ANI    7FH        ; Attribute set, delete now
  3144.      ENDIF            ; USELC OR REVID
  3145.  
  3146.      IF    NOT USELCW AND WHEEL
  3147.     MOV    E,A        ; Save the character for later
  3148.      ENDIF
  3149.  
  3150.      IF    ZCPR33 AND (NOT USELCW AND WHEEL)
  3151.     PUSH    H
  3152.     LHLD    Z3WHLL        ; Point to enviorment
  3153.     MOV    A,M        ; Get it
  3154.     POP    H
  3155.      ENDIF            ; ZCPR33
  3156.  
  3157.      IF    NOT ZCPR33 AND (NOT USELCW AND WHEEL)
  3158.     LDA    WHLOC        ; Get wheel byte
  3159.      ENDIF            ; NOT ZCPR33
  3160.  
  3161.      IF    NOT USELCW AND WHEEL
  3162.     ORA    A        ; Don't use lower case or REVID
  3163.     MOV    A,E        ; Get back the character to display
  3164.     JZ    CONOUT
  3165.      ENDIF            ; NOT USELCW AND WHEEL
  3166.  
  3167.      IF    REVID
  3168.     PUSH    PSW        ; Save character
  3169.     LXI    D,RVON        ; Turn on reverse video
  3170.     CALL    COUTS        ; If not null
  3171.     POP    PSW        ; Restore character
  3172.      ENDIF            ; REVID
  3173.  
  3174.      IF    USELC
  3175.     CPI    'A'        ; Change only from A-Z
  3176.     JC    TYPEC
  3177.     CPI    'Z'+1
  3178.     JNC    TYPEC        ; Punctuation can change so leave it
  3179.     ORI    20H        ; If attribute, make lower case
  3180.      ENDIF            ; USELC
  3181.  
  3182.      IF    USELC OR REVID
  3183. TYPEC:    CALL    CONOUT        ; Send the processed character
  3184.      ENDIF            ; USELC OR REVID
  3185.  
  3186.      IF    REVID
  3187.     LXI    D,RVOFF        ; Turn off reverse video
  3188.     CALL    COUTS        ; If not null
  3189.      ENDIF            ; REVID
  3190.  
  3191.      IF    USELC OR REVID
  3192.     RET
  3193.      ENDIF            ; USELC OR REVID
  3194. ;.....
  3195. ;
  3196. ; Output character in A to console
  3197. ;
  3198. CONOUT:    MOV    E,A        ; Get character for BDOS entry
  3199.     MVI    C,WRCON
  3200.     JMP    BDOS        ; Console Output
  3201. ;.....
  3202. ;
  3203. ; Output (raw) null-terminated string at (DE) to console.
  3204. ;
  3205.  
  3206. COUTS:    LDAX    D        ; Get byte of string
  3207.     ORA    A        ; Null?
  3208.     RZ            ; Return if so
  3209.     PUSH    D
  3210.     CALL    CONOUT
  3211.     POP    D
  3212.     INX    D        ; Next byte
  3213.     JMP    COUTS
  3214. ;.....
  3215. ;
  3216. ; Output bytes at HL of length B to console/printer/file
  3217. ;
  3218. PUTSB:    MOV    A,M
  3219.     CALL    PUTCHR
  3220.     INX    H
  3221.     DCR    B
  3222.     JNZ    PUTSB
  3223.     RET
  3224. ;.....
  3225. ;
  3226. ; Output null-terminated string to console/printer/file
  3227. ;
  3228. PUTS:    LDAX    D        ; Load character from DE string
  3229.     ANI    7FH        ; Strip off parity
  3230.     ORA    A        ; Is a 0?
  3231.     RZ            ; Yes, Terminate
  3232.     CALL    PUTCHR        ; Display character
  3233.     INX    D        ; Next string position
  3234.     JMP    PUTS        ; Continue
  3235. ;.....
  3236. ;
  3237. ; Fetch character from console (without echo)
  3238. ;
  3239. GETCH:    LHLD    0000H+1        ; Warm Boot Address
  3240.     MVI    L,9        ; Direct Console
  3241.     CALL    GOHL        ; Get Character
  3242.     ANI    7FH        ; Strip off any parity
  3243.     RET
  3244. ;.....
  3245. ;
  3246. ; Check for a CTL-C or CTL-S entered from the keyboard.  Jump to EXIT if
  3247. ; CTL-C, pause on CTL-S.
  3248. ;
  3249. CKABRT:    PUSH    H
  3250.     PUSH    D
  3251.     PUSH    B
  3252.     MVI    C,CONST
  3253.     CALL    BDOS
  3254.     ORA    A
  3255.     JZ    CKAB3        ; No character, exit
  3256.     MVI    C,RDCON
  3257.     CALL    BDOS
  3258.     ANI    5FH
  3259.     CPI    'S'-40H
  3260.     JZ    CKAB0
  3261.     CPI    'S'
  3262.     JNZ    CKAB1
  3263.     CALL    CKAB4
  3264.  
  3265. CKAB0:    MVI    C,RDCON
  3266.     CALL    BDOS
  3267.     ANI    5FH
  3268.  
  3269. CKAB1:    CPI    'C'-40H        ; CTL-C?
  3270.     JZ    CKAB2        ; Yes, quit
  3271.     CPI    'K'-40H
  3272.     JZ    CKAB2
  3273.     CPI    'X'-40H
  3274.     JZ    CKAB2
  3275.     CPI    ' '        ; Any other CTL-character, abort
  3276.     JC    CKAB3
  3277.     CALL    CKAB4        ; Clear the character from screen
  3278.     CPI    'C'
  3279.     JZ    CKAB2
  3280.     CPI    'K'
  3281.     JZ    CKAB2
  3282.     CPI    'X'
  3283.     JNZ    CKAB3
  3284.  
  3285. CKAB2:    LXI    D,CKMS1
  3286.     CALL    PUTS
  3287.     POP    B
  3288.     POP    D
  3289.     POP    H
  3290.     JMP    EX0        ; All done
  3291.  
  3292. CKAB3:    POP    B
  3293.     POP    D
  3294.     POP    H
  3295.     RET
  3296.  
  3297. CKAB4:    PUSH    PSW
  3298.     LXI    D,CKMS2
  3299.     CALL    PUTS
  3300.     POP    PSW
  3301.     RET
  3302. ;.....
  3303. ;
  3304. ; Call here to call address in HL
  3305. ;
  3306. GOHL:    PCHL
  3307. ;
  3308. ; Enter BDOS, save all extended registers
  3309. ;
  3310. CPM:    PUSH    B        ; Save Registers
  3311.     PUSH    D
  3312.     PUSH    H
  3313.  
  3314.      IF    ZRDOS
  3315.     LDA    ZRDFLG        ; ZRDOS running?
  3316.     ORA    A
  3317.     JNZ    ZRD        ; ZRDOS error trap and DOSs call
  3318.      ENDIF            ; ZRDOS
  3319.  
  3320.     CALL    BDOS
  3321.     MOV    B,A        ; Save return code
  3322.     LDA    VERFLG        ; Is this 3.0?
  3323.     CPI    30H
  3324.     MOV    A,B
  3325.     JC    CPM20        ; No, exit normally
  3326.     CPI    0FFH        ; Yes, was return code FF?
  3327.     JNZ    CPM20        ; No, exit normally
  3328.     MOV    A,H        ; Yes, check for error code
  3329.     ORA    A
  3330.     JNZ    DSKERR        ; Exit if physical error
  3331.     MOV    A,B        ; Else, continue normally
  3332.  
  3333. CPM20:    POP    H
  3334.     POP    D
  3335.     POP    B
  3336.     RET
  3337. ;.....
  3338. ;
  3339. ; ZRDOS Error Trap and System Call exits to CPM20
  3340. ;
  3341.      IF    ZRDOS
  3342. ZRD:    CALL    SETTRAP        ; Set the warm boot trap
  3343.     CALL    BDOS        ; Do what we're told
  3344.     CALL    RESTRAP        ; Reset the trap
  3345.     JMP    CPM20        ; Error free exit
  3346. ;.....
  3347. ;
  3348. ; Set Warm Boot Trap in ZRDOS
  3349. ;
  3350. SETTRAP:PUSH    H
  3351.     PUSH    D
  3352.     PUSH    B
  3353.     MVI    C,SETWBT    ; Set warm boot trap to come here
  3354.     LXI    D,WBTRAP
  3355.     CALL    BDOS
  3356.     POP    B
  3357.     POP    D
  3358.     POP    H
  3359.     RET
  3360. ;.....
  3361. ;
  3362. ; WBTRAP is where the ZRDOS returns control on warm boot (error)
  3363. ;
  3364. WBTRAP:    LXI    H,DSKERR    ; Return here after trap reset
  3365.     PUSH    H        ; Save DSKERR on stack
  3366. ;
  3367. ; Reset Warm Boot Trap in ZRDOS
  3368. ;
  3369. RESTRAP:PUSH    H
  3370.     PUSH    D
  3371.     PUSH    B
  3372.     PUSH    PSW
  3373.     MVI    C,RESWBT    ; Reset warm boot trap
  3374.     CALL    BDOS
  3375.     POP    PSW
  3376.     POP    B
  3377.     POP    D
  3378.     POP    H
  3379.     RET
  3380.      ENDIF            ; ZRDOS
  3381. ;.....
  3382. ;
  3383. ; For file output mode, return to old user area and set DMA for the file
  3384. ; output buffer.
  3385. ;
  3386. SETFOP:    CALL    CKVER        ; Clear carry if CP/M 2 or later
  3387.     LDA    OLDUSR        ; Get user number at startup
  3388.     MOV    E,A
  3389.     MVI    C,STUSER
  3390.     CNC    CPM        ; Reset old user number if CP/M 2
  3391.     LXI    D,OUTBUF    ; Move DMA from search buffer into
  3392.     JMP    SET2        ; Output buffer
  3393.     RET
  3394. ;.....
  3395. ;
  3396. ; Move disk buffer DMA to default buffer for directory search operations
  3397. ; and BDOS media change routines (required for pre-CP/M 2 systems while
  3398. ; in file output mode with active buffer).
  3399. ;
  3400. SETSRC:    LXI    D,TBUF        ; Default DMA Address
  3401.  
  3402. SET2:    MVI    C,STDMA        ; Set DMA Address
  3403.     JMP    CPM
  3404. ;.....
  3405. ;
  3406. ; Print amount of free space remaining on selected drive
  3407. ;
  3408. PRTFRE:    LXI    D,TOTMS7    ; Print " Free: '
  3409.     CALL    PUTS
  3410.     LHLD    FREEBY
  3411.     CALL    DECPRT        ; Print k free
  3412.     LXI    D,TOTMS8    ; Print "k "
  3413.     CALL    PUTS
  3414.     LDA    VFLAG        ; Alphabetizing vertically?
  3415.     ORA    A
  3416.     RZ            ; If yes, finished
  3417.     JMP    CRLF        ; Else turn up an extra line
  3418. ;.....
  3419. ;
  3420. ; Show string on the console
  3421. ;
  3422. SHOW:    LDAX    D        ; Get character from DE string
  3423.     ANI    7FH        ; Strip off parity
  3424.     ORA    A        ; Is it a 0?
  3425.     RZ            ; Yes, terminate
  3426.     PUSH    B        ; Save registers
  3427.     PUSH    D
  3428.     PUSH    H
  3429.     CALL    CONOUT        ; Show character on console
  3430.     POP    H        ; Load registers
  3431.     POP    D
  3432.     POP    B
  3433.     INX    D        ; Next string position
  3434.     JMP    SHOW        ; Continue
  3435. ;.....
  3436. ;
  3437. ; Compare routine for last extent of file search
  3438. ;
  3439. COMPR:    PUSH    H        ; Save table address
  3440.     MOV    E,M        ; Load low order
  3441.     INX    H
  3442.     MOV    D,M        ; Load high order
  3443.     INX    H
  3444.     MOV    C,M
  3445.     INX    H
  3446.     MOV    B,M
  3447. ;
  3448. ; BC, DE now point to entries to be compared
  3449. ;
  3450.     XCHG
  3451.     MOV    E,A        ; Get count
  3452.  
  3453. CMPLP:    LDAX    B
  3454.     XRA    M        ; Copy bit 7 of M
  3455.     ANI    7FH        ; Into bit 7 of A
  3456.     XRA    M
  3457.     CMP    M        ; Then compare
  3458.     INX    H
  3459.     INX    B
  3460.     JNZ    NOTEQL        ; Quit on mismatch
  3461.     DCR    E        ; Or end of count
  3462.     JNZ    CMPLP
  3463. ;
  3464. NOTEQL:    POP    H
  3465.     RET            ; Condition code tells all
  3466. ;.....
  3467. ;
  3468. ; Swap entries in the order table
  3469. ;
  3470. SWAP:    LXI    B,ORDER-2    ; Table base
  3471.     DAD    H        ; *2
  3472.     DAD    B        ; + base
  3473.     XCHG
  3474.     DAD    H        ; *2
  3475.     DAD    B        ; + base
  3476.     MOV    C,M
  3477.     LDAX    D
  3478.     XCHG
  3479.     MOV    M,C
  3480.     STAX    D
  3481.     INX    H
  3482.     INX    D
  3483.     MOV    C,M
  3484.     LDAX    D
  3485.     XCHG
  3486.     MOV    M,C
  3487.     STAX    D
  3488.     RET
  3489. ;.....
  3490. ;
  3491. ; New compare routine for sorting
  3492. ;
  3493. COMPARE:LXI    B,ORDER-2
  3494.     DAD    H
  3495.     DAD    B
  3496.     XCHG
  3497.     DAD    H
  3498.     DAD    B
  3499.     XCHG
  3500.     MOV    C,M
  3501.     INX    H
  3502.     MOV    B,M
  3503.     XCHG
  3504.     MOV    E,C
  3505.     MOV    D,B
  3506.     MOV    C,M
  3507.     INX    H
  3508.     MOV    H,M
  3509.     MOV    L,C
  3510.     MVI    B,13        ; Count for normal sort
  3511.     LDA    TOPFLG        ; Check for sort by type
  3512.     ORA    A
  3513.     JNZ    CMPLPE        ; Jump if normal sort
  3514.     PUSH    H        ; Save name pointers for later
  3515.     PUSH    D
  3516.     LXI    B,8        ; Point to file types
  3517.     DAD    B
  3518.     XCHG
  3519.     DAD    B
  3520.     XCHG
  3521.     MVI    B,3        ; Count for type compare
  3522.     CALL    CMPLPE
  3523.     POP    D        ; Retrieve name pointers
  3524.     POP    H        ; 
  3525.     RNZ
  3526.     MVI    B,8        ; Count for name compare
  3527.     CALL    CMPLPE
  3528.     RNZ
  3529.     INX    D        ; Point to extent
  3530.     INX    D
  3531.     INX    D
  3532.     INX    H
  3533.     INX    H
  3534.     INX    H
  3535.     MVI    B,2        ; Count for extent compare
  3536.  
  3537. CMPLPE:    LDAX    D        ; 
  3538.     XRA    M        ; Copy bit 7 of M
  3539.     ANI    7FH        ; Into bit 7 of A
  3540.     XRA    M        ; 
  3541.     CMP    M        ; Then compare
  3542.     INX    D
  3543.     INX    H
  3544.     RNZ
  3545.     DCR    B
  3546.     JNZ    CMPLPE
  3547.     RET
  3548. ;.....
  3549. ;
  3550. ; Error exit
  3551. ;
  3552. ERXIT:    MVI    A,0FFH        ; Error Flag
  3553.     STA    FOPFLG        ; Disable file output on error
  3554.     CALL    CRLF        ; Space down
  3555.     POP    D        ; Load message string pointer
  3556.     CALL    PUTS        ; Print message
  3557.     LXI    D,ERRMS1    ; " Error"
  3558.     CALL    PUTS        ; Print message
  3559.     CALL    CRLF        ; Space down
  3560. ;
  3561. ; Exit - all done, restore stack
  3562. ;
  3563. EXIT:    LDA    DOPFLG        ; Multi-disk selected?
  3564.     ORA    A
  3565.     JNZ    EX0        ; No, skip next
  3566.     CALL    CKABRT        ; Check for user abort
  3567.     MVI    A,HIDRV-LODRV    ; Maximum drive code to search
  3568.     LXI    H,FCB        ; Increment directory FCB drive code
  3569.     INR    M
  3570.     CMP    M        ; Does next disk exceed maximum?
  3571.     JC    EX0
  3572.  
  3573. ;     IF    MAXDRV
  3574.  
  3575.      IF    ZCPR33 AND MAXDRV
  3576.     PUSH    H
  3577.     LHLD    Z3DRVL        ; Point to ENV
  3578.     MOV    A,M        ; Get it
  3579.     POP    H
  3580.      ENDIF            ; ZCPR33
  3581.  
  3582.      IF    NOT ZCPR33 AND MAXDRV
  3583.     LDA    MXDRV        ; Look at another value limit
  3584.     INR    A
  3585.      ENDIF            ; NOT ZCPR33
  3586.  
  3587.      IF    MAXDRV
  3588.     CMP    M        ; Is it lower?
  3589.     JC    EX0        ; Bail out if too low
  3590.     JMP    NOOPT        ; Search next disk
  3591.      ENDIF            ; MAXDRV
  3592.  
  3593.     JNC    NOOPT        ; Search next disk if MAXDR not true
  3594.  
  3595. EX0:    LDA    VFLAG        ; Check display form
  3596.     ORA    A
  3597.     CZ    CRLF        ; Turn up a blank line at end if vertical
  3598.     MVI    C,CONST        ; Check console status
  3599.     CALL    CPM
  3600.     ORA    A        ; Character waiting?
  3601.     MVI    C,RDCON
  3602.     CNZ    CPM        ; Gobble up character
  3603.  
  3604.      IF    ZRDOS
  3605.     LDA    ZRDFLG        ; ZRDOS running?
  3606.     ORA    A
  3607.     JNZ    EXIT2        ; Yes
  3608.      ENDIF            ; ZRDOS
  3609.  
  3610.     LDA    VERFLG        ; Version flag
  3611.     CPI    30H        ; CP/M 3.0?
  3612.     JC    EXIT1        ; No
  3613.     MVI    C,2DH        ; Yes,
  3614.     MVI    E,0        ; Reset error mode to default
  3615.     CALL    CPM
  3616.     JMP    EXIT2        ; Quit
  3617.  
  3618. EXIT1:    LDA    DOPFLG        ; If they were swapped
  3619.     ORA    A
  3620.     CZ    SWAPEM
  3621.  
  3622. EXIT2    EQU    $
  3623.  
  3624.      IF    SHOPUB
  3625.     CALL    RSTPUB
  3626.      ENDIF            ; SHOPUB
  3627.  
  3628.     LDA    AOPFLG        ; Doing all users
  3629.     MOV    C,A
  3630.     LDA    DOPFLG        ; Or disk?
  3631.     ANA    C
  3632.     MOV    C,A
  3633.     LDA    HOPFLG        ; Or higher users?
  3634.     ANA    C
  3635.     JNZ    TOTDONE        ; If no, skip totals
  3636.     MVI    A,1        ; Force no file output
  3637.     STA    LINCNT
  3638.     STA    FOPFLG
  3639.     LXI    D,ALLTOT    ; First part of message
  3640.     CALL    PUTS
  3641.     LHLD    TOTFL1        ; Total files found
  3642.     CALL    DECPRT
  3643.     LXI    D,TOTMS4
  3644.     CALL    PUTS
  3645.     LHLD    TOTSZ1        ; Total 'k' found
  3646.     CALL    DECPRT
  3647.     LXI    D,TOTMS8
  3648.     CALL    PUTS
  3649.     LXI    D,TOTMS7
  3650.     CALL    PUTS
  3651.     LHLD    TOTFRE
  3652.     CALL    DECPRT
  3653.     LXI    D,ALLTO1
  3654.     CALL    PUTS
  3655. TOTDONE:
  3656.      IF    WMBOOT
  3657.     JMP    0000H
  3658.      ENDIF            ; WMBOOT
  3659.  
  3660.     LDA    OLDDSK        ; Restore original drive
  3661.     MOV    E,A
  3662.     MVI    C,14
  3663.     CALL    CPM
  3664.     LDA    OLDUSR        ; Restore original user area
  3665.     MOV    E,A
  3666.     MVI    C,32
  3667.     CALL    CPM
  3668.  
  3669. EXIT3:    LHLD    STACK        ; Get old stack pointer
  3670.     SPHL            ; Move back to old stack
  3671.     RET            ; And return to CCP
  3672. ;.....
  3673. ;
  3674. ; Restore Public areas if they were changed
  3675. ;
  3676.      IF    SHOPUB
  3677. RSTPUB:    LHLD    0109H
  3678.     MVI    D,0
  3679.     MVI    E,07EH
  3680.     DAD    D
  3681.     LDA    PUBDRV
  3682.     MOV    M,A
  3683.     INX    H
  3684.     LDA    PUBUSR
  3685.     MOV    M,A
  3686.     RET
  3687.      ENDIF            ; SHOPUB
  3688. ;.....
  3689. ;
  3690.      IF    NDIRS
  3691. NAMDIR:    MVI    A,0
  3692.     STA    CURDIR        ; Initial check count
  3693.  
  3694. NAMDR1:    LHLD    NAMADR        ; Named directory buffer address
  3695.  
  3696. NAMDR2:    LDA    FCB        ; Get current Drive
  3697.     CMP    M        ; Does NDR entry match current drive?
  3698.     JNZ    NXTDIR        ; No, check next
  3699.     LDA    NEWUSR        ; Get current user
  3700.     INX    H
  3701.     CMP    M        ; Does NDR entry match current user?
  3702.     JNZ    NXTDIR        ; No, check next
  3703.     MVI    A,'['        ; Frame the name in brackets
  3704.     CALL    PUTCHR
  3705.     MVI    C,8        ; Number of Characters in entry
  3706.  
  3707. DIRCHR:    INX    H        ; Match, Point to Directory Name
  3708.     MOV    A,M        ; Get Character
  3709.     CPI    20H        ; End of entry?
  3710.     JNZ    DIRCH1        ; No
  3711.  
  3712. DIRCH0:    PUSH    PSW
  3713.     MVI    A,']'        ; Print closing bracket
  3714.     CALL    PUTCHR
  3715.     POP    PSW
  3716.     JMP    DIRCH2
  3717.  
  3718. DIRCH1:    CALL    PUTCHR
  3719.     DCR    C
  3720.     JNZ    DIRCHR        ; Output Eight characters
  3721.     JMP    DIRCH0
  3722.     RET            ; Done
  3723. DIRCH2:    MOV    A,C
  3724.     ORA    A
  3725.     RZ
  3726.     MVI    A,20H        ; Fill with spaces for neatness sake
  3727.     CALL    PUTCHR
  3728.     DCR    C
  3729.     JNZ    DIRCH2
  3730.     RET
  3731.  
  3732. NXTDIR:    LDA    CURDIR
  3733.     ADI    1        ; Increment Directory pointer
  3734.     STA    CURDIR
  3735.     LXI    H,NUMDIR
  3736.     CMP    M        ; Exceeded Max Entry?
  3737.     JZ    NODIR        ; Yes, there is no entry for this DU
  3738.     LHLD    NAMADR        ; Get base NDR address
  3739.     MVI    D,0
  3740.     MVI    E,18        ; Increment to next entry
  3741.  
  3742. NXTD:    DAD    D
  3743.     DCR    A        ; Decrement count
  3744.     JNZ    NXTD        ; Until current Offset reached
  3745.     JMP    NAMDR2        ; And check the entry for a match
  3746. NODIR:    MVI    C,10        ; No match, output ten spaces
  3747.  
  3748. NODIR1:    MVI    A,20H
  3749.     CALL    PUTCHR
  3750.     DCR    C
  3751.     JNZ    NODIR1
  3752.     RET
  3753.      ENDIF            ; NDIRS
  3754. ;.....
  3755. ;
  3756. ; Trap BDOS select and sector error vectors to our own intercept routine
  3757. ; so we can catch a reference to an illegal drive.
  3758. ;
  3759. SWAPEM:    DS    0
  3760.  
  3761.      IF    ZRDOS
  3762.     LDA    ZRDFLG        ; See if ZRDOS running
  3763.     ORA    A
  3764.     RNZ            ; Yes, quit this
  3765.      ENDIF            ; ZRDOS
  3766.  
  3767.     LDA    VERFLG        ; Version flag
  3768.     CPI    30H        ; Error mode call available?
  3769.     JC    SWAP20        ; No, use BDOS error vectors
  3770.     MVI    C,2DH        ; Yes, use error mode call
  3771.     MVI    E,0FFH        ; 
  3772.     CALL    CPM        ; Set "return code only" mode
  3773.     RET
  3774.  
  3775. SWAP20:    LHLD    BDOS+1        ; Load pointer to base of BDOS
  3776.     INX    H        ; Swap new pointer if running a
  3777.     MOV    E,M        ; Program below the CCP
  3778.     INX    H
  3779.     MOV    D,M
  3780.     XCHG            ; HL points to the proper vector
  3781.     MVI    L,9        ; Point to record error vector
  3782.     LXI    D,VECTBL    ; Exchange with our vector table
  3783.     MVI    A,4        ; 4 bytes to swap
  3784.  
  3785. SWAPLP:    MOV    B,M        ; Load byte from HL
  3786.     XCHG
  3787.     MOV    C,M        ; Load byte from DE
  3788.     MOV    M,B        ; Save byte from HL
  3789.     XCHG
  3790.     MOV    M,C        ; Save byte from DE
  3791.     INX    H        ; Increment exchange pointers
  3792.     INX    D
  3793.     DCR    A        ; Counter-1
  3794.     JNZ    SWAPLP        ; Continue swapping
  3795.     RET
  3796. ;.....
  3797. ;
  3798. ; Check CP/M version number. Return carry flag set if pre-CP/M 2.  If
  3799. ; CP/M 2 or later or MP/M (any version), return carry clear.
  3800. ;
  3801. CKVER:    LDA    VERFLG        ; Version Flag
  3802.     CPI    20H        ; CP/M 2.0?
  3803.     RET
  3804. ;.....
  3805. ;
  3806. ; Return point from intercepted BDOS select and bad record errors.
  3807. ;
  3808. DSKERR:    LXI    SP,STACK    ; Get out of BDOS' stack
  3809.     JMP    EXIT        ; And exit back to CCP
  3810. ;.....
  3811. ;
  3812. ;-----------------------------------------------------------------------
  3813. ;             Start of FNAME routine
  3814. ;
  3815. ; Main module
  3816. ;    on entry, DE points to FCB to be filled, HL points to first
  3817. ;        byte of target string, RFCB is 36 bytes long
  3818. ;    on exit, B=disk number (1 for A, etc.) and C=user number
  3819. ;        HL points to terminating character
  3820. ;        A=0 and Z set if error in disk or user numbers
  3821. ;        A=0FFH and NZ if ok
  3822. ;
  3823. MAXDISK EQU    16        ; Maximum number of disks
  3824. MAXUSER EQU    31        ; Maximum user number
  3825.  
  3826. FNAME:    PUSH    D        ; Save DE
  3827.     MVI    A,0FFH        ; Set default disk and user
  3828.     STA    DISKNO
  3829.     STA    USERNO
  3830.     MVI    B,36        ; Initialize FCB
  3831.     PUSH    D        ; Save pointer
  3832.     XRA    A        ; A=0
  3833.  
  3834. FNINI:    STAX    D        ; Store zero
  3835.     INX    D        ; Point to next
  3836.     DCR    B        ; Count down
  3837.     JNZ    FNINI
  3838.     POP    D        ; Get pointer back
  3839.     PUSH    H        ; Save pointer
  3840. ;
  3841. ; Scan for colon, comma, or space in string
  3842. ;
  3843. COLON:    MOV    A,M        ; Scan for colon or space
  3844.     INX    H        ; Point to next
  3845.     CPI    ':'        ; Colon found?
  3846.     JZ    COLON1
  3847.     CPI    ','        ; Comma found?
  3848.     JZ    GETF1
  3849.     CPI    ' '+1        ; Delimiter?
  3850.     JC    GETF1
  3851.     JMP    COLON        ; Continue if not EOL
  3852. ;
  3853. COLON1:    POP    H        ; Clear stack
  3854.     MOV    A,M        ; Save possible drive specification
  3855.     CALL    CAPS        ; Capitalize
  3856.     CPI    'A'        ; Digit if less than "A"
  3857.     JC    USERCK        ; Process user number
  3858.     SUI    'A'        ; Change from ASCII to binary
  3859.     CPI    MAXDISK        ; Within bounds?
  3860.     JC    SVDISK
  3861. ;
  3862. ERREXIT:XRA    A        ; Error indicator
  3863.     POP    D        ; Restore DE
  3864.     RET
  3865. ;.....
  3866. ;
  3867. ; Log in specified disk
  3868. ;
  3869. SVDISK:    INR    A        ; Adjust to 1 for "A"
  3870.     STA    DISKNO        ; Save flag
  3871.     INX    H        ; Point to next character
  3872. ;
  3873. ; Check for user
  3874. ;
  3875. USERCK:    MOV    A,M        ; Get possible user #
  3876.     CPI    ':'        ; No user number
  3877.     JZ    GETFILE
  3878.     CPI    '?'        ; All user numbers?
  3879.     JNZ    USERC1
  3880.     STA    USERNO        ; Set value
  3881.     INX    H        ; Point to after
  3882.     MOV    A,M        ; Must be colon
  3883.     CPI    ':'
  3884.     JZ    GETFILE
  3885.     JMP    ERREXIT        ; Fatal error if not colon after ?
  3886.  
  3887. USERC1:    XRA    A        ; Zero user number
  3888.     MOV    B,A        ; B = A for user number
  3889.  
  3890. USRLOOP:MOV    A,M        ; Get digit
  3891.     INX    H        ; Point to next
  3892.     CPI    ':'        ; Done?
  3893.     JZ    USRDN
  3894.     SUI    '0'        ; Convert to binary
  3895.     JC    ERREXIT        ; User number error?
  3896.     CPI    10
  3897.     JNC    ERREXIT
  3898.     MOV    C,A        ; Next digit in C
  3899.     MOV    A,B        ; Old number in A
  3900.     ADD    A        ; *2
  3901.     ADD    A        ; *4
  3902.     ADD    B        ; *5
  3903.     ADD    A        ; *10
  3904.     ADD    C        ; *10+new digit
  3905.     MOV    B,A        ; Result in B
  3906.     JMP    USRLOOP
  3907.  
  3908. USRDN:    MOV    A,B        ; Get newer user number
  3909.     CPI    MAXUSER+1    ; Within range?
  3910.     JNC    ERREXIT
  3911.     STA    USERNO        ; Save in flag
  3912.     JMP    GETFILE
  3913. ;
  3914. ; Extract file name
  3915. ;
  3916. GETF1:    POP    H        ; Get pointer to byte
  3917. ;
  3918. GETFILE:MOV    A,M        ; Pointing to colon?
  3919.     CPI    ':'
  3920.     JNZ    GFILE1
  3921.     INX    H        ; Skip over colon
  3922.  
  3923. GFILE1:    MOV    A,M        ; Get next character
  3924.     CPI    ','        ; Delimiter?
  3925.     JZ    GFQUES
  3926.     CPI    ' '+1        ; Not a delimiter?
  3927.     JNC    GFILE2
  3928.  
  3929. GFQUES:    INX    D        ; Fill with ???
  3930.     MVI    B,11        ; 11 bytes
  3931.     MVI    A,'?'
  3932.  
  3933. GFFILL:    STAX    D        ; Put?
  3934.     INX    D        ; Point to next
  3935.     DCR    B        ; Count down
  3936.     JNZ    GFFILL
  3937.  
  3938. FNDONE:    LDA    DISKNO        ; Get disk number
  3939.     MOV    B,A        ; In 'B'
  3940.     LDA    USERNO        ; Get user number
  3941.     MOV    C,A        ; In 'C'
  3942.     POP    D        ; Restore registers
  3943.     MVI    A,0FFH        ; No error
  3944.     ORA    A        ; Set flags
  3945.     RET
  3946. ;
  3947. ; Get file name fields
  3948. ;
  3949. GFILE2:    MVI    B,8        ; At most, 8 byte filename
  3950.     CALL    SCANF        ; Scan and fill
  3951.     MVI    B,3        ; At most, 3 byte filetype
  3952.     MOV    A,M        ; Get delimiter
  3953.     CPI    '.'        ; Filename ending in "."?
  3954.     JNZ    GFILE3
  3955.     INX    H        ; Point to character after "."
  3956.     CALL    SCANF        ; Scan and fill
  3957.     JMP    FNDONE        ; Done, return to "args"
  3958.  
  3959. GFILE3:    CALL    SCANF4        ; Fill with spaces
  3960.     JMP    FNDONE
  3961. ;
  3962. ; Scanner routine
  3963. ;
  3964. SCANF:    CALL    DELCK        ; Check for delimiter
  3965.     JZ    SCANF4        ; Fill with spaces if found
  3966.     INX    D        ; Next byte in filename
  3967.     CPI    '*'        ; Question mark fill ?
  3968.     JNZ    SCANF1
  3969.     MVI    A,'?'        ; Place "?"
  3970.     STAX    D
  3971.     JMP    SCANF2
  3972.  
  3973. SCANF1:    STAX    D        ; Place character
  3974.     INX    H        ; Next position
  3975.  
  3976. SCANF2:    DCR    B        ; Count down
  3977.     JNZ    SCANF        ; Continue loop
  3978.  
  3979. SCANF3:    CALL    DELCK        ; Skip to delimiter
  3980.     RZ
  3981.     INX    H        ; Point to next
  3982.     JMP    SCANF3
  3983.  
  3984. SCANF4:    INX    D        ; Next filename or filetype
  3985.     MVI    A,' '        ; Fill with spaces
  3986.     STAX    D
  3987.     DCR    B        ; Count down
  3988.     JNZ    SCANF4
  3989.     RET
  3990. ;.....
  3991. ;
  3992. ; Check character pointed to by HL for a delimiter,
  3993. ; return with Zero flag set if the character is a delimiter
  3994. ;
  3995. DELCK:    MOV    A,M        ; Get the character
  3996.     CALL    CAPS        ; Capitalize
  3997.     ORA    A        ; 0=delimiter
  3998.     RZ
  3999.     CPI    ' '+1        ; Space character+1
  4000.     JC    DELCK1        ; Space character or less
  4001.     CPI    '='
  4002.     RZ
  4003.     CPI    5FH        ; Underscore
  4004.     RZ
  4005.     CPI    '.'
  4006.     RZ
  4007.     CPI    ':'
  4008.     RZ
  4009.     CPI    ';'
  4010.     RZ
  4011.     CPI    ','
  4012.     RZ
  4013.     CPI    '<'
  4014.     RZ
  4015.     CPI    '>'
  4016.     RET
  4017. ;
  4018. DELCK1:    CMP    M        ; Compare with self for OK
  4019.     RET
  4020. ;.....
  4021. ;
  4022. CAPS:    CPI    'a'
  4023.     RC
  4024.     CPI    'z'+1
  4025.     RNC
  4026.     SUI    20H
  4027.     RET
  4028. ;.....
  4029. ;              End of FNAME routine
  4030. ;-----------------------------------------------------------------------
  4031. ;
  4032. ; Subroutines to read library file directory
  4033. ;
  4034. PRTLMEM:LXI    H,ORDER        ; Initialize order table pointer
  4035.     SHLD    NEXTL
  4036.     XRA    A
  4037.     STA    LNCNT
  4038.  
  4039. ENTRYL:    LHLD    LCOUNT        ; Get FCB count
  4040.     DCX    H        ; Decrement it
  4041.     SHLD    LCOUNT
  4042.     MOV    A,H        ; Is this the last file?
  4043.     ORA    L
  4044.     JZ    LBRTST        ; Yes, skip compare
  4045.     PUSH    B
  4046.     CALL    CKABRT        ; Keyboard abort?
  4047.     LHLD    NEXTL
  4048.     MVI    A,11
  4049.     CALL    COMPR        ; This entry match next one?
  4050.     POP    B
  4051.     JNZ    LBRTST        ; No, print it
  4052.     INX    H
  4053.     INX    H        ; Skip, highest extent last in list
  4054.     SHLD    NEXTL
  4055.     JMP    ENTRYL        ; Loop back for next lowest extent
  4056. ;.....
  4057. ;
  4058. ; Exit Library member printing
  4059. ;
  4060. LBEXIT:    LHLD    LMTOTL
  4061.     MOV    A,H
  4062.     ORA    L
  4063.     RZ
  4064.     PUSH    H        ; Save member count
  4065.     XRA    A        ; Get a zero to
  4066.     STA    SUPSPC        ; Suppress leading spaces in totals
  4067.  
  4068.      IF    Z80DOS
  4069.     MVI    L,2        ; If last line is full, don't turn
  4070.     LDA    NODFLG
  4071.     ORA    A
  4072.     JZ    NOD7
  4073.     MVI    L,4
  4074. NOD7:
  4075.      ENDIF            ; Z80DOS
  4076.  
  4077.      IF    NOT Z80DOS
  4078.     MVI    L,4        ; If last line is full, don't turn
  4079.      ENDIF            ; NOT Z80DOS
  4080.  
  4081.     LDA    LNCNT
  4082.     CMP    L        ; Up extra line
  4083.     CNZ    CRLF        ; If partial line, extra line needed
  4084.     LXI    D,CONTM1    ; Print "There are "
  4085.     CALL    PUTS
  4086.     POP    H        ; Get total member count back
  4087.     CALL    DECPRT
  4088.     LXI    D,MFILES    ; Print "Members in "
  4089.     CALL    PUTS
  4090.     LHLD    LBTOTL
  4091.     CALL    DECPRT
  4092.     LXI    D,LIBR
  4093.     JMP    PUTS
  4094. ;
  4095. ; Valid entry obtained - spit it out
  4096. ;
  4097. LBRTST:    MVI    A,1        ; Turn off .ARC/ARK
  4098.     STA    ISARC
  4099.     LHLD    NEXTL        ; Load order table pointer
  4100.     MOV    E,M        ; Low order address
  4101.     INX    H
  4102.     MOV    D,M        ; High order address
  4103.     INX    H
  4104.     SHLD    NEXTL        ; Save updated table pointer
  4105.     LXI    H,8
  4106.     DAD    D
  4107.     CALL    CKLBR
  4108.     JZ    LBRSET
  4109.     CALL    CKARC
  4110.     JNZ    LBRNEX
  4111.     XRA    A
  4112.     STA    ISARC
  4113.  
  4114. LBRSET:    PUSH    D
  4115.  
  4116.      IF    Z80DOS OR CPM3
  4117.     LDA    NODFLG
  4118.     ORA    A
  4119.     JNZ    ZARC0
  4120.     LDA    ISARC
  4121.     ORA    A
  4122.     JZ    ZARC0
  4123.     MVI    L,2        ; 2 NAMES PER LINE
  4124.     JMP    ZARC0A
  4125. ZARC0:    MVI    L,4        ; 4 NAMES PER LINE
  4126. ZARC0A:    LDA    LNCNT
  4127.      ENDIF            ; Z80DOS/CPM3
  4128.  
  4129.      IF    NOT (Z80DOS OR CPM3)
  4130.     LDA    LNCNT
  4131.     MVI    L,4
  4132.      ENDIF            ; NOT Z80DOS/CPM3
  4133.  
  4134.     CMP    L
  4135.     CNZ    CRLF
  4136.     PUSH    PSW        ; Just in case
  4137.     LXI    D,LFMSP1    ; Long Library directory message
  4138.     LDA    ISARC
  4139.     ORA    A
  4140.     JNZ    SARCM1
  4141.     LXI    D,AFMSP1
  4142.  
  4143. SARCM1:    CALL    PUTS        ; Print it
  4144.     POP    PSW        ; Put it back
  4145.     LDA    FCB        ; Load current drive
  4146.     ADI    'A'-1        ; Convert to ASCII
  4147.     CALL    PUTCHR        ; Print it
  4148.     CALL    PUTUSR        ; Print user # after it
  4149.     MVI    A,':'        ; And colon
  4150.     CALL    PUTCHR
  4151.     POP    H
  4152.     PUSH    H
  4153.     MVI    B,8        ; Filename length
  4154.     CALL    PUTSB
  4155.     MVI    A,'.'        ; Period after filename
  4156.     CALL    PUTCHR
  4157.     MVI    B,3        ; 3 characters of filetype
  4158.     CALL    PUTSB
  4159.  
  4160.      IF    Z80DOS OR CPM3
  4161.     LDA    NODFLG
  4162.     ORA    A
  4163.     JNZ    NOD8
  4164.     CALL    DISDAT
  4165. NOD8:
  4166.      ENDIF            ; Z80DOS/CPM3
  4167.  
  4168.     CALL    SIZEFL        ; Compute size of library in k
  4169.     XCHG
  4170.     CALL    DECPRT
  4171.     LXI    D,LFMSP3
  4172.     CALL    PUTS
  4173.     POP    H
  4174. ;
  4175. ; Saves the library file name into LBRFCB
  4176. ;
  4177.     LDA    FCB
  4178.     LXI    D,LBRFCB    ; To
  4179.     STAX    D
  4180.     INX    D
  4181.  
  4182.      IF    Z80DOS OR CPM3
  4183.     LXI    B,11        ; Length
  4184.     DW    ZMOVE        ; Z80's LDIR
  4185.      ENDIF            ; Z80DOS/CPM3
  4186.  
  4187.      IF    NOT (Z80DOS OR CPM3)
  4188.     MVI    B,11        ; Length
  4189.     CALL    MOVE        ; Do the move
  4190.      ENDIF            ; NOT Z80DOS/CPM3
  4191.  
  4192.     XCHG
  4193.     MVI    B,25
  4194.  
  4195. CLMFCB:    MVI    M,0
  4196.     INX    H
  4197.     DCR    B
  4198.     JNZ    CLMFCB
  4199.     CALL    SETLDMA
  4200.     LXI    D,LBRFCB    ; Point to file
  4201.     MVI    C,OPEN        ; Get function
  4202.     CALL    CPM        ; Open it
  4203.     MVI    C,READ
  4204.     LXI    D,LBRFCB
  4205.     CALL    CPM
  4206.     CALL    SETFOP
  4207.     LXI    H,LBBUF
  4208.     MOV    A,M
  4209.     ORA    A
  4210.     JZ    CKLDIR        ; Check directory present?
  4211.  
  4212.     LDA    ISARC
  4213.     ORA    A
  4214.     JNZ    BADLBR
  4215.     MOV    A,M
  4216.     CPI    ARCMAR
  4217.     JZ    CKADIR
  4218.  
  4219. BADLBR:    LXI    H,NLBRF
  4220.     LDA    ISARC
  4221.     ORA    A
  4222.     JNZ    NBARC
  4223.     LXI    H,NARCF
  4224.  
  4225. NBARC:    MVI    B,25
  4226.     CALL    PUTSB
  4227. ;
  4228. LMLEXI:    CALL    LBCLOS
  4229. ;
  4230. ; Do next library file
  4231. ;
  4232. LBRNEX:    LHLD    LCOUNT        ; Check count
  4233.     MOV    A,H
  4234.     ORA    L
  4235.     JZ    LBEXIT        ; No more, all done
  4236.     JMP    ENTRYL        ; Else, get next .LBR file
  4237. ;.....
  4238. ;
  4239. ; Close the library file
  4240. ;
  4241. LBCLOS:    LXI    D,LBRFCB
  4242.     MVI    C,CLOSE
  4243.     CALL    CPM
  4244.     RET
  4245. ;.....
  4246. ;
  4247. ; Set the Library file DMA address
  4248. ;
  4249. SETLDMA:CALL    CKVER        ; Set carry if pre-CP/M 2
  4250.     LDA    NEWUSR        ; Get user area for directory
  4251.     MOV    E,A
  4252.     MVI    C,STUSER    ; Get the user function
  4253.     CNC    CPM        ; And set new user number if CP/M 2
  4254.     LXI    D,LBBUF
  4255.     MVI    C,STDMA
  4256.     CALL    CPM
  4257.     RET
  4258. ;.....
  4259. ;
  4260. ; Check to see if there indeed is a LBR file directory
  4261. ;
  4262. CKLDIR:    MVI    B,11        ; Length of file name
  4263.     MVI    A,' '        ; Space
  4264.     INX    H
  4265.  
  4266. CKDLP:    CMP    M
  4267.     JNZ    BADLBR
  4268.     DCR    B
  4269.     INX    H
  4270.     JNZ    CKDLP
  4271. ;
  4272. ; The first entry in the LBR directory is indeed blank.  Now see if the
  4273. ; directory size is > 0
  4274. ;
  4275.     MOV    E,M        ; File starting location low
  4276.     INX    H        ; Must be zero here
  4277.     MOV    A,M        ; File starting location high
  4278.     ORA    E        ; Must be zero here also
  4279.     JNZ    BADLBR
  4280.     INX    H
  4281.     MOV    E,M        ; Get library size low
  4282.     INX    H        ; Point to library size high
  4283.     MOV    D,M        ; Get library size high
  4284.     MOV    A,D
  4285.     ORA    E        ; Library must have some size
  4286.     JZ    BADLBR
  4287.     DCX    D
  4288.     XCHG
  4289.     SHLD    SLFILE
  4290.     LHLD    LBTOTL
  4291.     INX    H
  4292.     SHLD    LBTOTL
  4293.  
  4294.      IF    Z80DOS OR CPM3
  4295.     LDA    ISARC
  4296.     ORA    A
  4297.     JZ    ZARC1
  4298.     LDA    NODFLG
  4299.     ORA    A
  4300.     JNZ    ZARC1
  4301.     MVI    A,2
  4302.     JMP    ZARC1A
  4303. ZARC1:    MVI    A,4
  4304. ZARC1A:
  4305.      ENDIF            ; Z80DOS/CPM3
  4306.  
  4307.      IF    NOT (Z80DOS OR CPM3)
  4308.     MVI    A,4
  4309.      ENDIF            ; NOT Z80DOS/CPM3
  4310.  
  4311.     STA    LNCNT        ; Reset names per line counter
  4312.     MVI    B,3
  4313.     LXI    H,17
  4314.     DAD    D
  4315.     JMP    LMTEST
  4316.  
  4317. LFMLOP:    LHLD    SLFILE        ; Get next buffer if more
  4318.     MOV    A,L
  4319.     ORA    H
  4320.     JZ    LMLEXI
  4321.     DCX    H
  4322.     SHLD    SLFILE
  4323.     CALL    SETLDMA
  4324.     MVI    C,READ
  4325.     LXI    D,LBRFCB
  4326.     CALL    CPM
  4327.     CALL    SETFOP
  4328.     MVI    B,4        ; Get file count per record
  4329.     LXI    H,LBBUF        ; Get buffer starting address
  4330.  
  4331. LMTEST:    MOV    A,M        ; Get member open flag
  4332.     ORA    A        ; Test for open
  4333.     JZ    PRMNAM
  4334.  
  4335. LMTESA:    LDA    ISARC
  4336.     ORA    A
  4337.     RZ
  4338.     LXI    D,32        ; Member not open get offset
  4339.     DAD    D        ; To next and add it in
  4340.     DCR    B        ; Is buffer empty ?
  4341.     JNZ    LMTEST        ; No so test next entry
  4342.     JMP    LFMLOP        ; Yes, get next buffer
  4343. ;
  4344. PRMNAM:    PUSH    H        ; Print member name and size
  4345.     PUSH    B
  4346.     CALL    CKABRT        ; Keyboard abort?
  4347.     LXI    H,LNCNT
  4348.  
  4349.      IF    Z80DOS OR CPM3
  4350.     LDA    ISARC
  4351.     ORA    A
  4352.     JZ    ZARC2
  4353.     LDA    NODFLG
  4354.     ORA    A
  4355.     JNZ    ZARC2
  4356.     MVI    A,2
  4357.     JMP    ZARC2A
  4358. ZARC2:    MVI    A,4
  4359. ZARC2A:
  4360.      ENDIF            ; Z80DOS/CPM3
  4361.  
  4362.      IF    NOT (Z80DOS OR CPM3)
  4363.     MVI    A,4
  4364.      ENDIF            ; NOT Z80DOS/CPM3
  4365.  
  4366.     CMP    M
  4367.     JNZ    PRMNA1
  4368.  
  4369.      IF    PRBRDR
  4370.     MVI    A,'*'        ; Load "A" with border character
  4371.     CALL    PUTCHR        ; Print it
  4372.     MVI    A,' '        ; 
  4373.     CALL    PUTCHR        ; Space between border and text
  4374.      ENDIF            ; PRBRDR
  4375.  
  4376.     JMP    PRMNA2
  4377.  
  4378. PRMNA1:    CALL    SPACE
  4379.     MVI    A,':'
  4380.     CALL    PUTCHR
  4381.     CALL    SPACE
  4382.  
  4383. PRMNA2:    POP    B
  4384.     POP    H
  4385.     PUSH    H
  4386.     PUSH    B
  4387.     INX    H
  4388.     MVI    B,8        ; Filename length
  4389.     CALL    PUTSB
  4390.     MVI    A,'.'        ; Period after filename
  4391.     CALL    PUTCHR
  4392.     MVI    B,3        ; 3 characters of filetype
  4393.     CALL    PUTSB
  4394.     INX    H
  4395.     INX    H
  4396.  
  4397.      IF    Z80DOS OR CPM3
  4398.     PUSH    H        ; Save pointer
  4399.     LDA    ISARC
  4400.     ORA    A
  4401.     JZ    ZARC3
  4402.     LDA    NODFLG
  4403.     ORA    A
  4404.     JNZ    ZARC3
  4405.     LXI    D,2
  4406.     DAD    D        ; Skip size field and point to CRC
  4407.                 ; DISDAT will point it to date field
  4408.     CALL    DISDAT        ; Show the date
  4409. ZARC3:    POP    H
  4410.      ENDIF            ; Z80DOS/CPM3
  4411.  
  4412.     MOV    E,M
  4413.     INX    H
  4414.     MOV    D,M
  4415.     XCHG
  4416. ;
  4417. ; Output the size of the individual file
  4418. ;
  4419.     PUSH    D
  4420.     PUSH    H
  4421.     XCHG
  4422.     LHLD    LLENLOC
  4423.     XCHG
  4424.     DAD    D
  4425.     SHLD    LLENLOC
  4426.     POP    H
  4427. ;
  4428. ; New code added to convert lib members from records to 'k'.  Upon entry
  4429. ; member's size in records is in HL.
  4430. ;
  4431.     LDA    COPFLG        ; File sizes wanted in records?
  4432.     ORA    A
  4433.     JZ    PRMNA3        ; Jump if so
  4434.     LXI    D,7        ; Round up to nearest 1k
  4435.     DAD    D
  4436.     XCHG
  4437.     LXI    H,0
  4438.     MOV    A,E        ; Low byte of record count in A
  4439.     RRC
  4440.     RRC
  4441.     RRC
  4442.     ANI    1FH
  4443.     MOV    E,A        ; And put it back
  4444.     MOV    L,D        ; Get the high byte if any
  4445.     MVI    D,0        ; Clean out the old resting place
  4446.     DAD    H        ; Multiply it by 32 to convert to
  4447.     DAD    H        ; Number of k bytes
  4448.     DAD    H
  4449.     DAD    H
  4450.     DAD    H
  4451.     DAD    D        ; And add in the low byte
  4452.  
  4453. PRMNA3:    POP    D
  4454.     CALL    DECPRT        ; Go print it
  4455.     LDA    FSIZEC        ; Follow with 'k' or 'r'
  4456.     CALL    PUTCHR
  4457. ;
  4458. ; Update library member total and name counter
  4459. ;
  4460.     LHLD    LMTOTL
  4461.     INX    H
  4462.     SHLD    LMTOTL
  4463.     LDA    LNCNT
  4464.     DCR    A
  4465.     STA    LNCNT
  4466.     POP    B
  4467.     POP    H
  4468.     JNZ    LMTESA        ; And go output another file
  4469. ;
  4470. ; Current line full, start a new one
  4471. ;
  4472.      IF    Z80DOS OR CPM3
  4473.     LDA    ISARC
  4474.     ORA    A
  4475.     JZ    ZARC4
  4476.     LDA    NODFLG
  4477.     ORA    A
  4478.     JNZ    ZARC4
  4479.     MVI    A,2
  4480.     JMP    ZARC4A
  4481. ZARC4:    MVI    A,4
  4482. ZARC4A:
  4483.      ENDIF            ; Z80DOS/CPM3
  4484.  
  4485.      IF    NOT (Z80DOS OR CPM3)
  4486.     MVI    A,4
  4487.      ENDIF            ; NOT Z80DOS/CPM3
  4488.  
  4489.     STA    LNCNT        ; Reset names per line counter
  4490.     CALL    CRLF        ; Space down to next line
  4491.     JMP    LMTESA
  4492. ;.....
  4493. ;
  4494. ; Move characters from "HL" to "DE" length in "B"
  4495. ;
  4496.      IF    NOT (Z80DOS OR CPM3)
  4497. MOVE:    MOV    A,M        ; Get a character
  4498.     STAX    D        ; Store it
  4499.     INX    H        ; To next "from"
  4500.     INX    D        ; To next "to"
  4501.     DCR    B        ; More?
  4502.     JNZ    MOVE        ; Yes, loop
  4503.     RET            ; No, return
  4504.      ENDIF            ; NOT Z80DOS/CPM3
  4505. ;.....
  4506. ;
  4507. ; Archive file subroutines
  4508. ;
  4509. CKADIR:    XRA    A
  4510.     DCR    A
  4511.     STA    GETABL        ; Say buffer is full (first read by lbr test)
  4512.     LHLD    LBTOTL        ; Bump library count total
  4513.     INX    H
  4514.     SHLD    LBTOTL
  4515.     MVI    A,4        ; LDA     MNPL
  4516.     STA    LNCNT        ; Reset names per line counter
  4517.  
  4518. ARCLP:    CALL    GET        ; Get the next character from buffer
  4519.     CPI    ARCMAR        ; Is it archive header marker?
  4520.     JNZ    BADLBR        ; And abort if not
  4521.     CALL    GET        ; Get header version
  4522.     ORA    A        ; If zero, that's logical end of file,
  4523.     JZ    LMLEXI        ; And we're done
  4524.     LXI    D,ANAME        ; Set to fill header buffer
  4525.     MVI    B,HDRSIZ    ; Setup normal header size less file name
  4526.     CPI    1        ; But test if version 1
  4527.     JNZ    GETHD1        ; Skip if not version 1
  4528.     LXI    B,HDRSIZ-4    ; Else, header is 4 bytes less
  4529.  
  4530. GETHD1:    CALL    GET        ; Get header byte
  4531.     STAX    D        ; Store in buffer
  4532.     INX    D
  4533.     DCR    B
  4534.     JNZ    GETHD1        ; Loop for all bytes
  4535.     LXI    H,ARCFIL    ; Prefill dummy arc FCB name with spaces
  4536.     MVI    B,11
  4537.  
  4538. FIXAN:    MVI    M,' '
  4539.     INX    H
  4540.     DCR    B
  4541.     JNZ    FIXAN
  4542.     MVI    B,5        ; Prefill rest of dummy FCB with zero
  4543.  
  4544. FIXAE:    MVI    M,0
  4545.     INX    H
  4546.     DCR    B
  4547.     JNZ    FIXAE
  4548.     LXI    H,ANAME        ; Get pointer to archive header buffer
  4549.     LXI    D,ARCFIL    ; Point to our dummy FCB
  4550.     MVI    B,8        ; Get name length
  4551.  
  4552. MANAME:    MOV    A,M        ; Get character from header
  4553.     INX    H
  4554.     ORA    A
  4555.     JZ    AEDONE        ; Nothing in buffer so we're done
  4556.     CPI    02EH        ; Is the char a point
  4557.     JZ    DAEXT        ; DO FILE EXTENT
  4558.     STAX    D
  4559.     INX    D
  4560.     DCR    B
  4561.     JNZ    MANAME
  4562.  
  4563. DAEXT:    LXI    D,ARCFIL+8    ; Get dummy file extent address
  4564.     MVI    B,3
  4565.     MOV    A,M
  4566.     CPI    2EH
  4567.     JNZ    AELOP
  4568.     INX    H
  4569.  
  4570. AELOP:    MOV    A,M        ; Fill in the file extent
  4571.     ORA    A
  4572.     JZ    AEDONE
  4573.     STAX    D
  4574.     INX    H
  4575.     INX    D
  4576.     DCR    B
  4577.     JNZ    AELOP
  4578.  
  4579. AEDONE:    LXI    H,ASIZE
  4580.     MOV    E,M        ; Fetch BCDE from (HL)
  4581.     INX    H
  4582.     MOV    D,M
  4583.     INX    H
  4584.     MOV    C,M
  4585.     XRA    A        ; Clear flags
  4586.     MOV    A,E        ; Convert file length count in bytes
  4587.     RAL            ; To length in records for output
  4588.     MOV    A,D
  4589.     RAL
  4590.     MOV    E,A
  4591.     MOV    A,C
  4592.     RAL
  4593.     MOV    D,A
  4594.     XCHG
  4595.     SHLD    ARCFIL+13    ; Save file length
  4596.     LXI    H,ARCFIL-1    ; Point to dummy FCB
  4597.     CALL    PRMNAM        ; List the file info
  4598.     LXI    H,ASIZE        ; Get remaining file size
  4599.     MOV    A,M
  4600.     ANI    7FH
  4601.     LHLD    ARCFIL+13    ; Save file length
  4602.     XCHG            ; Save record offset
  4603.     LXI    H,GETABL    ; Point to offset of last byte read
  4604.     ADD    M        ; Add byte offsets
  4605.     CPI    80H        ; Does it overflow current record?
  4606.     JC    NRAD
  4607.     SUI    80H        ; Adjust pointer
  4608.     INX    D        ; Bump record number
  4609.  
  4610. NRAD:    MOV    M,A        ; Update buffer pointer for new position
  4611.     MOV    A,D        ; Check record offset
  4612.     ORA    E
  4613.     JZ    LEXIT        ; Return if none (still in same record)
  4614.     PUSH    D        ; Save record offset
  4615.     LXI    D,LBRFCB
  4616.     MVI    C,RECORD    ; Compute current "random" record no.
  4617.     CALL    CPM        ; (I.e. next sequential record to read)
  4618.     LHLD    LBRFCB+FRN    ; Get result
  4619.     DCX    H        ; Adjust next record to current record
  4620.     POP    D        ; Restore record offset
  4621.     DAD    D        ; Compute new record no.
  4622.     JC    BADLBR        ; If >64k, it's past largest (8 Mb) file
  4623.     SHLD    LBRFCB+FRN    ; Save new record no.
  4624.     MVI    C,READRN    ; Read the random record
  4625.     CALL    GETREC
  4626.     ORA    A
  4627.     JNZ    BADLBR        ; File read error
  4628.     LXI    H,LBRFCB+FCR    ; Point to current record in extent
  4629.     INR    M        ; Bump for subsequent sequential read
  4630.  
  4631. LEXIT:    JMP    ARCLP        ; Loop for next file
  4632. ;.....
  4633. ;
  4634. ; Get next sequential byte from archive file
  4635. ;
  4636. GET:    PUSH    B        ; Save registers
  4637.     PUSH    D
  4638.     PUSH    H
  4639.     LDA    GETABL        ; Point to last byte read
  4640.     INR    A        ; At end of buffer?
  4641.     CPI    80H
  4642.     CNC    GETNXT        ; Yes, read next record and reset pointer
  4643.     STA    GETABL        ; Save new buffer pointer
  4644.     MOV    L,A
  4645.     MVI    H,0
  4646.     LXI    D,LBBUF
  4647.     DAD    D
  4648.     MOV    A,M        ; Fetch byte from there
  4649.     POP    H        ; Restore registers
  4650.     POP    D
  4651.     POP    B
  4652.     RET            ; Return
  4653. ;
  4654. ; Get next sequential record from archive file
  4655. ;
  4656. GETNXT:    MVI    C,READ        ; Setup read-sequential function code
  4657.     CALL    GETREC
  4658.     ORA    A
  4659.     JNZ    RDERR
  4660.     PUSH    PSW
  4661.     XRA    A
  4662.     DCR    A
  4663.     STA    GETABL
  4664.     POP    PSW
  4665.     RET
  4666. ;
  4667. RDERR:    POP    H        ; Strip GETNXT return
  4668.     POP    H        ; Clean up the get stack
  4669.     POP    D
  4670.     POP    B
  4671.     POP    H        ; Strip get calling address
  4672.     JMP    BADLBR        ; Show error
  4673. ;
  4674. ; Get record (sequential or random) from archive file
  4675. ;
  4676. GETREC:    PUSH    H
  4677.     PUSH    B
  4678.     CALL    SETLDMA        ; Set library DMA address
  4679.     LXI    D,LBRFCB    ; Setup FCB address
  4680.     POP    B        ; Restore read function
  4681.     CALL    CPM        ; Do it
  4682.     PUSH    PSW        ; Save read status
  4683.     CALL    SETFOP        ; Reset Print file DMA address
  4684.     POP    PSW        ; Restore read status
  4685.     POP    H        ; Restore buffer pointer
  4686.     RET
  4687. ;.....
  4688. ;
  4689. ; Test file extent for ARC/ARK
  4690. ;
  4691. CKARC:    PUSH    H
  4692.     PUSH    D
  4693.     PUSH    B
  4694.     XCHG
  4695.     LXI    H,ARCTYP
  4696.     MVI    C,2        ; Number for the loop to test
  4697. ;
  4698. CKARL:    LDAX    D
  4699.     ANI    7FH
  4700.     CMP    M
  4701.     JNZ    CKARX
  4702.     INX    H
  4703.     INX    D
  4704.     DCR    C
  4705.     JNZ    CKARL
  4706. ;
  4707. ; The first 2 match now see if C or K for .ARC or .ARK
  4708. ;
  4709.     LDAX    D
  4710.     ANI    7FH
  4711.     CPI    'C'        ; See if "C"
  4712.     JZ    CKARX
  4713.     CPI    'K'        ; See if "K"
  4714.  
  4715. CKARX:    POP    B
  4716.     POP    D
  4717.     POP    H
  4718.     RET
  4719. ;.....
  4720. ;
  4721. ; Test file extent for LBR
  4722. ;
  4723. CKLBR:    PUSH    H
  4724.     PUSH    D
  4725.     PUSH    B
  4726.     XCHG
  4727.     LXI    H,LBRTYP
  4728.     MVI    C,3
  4729.  
  4730. CKLBL:    LDAX    D
  4731.     ANI    7FH
  4732.     CMP    M
  4733.     JNZ    CKLBX
  4734.     INX    H
  4735.     INX    D
  4736.     DCR    C
  4737.     JNZ    CKLBL
  4738.  
  4739. CKLBX:    POP    B
  4740.     POP    D
  4741.     POP    H
  4742.     RET
  4743. ;
  4744. ; TIMEON routine
  4745. ;
  4746. ; Go through a search to see if BYE is active
  4747. ;
  4748.      IF    TIMEON
  4749. TIME:    LHLD    0001H        ; Point to warm boot again
  4750.     DCX    H        ; If BYE active,
  4751.     MOV    D,M        ; Pick up pointer to BYE variables
  4752.     DCX    H        ; (COVECT) followed by "BYE"
  4753.     MOV    E,M
  4754.     LXI    H,15        ; Calculate address of BYE variable
  4755.     DAD    D        ; Where ptr to orig BIOS vector stored
  4756.     MOV    E,M        ; Load that address into DE
  4757.     INX    H        ; If BIOS active, DE now points to
  4758.     MOV    D,M        ; Original BIOS console output vector
  4759.     INX    H        ; Point to BYE signon message
  4760.     MOV    A,M        ; Get letter
  4761.     ANI    05FH        ; Convert to upper case if needed
  4762.     CPI    'B'        ; Try to match "BYE"
  4763.     RNZ            ; Out if BYE not active
  4764.     INX    H
  4765.     MOV    A,M
  4766.     ANI    05FH        ; Convert to u-case if needed
  4767.     CPI    'Y'
  4768.     RNZ
  4769.     INX    H
  4770.     MOV    A,M
  4771.     ANI    05FH        ; Convert to u-case if needed
  4772.     CPI    'E'
  4773.     RNZ
  4774.  
  4775.     LXI    D,6        ; Bye running, point to RTCBUF
  4776.     DAD    D
  4777.     MOV    E,M        ; Get RTCBUF address
  4778.     INX    H        ; And copy
  4779.     MOV    D,M        ; In DE
  4780.     XCHG            ; Put in HL
  4781.     LXI    D,7        ; Offset to
  4782.     DAD    D        ; Time-on-system byte
  4783.     MOV    A,M        ; Load TOS byte
  4784.     LXI    H,TONMS1    ; Where to store in ASCII
  4785.     CALL    DEC8        ; Convert binary to ASCII
  4786.     LXI    D,TONMSG
  4787.     CALL    PUTS        ; Print the message
  4788.     RET            ; And return
  4789. ;.....
  4790. ;
  4791. ; DEC8 will convert an 8 bit binary number in A to 3 ASCII
  4792. ; bytes. HL points to the MSB location where the ASCII bytes
  4793. ; will be stored. Leading zeros are suppressed, store spaces
  4794. ; in your buffer before calling.
  4795. ;
  4796. DEC8:    PUSH    B
  4797.     PUSH    D
  4798.     MVI    E,0        ; Leading zero flag
  4799.     MVI    D,100
  4800.  
  4801. DEC81:    MVI    C,'0'-1
  4802.  
  4803. DEC82:    INR    C
  4804.     SUB    D        ; 100 or 10
  4805.     JNC    DEC82        ; Still +
  4806.     ADD    D        ; Now add it back
  4807.     MOV    B,A        ; Remainder
  4808.     MOV    A,C        ; Get 100/10
  4809.     CPI    '1'        ; Zero?
  4810.     JNC    DEC83        ; Yes
  4811.     MOV    A,E        ; Check flag
  4812.     ORA    A        ; Reset?
  4813.     MOV    A,C        ; Restore byte
  4814.     JZ    DEC84        ; Leading zeros are skipped
  4815.  
  4816. DEC83:    MOV    M,A        ; Store in buffer
  4817.     INX    H        ; Increment storage location
  4818.     MVI    E,0FFH        ; Set zero flag
  4819.  
  4820. DEC84:    MOV    A,D
  4821.     SUI    90        ; 100 to 10
  4822.     MOV    D,A
  4823.     MOV    A,B        ; Remainder
  4824.     JNC    DEC81        ; Do it again
  4825.     ADI    '0'        ; Make ASCII
  4826.     MOV    M,A        ; And store it
  4827.     POP    D
  4828.     POP    B
  4829.     RET
  4830.  
  4831. TONMSG:    DB    13,10,'Minutes on System: '
  4832. TONMS1:    DB    '    ',0
  4833.      ENDIF            ; TIMEON
  4834. ;
  4835. ;              end of TIMEON routine
  4836. ;-----------------------------------------------------------------------
  4837. ;               help routine
  4838. ;
  4839. ; Help menu if ? is typed, using a fancy ZCMD or ZCPR system
  4840. ;
  4841.      IF    WHEEL
  4842. HELPME:    LXI    D,OPTMSG    ; Point at message
  4843.     CALL    SHOW
  4844.      ENDIF            ; WHEEL
  4845.  
  4846.      IF    ZCPR33 AND WHEEL
  4847.     PUSH    H
  4848.     LHLD    Z3WHLL        ; Point to enviorment
  4849.     MOV    A,M        ; Get it
  4850.     POP    H
  4851.      ENDIF            ; ZCPR33
  4852.  
  4853.      IF    NOT ZCPR33 AND WHEEL
  4854.     LDA    WHLOC        ; Get wheel byte
  4855.      ENDIF            ; NOT ZCPR33
  4856.  
  4857.      IF    WHEEL
  4858.     ORA    A        ; If set, help out poor SYSOP
  4859.     JZ    EXIT3        ; No - exit
  4860.     LXI    D,SYSOP1    ; Point at message
  4861.     CALL    SHOW
  4862.     JMP    EXIT3        ; And exit
  4863. ;
  4864. ; This menu of options will appear to normal users (WHEEL not set).
  4865. ; Modify the menus to accommodate your system requirements.
  4866. ;
  4867. OPTMSG:    DB    13,10,13,10
  4868.     DB    '  Available Options (start with a  $  or  /  or'
  4869.     DB    '  [ character):',13,10,13,10
  4870.     DB    '  A - all user areas               N - no page pause'
  4871.     DB    ' [more]',13,10
  4872.     DB    '  C - file sizes in records        Q - show non-$ARCHived'
  4873.     DB    ' files',13,10
  4874.     DB    '  D - all drives                   T - order files'
  4875.     DB    ' by EXT type',13,10
  4876.     DB    '  H - Current area to highest      V - show version'
  4877.     DB    ' number',13,10
  4878.     DB    '  L - list LBR/ARC/ARK members     X - aux. format'
  4879.     DB    ' (horiz/vert)'
  4880.      ENDIF
  4881.  
  4882.      IF    Z80DOS AND WHEEL
  4883.     DB    13,10
  4884.     DB    '  Z - show any dates',13,10
  4885.     DB    '  = - exact date match             + - GE date match',13,10
  4886.     DB    '  - - LT date match                ! - use creation date for'
  4887.     DB    ' match',13,10
  4888.     DB    '  % -use alteration date match     @ - use access date for'
  4889.     DB    ' match',13,10
  4890.     DB    'A date input with no =+-!%@ will use =% default, * as'
  4891.     DB    ' date is current date'
  4892.      ENDIF            ; Z80DOS
  4893.  
  4894.      IF    CPM3 AND WHEEL
  4895.     DB    13,10
  4896.     DB    '  Z - show any dates               - - LT date match',13,10
  4897.     DB    '  = - exact date match             + - GE date match',13,10
  4898.     DB    '  % - use UPDATE date match        @ - use ACCESS/CREATE date'
  4899.     DB    ' for match',13,10,13,10
  4900.      ENDIF
  4901.  
  4902.      IF    (CPM3 AND WHEEL) AND UPDATE
  4903.     DB    'A date input with no =+-%@ will use =% as the default, * as'
  4904.     DB    ' date is current date',13,10
  4905.      ENDIF            ; CPM3
  4906.  
  4907.      IF    (CPM3 AND WHEEL) AND NOT UPDATE
  4908.     DB    'A date input with no =+-%@ will use =@ as the default, * as'
  4909.     DB    ' date is current date',13,10
  4910.      ENDIF
  4911.  
  4912.      IF    WHEEL AND (NOT CPM3)
  4913.     DB    13,10,13,10
  4914.      ENDIF
  4915.  
  4916.      IF    (Z80DOS OR CPM3) AND WHEEL
  4917.     DB    ' Example - to list all drives/users, no pauses,'
  4918.     DB    ' GE date match on access date:',13,10,13,10
  4919.     DB    '                     B0>SD $AND+@ 7/1/88'
  4920.      ENDIF            ; Z80DOS/CPM3
  4921.  
  4922.      IF    NOT (Z80DOS OR CPM3) AND WHEEL
  4923.     DB    '  Example - to list all drives and user areas,'
  4924.     DB    ' no pauses:',13,10,13,10
  4925.     DB    '                     B0>SD $AND <ret>'
  4926.      ENDIF            ; NOT Z80DOS/CPM3
  4927.  
  4928.      IF    WHEEL
  4929.     DB    13,10,13,10,0
  4930. ;
  4931. ; This menu of options appears only when the WHEEL is set.
  4932. ;
  4933. SYSOP1:    DB    '  * * * Special SYSOP Options (WHEEL SET) * * *'
  4934.      ENDIF
  4935.  
  4936.      IF    NOT FATTRIB AND WHEEL
  4937.     DB    13,10,13,10
  4938.      ENDIF            ; NOT FATTRIB
  4939.  
  4940.      IF    FATTRIB AND WHEEL
  4941.     DB    13,10
  4942.      ENDIF            ; FATTRIB
  4943.  
  4944.      IF    WHEEL
  4945.     DB    '  F - file output (DISK.DIR)       R - reset disk'
  4946.     DB    ' system',13,10
  4947.     DB    '  O - show $SYS files only         S - include'
  4948.     DB    ' $SYS files',13,10
  4949.     DB    '  P - printer output',13,10
  4950.      ENDIF
  4951.  
  4952.      IF    FATTRIB AND WHEEL
  4953.     DB    '  1 - Check attrib 1               2 - Check attrib 2',13,10
  4954.     DB    '  3 - Check attrib 3               4 - Check attrib 4',13,10
  4955.      ENDIF            ; FATTRIB
  4956.  
  4957.      IF    WHEEL
  4958.     DB    0
  4959.      ENDIF            ; WHEEL
  4960. ;
  4961. ; Help menu if ? is typed, NOT using any fancy ZCMD or ZCPR system
  4962. ;
  4963.      IF    NOT WHEEL
  4964. HELPME:    LXI    D,OPTMSG    ; Point at message
  4965.     CALL    SHOW
  4966.     JMP    EXIT3        ; And exit
  4967. ;
  4968. OPTMSG:    DB    13,10,13,10
  4969.     DB    '  Available Options (start with a  $  or  /  or'
  4970.     DB    '  [  character):',13,10
  4971.     DB    13,10
  4972.     DB    '  A - all user areas               P - printer output'
  4973.     DB    13,10
  4974.     DB    '  C - file sizes in records        Q - show non $ARChived'
  4975.     DB    ' files',13,10
  4976.     DB    '  D - all drives                   R - reset disk system'
  4977.     DB    13,10
  4978.     DB    '  F - file output (DISK.DIR)       S - include $SYS'
  4979.     DB    ' files',13,10
  4980.     DB    '  H - Current area to highest      T - order files'
  4981.     DB    ' by EXT type',13,10
  4982.     DB    '  L - list LBR/ARC/ARK members     V - show version'
  4983.     DB    ' number',13,10
  4984.     DB    '  N - no page pause [more]         X - aux. format'
  4985.     DB    ' (horiz/vert)',13,10
  4986.     DB    '  O - show $SYS files only'
  4987.      ENDIF            ; NOT WHEEL
  4988.  
  4989.      IF    (Z80DOS OR CPM3) AND NOT WHEEL
  4990.     DB    '         Z - show any dates'
  4991.      ENDIF            ; Z80DOS/CPM3
  4992.  
  4993.      IF    NOT WHEEL
  4994.     DB    13,10
  4995.      ENDIF            ; NOT WHEEL
  4996.  
  4997.      IF    FATTRIB AND NOT WHEEL
  4998.     DB    '  1 - Check attrib 1               2 - Check attrib 2',13,10
  4999.     DB    '  3 - Check attrib 3               4 - Check attrib 4',13,10
  5000.      ENDIF            ; FATTRIB
  5001.  
  5002.      IF    Z80DOS AND NOT WHEEL
  5003.     DB    '  = - exact date match             + - GE date match',13,10
  5004.     DB    '  - - LT date match                ! - use creation date for'
  5005.     DB    ' match',13,10
  5006.     DB    '  % - use alteration date match    @ - use access date for'
  5007.     DB    ' match',13,10
  5008.     DB    '  A date input with no =+-!%@ will use =% for dafault,'
  5009.     DB    ' * as date is current date.',13,10,13,10
  5010.      ENDIF            ; Z80DOS
  5011.  
  5012.      IF    CPM3 AND NOT WHEEL
  5013.     DB    '  = = exact date match             + - GE date match',13,10
  5014.     DB    '  - - LT date match',13,10
  5015.     DB    '  % - use UPDATE date match        @ - use ACCESS/CREATE date'
  5016.     DB    ' for match',13,10
  5017.      ENDIF            ; CPM3
  5018.  
  5019.      IF    CPM3 AND UPDATE
  5020.     DB    'A date input with no =+-%@ will use =% as the default, * as'
  5021.     DB    ' date is current date',13,10
  5022.      ENDIF            ; CPM3
  5023.  
  5024.      IF    CPM3 AND NOT UPDATE
  5025.     DB    'A date input with no =+-%@ will use =@ as the default, * as'
  5026.     DB    ' date is current date',13,10
  5027.      ENDIF
  5028.  
  5029.      IF    Z80DOS OR CPM3
  5030.     DB    ' Example - to list all drives/users, no pauses,'
  5031.     DB    ' GE date match on access date:',13,10,13,10
  5032.     DB    '                     B0>SD $AND+@ 7/1/88',13,10,13,10,0
  5033.      ENDIF            ; Z80DOS/CPM3
  5034.  
  5035.      IF    NOT (Z80DOS OR CPM3) AND NOT WHEEL
  5036.     DB    13,10,'  Example - to list all drives and user areas,'
  5037.     DB    ' no pauses:',13,10,13,10
  5038.     DB    '                     B0>SD $AND <ret>'
  5039.     DB    13,10,13,10,13,10,13,10,13,10,13,10,13,10
  5040.     DB    0
  5041.      ENDIF            ; NOT Z80ODS/CPM3
  5042.  
  5043.      IF    Z80DOS OR CPM3
  5044. DISDAT:    PUSH    B
  5045.     PUSH    H        ; Save pointer to size field
  5046.     PUSH    D
  5047.     INX    H        ; and skip over size
  5048.     INX    H        ; 
  5049.     MOV    E,M        ; Get JD in DE
  5050.     INX    H        ; 
  5051.     MOV    D,M        ; 
  5052.     XCHG            ; to HL
  5053.     CALL    DATEHL        ; 
  5054.     PUSH    H        ; Month and Year in L,H
  5055.     PUSH    PSW        ; Day in A
  5056.     CALL    SPACE
  5057.     CALL    SPACE
  5058.     POP    PSW
  5059.     JNZ    DAYOK        ; NZ = was a day there
  5060.     POP    H
  5061.     CALL    NODATE
  5062.     JMP    DNOTOK
  5063.      ENDIF            ; Z80DOS/CPM3
  5064. DAYOK:    
  5065.      IF    (Z80DOS OR CPM3) AND NOT EDATE
  5066.     PUSH    PSW
  5067.     MOV    A,L        ; Month out
  5068.     CALL    BCDOUT
  5069.     MVI    A,'/'
  5070.     CALL    PUTCHR
  5071.     POP    PSW
  5072.     CALL    BCDOUT        ; Day out
  5073.      ENDIF            ; Z80DOS/CPM3
  5074.  
  5075.      IF    (Z80DOS OR CPM3) AND EDATE
  5076.     PUSH    H
  5077.     CALL    BCDOUT        ; Day out
  5078.     MVI    A,'/'
  5079.     CALL    PUTCHR
  5080.     POP    H
  5081.     MOV    A,L
  5082.     CALL    BCDOUT        ; Month out
  5083.      ENDIF            ; Z80DOS/CPM3
  5084.  
  5085.      IF    Z80DOS OR CPM3
  5086.     MVI    A,'/'
  5087.     CALL    PUTCHR
  5088.     POP    H
  5089.     MOV    A,H        ; Year out
  5090.     CALL    BCDOUT
  5091. DNOTOK:    CALL    SPACE
  5092.     CALL    SPACE
  5093.     POP    D
  5094.     POP    H
  5095.     POP    B
  5096.     RET
  5097.  
  5098. NODATE:
  5099.     LXI    D,NODATM
  5100.     CALL    PUTS
  5101.     RET
  5102. NODATM:
  5103.     DB    '--------',0
  5104.  
  5105. BCDOUT:
  5106.     PUSH    B        ; Save
  5107.     MOV    B,A        ; A holds BCD digits
  5108.     RAR
  5109.     RAR
  5110.     RAR
  5111.     RAR
  5112.     CALL    BCDOT1        ; Output high order
  5113.     MOV    A,B
  5114.     CALL    BCDOT1        ; And low order
  5115.     POP    B
  5116.     RET
  5117. BCDOT1:    ANI    0FH
  5118.     ADI    '0'
  5119.     CALL    PUTCHR
  5120.     RET
  5121.  
  5122. ;
  5123. ; DATEHL converts the value in HL to BCD year, month, day
  5124. ;     for use with Z80DOS or CPM3 time stamps.
  5125. ;
  5126. ;
  5127. ; Inputs:    HL contains hex days since December 31, 1977 or if CPM3
  5128. ;               Janurary 1, 1978
  5129. ;
  5130. ; Outputs:    H contains BCD 20th century year
  5131. ;        L contains BCD month
  5132. ;        A contains BCD day
  5133. ;
  5134. ;        Zero flag set (Z) and A=0 if invalid date (zero) detected,
  5135. ;        Zero flag reset (NZ) and A=0ffh otherwise.
  5136.  
  5137. ; DATEHL by Carson Wilson who Adapted from B5C-CPM3.INS
  5138.  
  5139. DATEHL:    MOV    A,H
  5140.     ORA    L        ; Test blank date (zero)
  5141.     RZ            ; Return Z and A=0 if so
  5142.     SHLD    DAYS        ; Save initial value
  5143.     MVI    B,78        ; Set years counter
  5144. LOOP:    CALL    CKLEAP
  5145.     LXI    D,-365        ; Set up for subtract
  5146.     JNZ    NOPLY        ; Skip if no leap year
  5147.     DCX    D        ; Set for leap year
  5148. NOPLY:    DAD    D        ; Subtract
  5149.     JNC    YDONE        ; Continue if years done
  5150.     MOV    A,H
  5151.     ORA    L
  5152.     JZ    YDONE
  5153.     SHLD    DAYS        ; Else save days count
  5154.     INR    B        ; Increment years count
  5155.     JMP    LOOP        ; And do again
  5156. ;
  5157. ; The years are now finished, the years count is in 'B' (HL is invalid)
  5158. ;
  5159. YDONE:    MOV    A,B
  5160.     CALL    BINBCD
  5161.     STA    YEARS        ; save BCD year
  5162. ;
  5163.     CALL    CKLEAP
  5164.     MVI    A,0E4H        ; -28
  5165.     JNZ    FEBNO        ; February not 29 days
  5166.     MVI    A,0E3H        ; Leap year -29
  5167. FEBNO:    STA    FEB        ; Set february
  5168.     LHLD    DAYS        ; Get days count
  5169.     LXI    D,MTABLE    ; Point to months table
  5170.     MVI    B,0FFH        ; Set up 'B' for subtract
  5171.     MVI    A,0        ; Set a for # of months
  5172. MLOOP:    PUSH    PSW
  5173.     LDAX    D        ; Get month
  5174.     MOV    C,A        ; Put in 'C' for subtract
  5175.     POP    PSW
  5176.     SHLD    DAYS        ; save days count
  5177.     DAD    B        ; Subtract
  5178.     INX    D        ; Increment months counter
  5179.     INR    A
  5180.     JC    MLOOP        ; Loop for next month
  5181.  
  5182. ;
  5183. ; The months are finished, days count is on stack.  First, calculate
  5184. ; month.
  5185. ;
  5186. MDONE:    MOV    B,A        ; Save months
  5187.     LHLD    DAYS
  5188.     MOV    A,H
  5189.     ORA    L
  5190.     JNZ    NZD
  5191.     DCX    D
  5192.     DCX    D
  5193.     LDAX    D
  5194.     CMA
  5195.     INR    A
  5196.     MOV    L,A
  5197.     DCR    B
  5198. NZD:    MOV    A,L        ; Retrieve binary day of month
  5199.     CALL    BINBCD        ; Convert to BCD
  5200.     PUSH    PSW        ; Save day in A
  5201. ;
  5202.     MOV    A,B        ; Retrieve the binary month
  5203.     CALL    BINBCD        ; Convert binary month to BCD
  5204.     MOV    L,A        ; Return month in L
  5205. ;
  5206.     LDA    YEARS
  5207.     MOV    H,A        ; Return year in H
  5208.     POP    PSW        ; Restore day
  5209.     ORA    A        ; Set NZ flag
  5210.     RET
  5211.  
  5212. ;
  5213. ; Support Routines:
  5214. ;
  5215.  
  5216. ; Check for leap years.
  5217. ;
  5218. CKLEAP:    MOV    A,B
  5219.     ANI    0FCH
  5220.     CMP    B
  5221.     RET
  5222. ;
  5223. ; Convert A to BCD & store back in A
  5224. ;
  5225. BINBCD:    ORA    A
  5226.     RZ
  5227.     PUSH    B
  5228.     MOV    B,A
  5229.     XRA    A
  5230. BINBCD1:ADI    1
  5231.     DAA
  5232.     DCR    B
  5233.     JNZ    BINBCD1
  5234.     POP    B
  5235.     RET
  5236. ;
  5237. ; Buffers:
  5238. ;
  5239. ; Months table
  5240. ;
  5241. MTABLE:    DB    0E1H        ; January -31
  5242. FEB:    DB    0E4H        ; February -28
  5243.     DB    0E1H,0E2H,0E1H,0E2H ; Mar-Jun -31,-30,-31,-30
  5244.     DB    0E1H,0E1H,0E2H    ; Jul-Sep -31,-31,-30
  5245.     DB    0E1H,0E2H,0E1H    ; Oct-Dec -31,-30,-31
  5246.  
  5247.      ENDIF            ; Z80DOS/CPM3
  5248. ;
  5249. ; Messages and Error statements
  5250. ;
  5251. CKMS1:    DB    13,10,'++ ABORTED ++',0
  5252. CKMS2:    DB    8,' ',8,0
  5253. DRUMSG:    DB    'Drive/User',0
  5254. EOSMSG:    DB    '[more] ','$'
  5255.  
  5256.      IF    VSPAGE
  5257. MORERA:    DB    13,'                  ----------------------------------------'
  5258.     DB    13,10,'$'
  5259.      ENDIF            ; VSPAGE
  5260.  
  5261.      IF    NOT VSPAGE
  5262. MORERA:    DB    13,'        ',13,'$'
  5263.      ENDIF
  5264.  
  5265. ERRMS1:    DB    ' '
  5266. ERRMS2:    DB    'Error',0
  5267. ERRTAG:    DB    ' ->',0
  5268. NOFLM:    DB    '>> No detectable file(s) on ',0
  5269. NOFMS1:    DB    13,10,13,10,' ',0
  5270. NOFMS2:    DB    '  ',0
  5271. NOFMS3:    DB    ':  ',0
  5272. SOHFLG:    DB    0
  5273. CRLSPC:    DB    13,10,'          ',0
  5274. TOTMS1:    DB    ' Drive ',0
  5275. TOTMS4:    DB    '/',0
  5276. TOTMS5:    DB    'k  ',0
  5277. TOTMS6:    DB    ' Files: ',0
  5278. TOTMS7:    DB    ' Free: ',0
  5279. TOTMS8:    DB    'k ',0
  5280. ALLTOT:    DB    13,10,'             Total files: ',0
  5281. ALLTO1:    DB    'k',13,10,0
  5282.  
  5283.      IF    PRBRDR
  5284. CONTM1:    DB    13,10,'** There are ',0
  5285. MFILES:    DB    ' member files in ',0
  5286. LIBR:    DB    ' library(s) and/or archive(s) **',0
  5287. AFMSP1:    DB    13,10,'** Archive directory for ',0
  5288. LFMSP1:    DB    13,10,'** Library directory for ',0
  5289. LFMSP3:    DB    'k'
  5290.     DB    ' **'
  5291.     DB    13,10,0
  5292.      ENDIF            ; PRBRDR
  5293.  
  5294.      IF    NOT PRBRDR
  5295. CONTM1:    DB    13,10,'There are ',0
  5296. MFILES:    DB    ' member files in ',0
  5297. LIBR:    DB    ' library(s) and/or archive(s)',0
  5298. AFMSP1:    DB    13,10,'Archive directory for ',0
  5299. LFMSP1:    DB    13,10,'Library directory for ',0
  5300. LFMSP3:    DB    'k'
  5301.     DB    13,10,0
  5302.      ENDIF            ; Not PRBRDR
  5303.  
  5304. NLBRF:    DB    '++ Not a library file ++',13,10
  5305. NARCF:    DB    '++ Not an archive file ++',13,10
  5306. LBRTYP:    DB    'LBR'
  5307. ARCTYP:    DB    'AR'        ; We only test the first 2 in the loop.
  5308.                 ; The C or K are tested separately.
  5309. ;
  5310. ; Permanently initialized data area
  5311. ;
  5312. VECTBL:    DW    DSKERR        ; BDOS record error intercept vector
  5313.     DW    DSKERR        ; BDOS select error intercept vector
  5314. ;
  5315. ; End of code that must be stored on disk in the .COM file
  5316. ;
  5317. ; Data area reinitialized by code when SD is run or rerun
  5318. ;
  5319. DATA0    EQU    $        ; Start of area to initialize
  5320.  
  5321. OTBL    EQU    $        ; Mark start of option table
  5322. VFLAG:    DS    1
  5323. AOPFLG:    DS    1
  5324. COPFLG:    DS    1
  5325. DOPFLG:    DS    1
  5326. FOPFLG:    DS    1
  5327. HOPFLG:    DS    1
  5328. LOPFLG:    DS    1
  5329. NOPFLG:    DS    1
  5330. OOPFLG:    DS    1
  5331. POPFLG:    DS    1
  5332. QOPFLG:    DS    1
  5333. ROPFLG:    DS    1
  5334. SOPFLG:    DS    1
  5335. TOPFLG:    DS    1
  5336. VOPFLG:    DS    1
  5337. XOPFLG:    DS    1
  5338.  
  5339.      IF    Z80DOS OR CPM3
  5340. DEOPFL:    DS    1
  5341. DPOPFL:    DS    1
  5342. DMOPFL:    DS    1
  5343. DNOPFL:    DS    1
  5344. DAOPFL:    DS    1
  5345. DGOPFL:    DS    1
  5346. NODFLG:    DS    1
  5347.      ENDIF            ; Z80DOS/CPM3
  5348.  
  5349.      IF    FATTRIB
  5350. ONEFLG:    DS    1
  5351. TWOFLG:    DS    1
  5352. THRFLG:    DS    1
  5353. FORFLG:    DS    1
  5354.      ENDIF
  5355.  
  5356. OEND    EQU    $        ; End of option table
  5357. ;
  5358. ; End of option lookup table
  5359. ;
  5360. BUFPNT:    DS    2        ; Next location in output buffer
  5361. BUFCNT:    DS    1        ; Number of bytes left in output buffer
  5362. OUTFCB:    DS    1+8+3        ; User number, filename, and filetype
  5363. ;
  5364. ; Beginning of area reinitialized to zero each time SD.COM is run
  5365. ;
  5366.     DS    21        ; Rest of DISK.DIR FCB
  5367. DISKNO:    DS    1        ; Disk number
  5368. USERNO:    DS    1        ; User number
  5369. OPNFLG:    DS    1        ; File open flag
  5370. DRVFLG:    DS    1        ; D option check for prior drive specificaton
  5371. FNDFLG:    DS    1        ; Files Matched Flag
  5372. BYEACT:    DS    1        ; BYE Active Flag
  5373.  
  5374. LINCNT:    DS    1        ; # lines printed on screen
  5375. LLENLOC:DS    2        ; Running total of .LBR length
  5376. LMTOTL:    DS    2
  5377. LBTOTL:    DS    2
  5378. LNCNT:    DS    1
  5379. LCOUNT:    DS    2
  5380. NEXTL:    DS    2
  5381. SLFILE:    DS    2
  5382. LINES:    DS    1        ; Number of lines to be printed
  5383. FIRSTT:    DS    1        ; First time flag for version number
  5384. ISARC:    DS    1
  5385. ;
  5386. ; Uninitialized data area
  5387. ;
  5388. BASUSR:    DS    1        ; Copy of original directory user #
  5389. BLKMAX:    DS    2        ; Highest block # on drive
  5390. BLKMSK:    DS    1        ; Records/block - 1
  5391. BLKSHF:    DS    1        ; Number shifts to mult by sec/blk
  5392. COUNT:    DS    2        ; Entry count
  5393. DIRMAX:    DS    2        ; Highest file # in directory
  5394. FILERC:    DS    2        ; File size in records
  5395. FREEBY:    DS    2        ; Number of k left on dir. drive
  5396. FSIZEC:    DS    1        ; File size character ('k' or 'r')
  5397. GAP:    DS    2        ; Sort routine storage
  5398. I:    DS    2        ; Sort routine storage
  5399. J:    DS    2        ; Sort routine storage
  5400. JG:    DS    2        ; Sort routine storage
  5401. LZFLG:    DS    1        ; 0 when printing leading zeros
  5402. MAXUSR:    DS    1        ; Max user # for drive
  5403. NEWUSR:    DS    1        ; User # selected by "$U" option
  5404. NEXTT:    DS    2        ; Next table entry
  5405. OLDDSK:    DS    1        ; Currently logged-in drive
  5406. OLDUSR:    DS    1        ; User number upon invocation
  5407. SCOUNT:    DS    2        ; # to sort
  5408. SUPSPC:    DS    1        ; Leading space flag
  5409. TBLOC:    DS    2        ; Start of name table
  5410. TOTFIL:    DS    2        ; Total number of files
  5411. TOTSIZ:    DS    2        ; Total size of all files
  5412. TOTFL1:    DS    2        ; Total files of all D/U
  5413. TOTSZ1:    DS    2        ; Total size of all D/U
  5414. TOTFRE:    DS    2
  5415. USRNR:    DS    1        ; User number
  5416. VERFLG:    DS    1        ; CP/M version number (0=pre-CP/M 2)
  5417. ZRDFLG:    DS    1        ; ZRDOS version number
  5418.  
  5419.      IF    Z80DOS OR CPM3
  5420. DATPLS:    DS    1        ; Holds +/- flag for date math
  5421. DATCH1:    DS    2        ; Holds first input date
  5422. DATCHK:    DS    2        ; Holds date to look for
  5423. DTMTCH:    DS    1        ; Holds <,>=,>
  5424. DATMOD:    DS    2        ; Holds date found for file
  5425. DAYS:    DS    2        ; temporary buffers
  5426. YEARS:    DS    1        ; 
  5427. YEARS1:    DS    1
  5428. MONTHS:    DS    1
  5429. DAYS1:    DS    1
  5430. ASCII:    DS    5        ; holds date from system
  5431.      ENDIF            ; Z80DOS/CPM3
  5432.  
  5433.      IF    CPM3
  5434. LATDAT:    DS    2
  5435.      ENDIF            ; CPM3
  5436.  
  5437. DATA1    EQU    $        ; End of area to initialize
  5438.  
  5439.      IF    ZCPR33
  5440. Z3DRVL:    DS    2        ; Points to Z33 max drv location
  5441. Z3USRL:    DS    2        ; Points to Z33 max user location
  5442. Z3WHLL:    DS    2        ; Points to Z33 wheel location
  5443.      ENDIF            ; ZCPR33
  5444.  
  5445.      IF    NDIRS
  5446. NAMADR:    DS    2        ; Named Directory Buffer Address
  5447. NUMDIR:    DS    1        ; Number of entries
  5448. CURDIR:    DS    1        ; NDR Check counter
  5449.      ENDIF            ; NDIRS
  5450.  
  5451.      IF    SHOPUB
  5452. PUBDRV:    DS    1        ; Storage for Public Drive byte
  5453. PUBUSR:    DS    1        ; "    "    "      User     "
  5454.      ENDIF            ; SHOPUB
  5455.  
  5456. GETABL:    DS    1
  5457. LBRFCB:    DS    36
  5458. LBBUF:    DS    128
  5459.  
  5460. ANAME:    DS    13
  5461. ASIZE:    DS    14
  5462. ARCFIL:    DS    16
  5463.  
  5464. NEWPTR:    DS    2        ; Start of second table
  5465. XPOINT:    DS    2
  5466. JUMPER:    DS    2        ; Increment for second table to
  5467. WASHERE:
  5468.     DS    1
  5469. VSFRST:    DS    1
  5470. OUTBUF:    DS    128        ; Output file buffer
  5471. ;
  5472. ; BDOS equates
  5473. ;
  5474. BDOS    EQU    0005H        ; Entry Point for BDOS calls
  5475. FCB    EQU    005CH        ; Default FCB Address
  5476. TBUF    EQU    0080H        ; Default DMA Address
  5477.  
  5478. RDCON    EQU    1        ; Console input
  5479. WRCON    EQU    2        ; Console output
  5480. LIST    EQU    5        ; List output
  5481. PRINT    EQU    9        ; Print string
  5482. CONST    EQU    11        ; Get console status
  5483. CPMVER    EQU    12        ; Return CP/M version
  5484. RESET    EQU    13        ; Reset disk system
  5485. SELDSK    EQU    14        ; Select disk
  5486. OPEN    EQU    15        ; Open file
  5487. CLOSE    EQU    16        ; Close file
  5488. SRCHF    EQU    17        ; Search for first
  5489. SRCHN    EQU    18        ; Search for next
  5490. READ    EQU    20        ; Read sequential
  5491. WRITE    EQU    21        ; Write sequential
  5492. MAKE    EQU    22        ; Make file
  5493. CURDSK    EQU    25        ; Return current disk
  5494. STDMA    EQU    26        ; Set DMA Address
  5495. DSKALL    EQU    27        ; Get address of allocation vector
  5496. DSKPAR    EQU    31        ; Get address of disk parameters
  5497. STUSER    EQU    32        ; Set/get user number
  5498.  
  5499.      IF    ZRDOS
  5500. ZRDVER    EQU    48        ; Return version (ZRDOS)
  5501. SETWBT    EQU    50        ; Set warm boot trap (ZRDOS)
  5502. RESWBT    EQU    52        ; Reset warm boot trap (ZRDOS)
  5503.      ENDIF            ; ZRDOS
  5504.  
  5505.     DS    60        ; Stack area
  5506. STACK:    DS    2        ; Old stack pointer
  5507.  
  5508. ORDER    EQU    $        ; Order table starts here
  5509.  
  5510.     END
  5511.