home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / jsage / znode3 / z80dos / sdzd136.lbr / SDZD136.AZM / SDZD136.ASM
Encoding:
Assembly Source File  |  1993-06-08  |  113.8 KB  |  5,297 lines

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