home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / BEEHIVE / BBS / ZCMD28.ASM < prev   
Assembly Source File  |  2000-06-30  |  82KB  |  2,961 lines

  1. ;
  2. ;   ZCMD   - Z80 CCP command processor program replacement
  3. ;   v2.8
  4. ; 07/22/86 - Tom Brady  Decibel RCP/M (PBBS)  (404) 288-6858
  5. ;
  6. ; The EQUates are currently set for use by an RCP/M -- you will want
  7. ;  verify the settings of those equates tagged with an asterisk (*)
  8. ;  beside the comment field for your particular system needs.
  9. ;
  10. ; NOTE:     Read ZCMD.HIS for a complete history of updates.
  11. ;
  12. ;   ZCMD2 is ZCPR2.2.3 with special RCPM features for RCPM use.
  13. ;   ZCPR2 was originally written by Richard Conn.
  14. ;
  15. ; Extensive documentation on ZCPR2 and the utilities in the ZCPR2 system
  16. ;  can be found in the following manuals:
  17. ;
  18. ;        ZCPR2 Concepts Manual
  19. ;        ZCPR2 Installation Manual
  20. ;        ZCPR2 User's Guide
  21. ;        ZCPR2 Rationale
  22. ;
  23. ; ******** Structure Notes ********
  24. ;
  25. ; ZCMD2 is divided into a number of major sections.  The following is an
  26. ;   outline of these sections and the names of the major routines located
  27. ;   therein.
  28. ;
  29. ; Section    Function/Routines
  30. ; -------    -----------------
  31. ;
  32. ;   --        Opening Comments, Equates, and Macro Definitions
  33. ;
  34. ;    0        JMP Table into ZCMD2
  35. ;
  36. ;    1        Buffers
  37. ;
  38. ;    2        CCP Starting Modules
  39. ;            CCP    CCP1    CONT    RESTRT    RS1
  40. ;            CAPBUF    RSTCCP    RCCPNL    ERROR    PRNNF
  41. ;
  42. ;    3        Utilities
  43. ;            CRLF    CONOUT    CONIN    LCOUT    LSTOUT
  44. ;            PAGER    READF    READ    BDOSB    PRINTC
  45. ;            PRINT    PRIN1    GETDRV    DEFDMA    DMASET
  46. ;            RESET    BDOSJP    LOGIN    OPENF    OPEN
  47. ;            GRBDOS    CLOSE    SEARF    SEAR1    SEARN
  48. ;            SUBKIL    DELETE    GETUSR    SETUSR
  49. ;
  50. ;     4     CCP Utilities
  51. ;            SETUD    UCASE    REDBUF    BREAK    SDELM
  52. ;            ADVAN    SBLANK    ADDAH    NUMBER    NUMERR
  53. ;            HEXNUM    DIRPTR    SLOGIN    DLOGIN    SCANLOG
  54. ;            SCANER    SCANX    SCANF    CMDSER
  55. ;
  56. ;     5     CCP-Resident Commands and Functions
  57. ;     5A        DIR    DIRPR    PRFN    GETSBIT FILLQ
  58. ;     5B        ERA
  59. ;     5C        LIST
  60. ;     5D        TYPE
  61. ;     5E        SAVE    EXTEST
  62. ;     5F        REN
  63. ;     5G        JUMP
  64. ;     5H        GO
  65. ;     5I        COM    CALLPROG
  66. ;     5J        GET    MLOAD    PRNLE    PATH
  67. ;
  68. ;-----
  69. ;
  70. ;  The following equates may be used to customize this CCP for the user's
  71. ;  system and integration technique.  The following constants are provided:
  72. ;
  73. ;    REL    - YES if integration is to be done via MOVCPM
  74. ;        - NO if integration is to be done via DDT and SYSGEN
  75. ;
  76. ;    CCPLOC - Beginning address of CCP; this value can be obtained by
  77. ;          running the public domain utility PROBE.
  78. ;
  79. ;=====
  80. ;
  81. ; SPECIAL NOTE:  Look for and change the following lines for your system
  82. ;         requirements.  This is the area that is stuffed with a 
  83. ;         command for auto-execution upon cold boot.  As an example,
  84. ;         upon cold boot, your computer would run SUBMIT.COM and 
  85. ;         look in BOOT.SUB for instructions.  The character count 
  86. ;         is 11.
  87. ;         
  88. ; * EXAMPLE ONLY * LEAVE COMMENTED OUT * 
  89. ;
  90. ;CHRCNT: DB    11        ; Number of valid chars in command line
  91. ;CMDLIN: DB    'SUBMIT BOOT'   ; Default (cold boot) command
  92. ;     DB    0        ; Command string terminator
  93. ;
  94. ;=====
  95. ;
  96. NO    EQU    0
  97. YES    EQU    NOT NO
  98. ;
  99. ; ************************************
  100. ; USER CONFIGURABLE EQUATES BEGIN HERE
  101. ; ************************************
  102. ;
  103. REL    EQU    NO        ; Yes, for MOVCPM integration
  104. MAKESPR    EQU    NO        ; Yes, for SPR generation
  105. OZFLOP    EQU    NO        ; Yes, if booting Ozzie-1 from floppy
  106.                 ;   disk system tracks.    
  107.                 ; No, if MAKESPR is YES (Read OZZIE-1.NOT)
  108. ;
  109.      IF    NOT MAKESPR
  110.      IF    REL
  111. CCPLOC    EQU    0        ; MOVCPM image
  112.      ENDIF
  113. ;
  114. ; If REL is NO, obtain the beginning address of your current CCP
  115. ;  using PROBE (or its equivalent), then merely set CCPLOC to that
  116. ;  value as as in the following line:
  117. ;
  118.      IF    (NOT OZFLOP) AND (NOT REL)
  119. CCPLOC    EQU    0D800H        ;*Fill in with BDLSLOC-supplied value
  120.      ENDIF
  121. ;
  122.      IF    OZFLOP AND (NOT REL)
  123. CCPLOC    EQU    0D400H        ; Ozzie-1 floppy disk default CCP
  124.                 ;   location is here
  125.      ENDIF
  126. ;
  127. ; The following gives the required offset to load the CCP into the CP/M
  128. ;  SYSGEN image through DDT (the Roffset command).  Note that this value
  129. ;  conforms with the standard value presented in the CP/M reference manuals,
  130. ;  but it may not necessarily conform with the location of the CCP in your
  131. ;  CP/M system -- several systems (Morrow Designs, P&T, Heath ORG-0 and
  132. ;  others) have the CCP located at a non-standard address in the SYSGEN image.
  133. ;
  134.      IF    NOT REL
  135. ;;CCPR    EQU    980H-CCPLOC    ; DDT load offset for normal systems
  136. ;;CCPR    EQU    1100H-CCPLOC    ; DDT load offset for Morrow Designs
  137. CCPR    EQU    0B00H-CCPLOC    ; DDT load offset for Kaypro w/Advent Turbo Rom
  138.      ENDIF
  139. ;
  140. ; The following equate identifies the location of the BIOS.  This equate
  141. ;  assumes the standard sizes of 800H for ZCMD2 and 0E00H for BDOS and
  142. ;  does not need to be modified if the user is running a standard CP/M
  143. ;  configuration.
  144. ;
  145. BIOS    EQU    CCPLOC+800H+0E00H ; Address of BIOS
  146.      ENDIF
  147. ;
  148. ; The following macros define the file types of the command object files
  149. ;  (.COM files under CP/M 2.2) to be loaded when a non-resident ZCMD2
  150. ;  command is given and of the indirect command files (SUB files under
  151. ;  CP/M 2.2) to be used to extract commands from when the indirect 
  152. ;  command facility is invoked.
  153. ;
  154. COMTYP     MACRO
  155.     DB    'COM'        ; File type of command file
  156.      ENDM
  157. ;
  158. SUBTYP     MACRO
  159.     DB    'SUB'        ; File type of indirect command file
  160.      ENDM
  161. ;
  162. ; The following flag enables or disables the ability of ZCMD2 to process
  163. ;  SUBMIT files (command files of the form $$$.SUB).  If SUBON is YES,
  164. ;  then ZCMD2 will process such files like CP/M's CCP normally does; if
  165. ;  SUBON is NO, ZCMD2 will not process such files (just ignores them).  In
  166. ;  such a case only indirect command file facilities like ZEX will work.
  167. ;
  168. SUBON    EQU    yes        ;*Yes, enable processing of $$$.SUB files.
  169.                 ;   This is a large code eater so beware
  170.                  ;   of size.  It's a good one to set NO if
  171.                  ;   size >800H.
  172. ;
  173. ; The following flag allows ZCMD2 to accept commands like:  "A1:DIR".
  174. ;  If DRVPREFIX is YES, this form is accepted; if NO, this form is not
  175. ;  accepted.  This flag has the additional side effect of automatically
  176. ;  selecting files in the current disk/user if the command is of the form
  177. ;  "A3>CMND".  The DRVPFATT determines the attributes of selected
  178. ;  files if DRVPREFIX is YES.
  179. ;
  180. DRVPREFIX EQU    NO        ; YES to enable prefix.
  181. ;
  182. ; The following flag allows the user to select the attributes of the
  183. ;  files in the current disk/current user to be examined if the DRVPREFIX
  184. ;  flag YES.  The following values are defined:
  185. ;
  186. ;        DRVPFATT    Files Selected
  187. ;            0        System
  188. ;           80H        Directory
  189. ;            1        Both System and Directory
  190. ;
  191. DRVPFATT EQU    1        ; Select both system and directory
  192. ;
  193. ; The following flag enables or disables the ability to switch user
  194. ;  areas.  If your BBS system pokes the maximum drive/user area available
  195. ;  areas.  If your BBS system pokes DRVMAX/USRMAX memory areas (see below)
  196. ;  with a user's maximum drive/user area access, set USERON to YES and you
  197. ;  will be just as secure as if you had set it to NO.
  198. ;
  199. USERON    EQU    yes        ; Enable user specification
  200. SUPRES    EQU    no        ; No to see A0> instead of A>
  201. ;
  202. ; The following equate specifies the address of the PATH to be followed
  203. ;  for the PATH command-search if the PATH is to be initialized by the BIOS
  204. ;  and set by the user via a PATH.COM program.  The value of PATH should
  205. ;  be the address of the PATH data area in memory.  If the internal PATH
  206. ;  provided by Z80CCP is to be used, then INTPATH should be equated to YES,
  207. ;  which selects the PATH defined by the IPATH MACRO and the SYSOP path
  208. ;  (WHEEL).
  209. ;  If the external PATH is to be used, then INTPATH should be equated to NO
  210. ;  and an equate value for the address of the PATH should be provided.
  211. ;
  212. ; A PATH is a series of byte-pairs, terminated by a binary 0.  The first
  213. ;  byte of each pair is the disk number (1-16 for disks A-P), and the second
  214. ;  byte of each pair is the user number (0-31).    The special character '$'
  215. ;  indicates the current user or current disk.  For example, the path
  216. ;  from current disk/current user to current disk/user 0 to disk A/user 0
  217. ;  is selected by the following sequence:
  218. ;
  219. ;        DB    '$$'    ;current disk/user
  220. ;        DB    '$',0    ;current disk/user 0
  221. ;        DB    1,0    ;disk A/user 0
  222. ;        DB    0    ;end of path
  223. ;
  224. ; NOTE:  If DRVPREFIX is YES, then current disk/user is automatically
  225. ;  searched, and including it in the command search path causes it to be
  226. ;  searched twice, wasting time (and space in the path).  Since many environs
  227. ;  will run with DRVPREFIX = YES, then a good command search path would not
  228. ;  include the current disk/user.
  229. ;
  230. INTPATH    EQU    YES        ; NO to use external ZCMD2 path
  231. ;
  232.      IF    INTPATH
  233. IPATH     MACRO
  234.     DB    '$$'        ; Current drive/user
  235.     DB    'A'-'@',0    ; Drive A, user 0.  Set as many pairs as
  236.      ENDM            ;  you like, but leave off terminating 0.
  237.                 ;  That last 0 is provided elsewhere.
  238. ;
  239. ; The following equates define the extra path to search if the Wheel
  240. ;  byte is ON, and INTPATH is YES.
  241. ;
  242. SYSDRV    EQU    'A'-'@'        ; Search this drive if WHEEL byte on
  243. SYSUSR    EQU    15        ; User area of SYSDRV to find Sysop's
  244.                 ;   .COM files.
  245.      ENDIF
  246. ;
  247. ; This equate defines the base address of the external path
  248. ;
  249.      IF    NOT INTPATH    ; External path selected
  250. PATH    EQU    40H        ; External ZCMD2 path at CBIOS buffer
  251.                 ;   area
  252.      ENDIF            ; NOT INTPATH
  253. ;
  254. ; The following equate causes ERA to confirm on the files to be erased
  255. ;  before it goes ahead and erases them.  If ERAOK is YES, then the user
  256. ;  will be prompted each time; if it is NO, then the user will not be
  257. ;  prompted.
  258. ;
  259. ERAOK    EQU    yes        ; YES for prompt
  260. ;
  261. ; If ERAOK is YES, the following equate adds a Verify option to the ERA
  262. ;  command which causes the user to be prompted only if the Verify option
  263. ;  letter, defined by ERDFLG, is given after the file name.  If ERAV is
  264. ;  NO then the user will be asked to verify only when ERDFLG is contained
  265. ;  in the command line; if ERAV is NO, the user will always be asked to
  266. ;  verify.
  267. ;
  268. ERAV    EQU    YES        ; Enable verify option
  269. ERDFLG    EQU    'V'        ; Set option letter
  270. ;
  271. ;
  272. ; If both BYCLOCK and BYTLOS are set NO (probably because you aren't
  273. ;  running NUBYE/BYE5), but you have a clock and want the [hh:mm] shown
  274. ;  before the drive/user prompt -- set CLOCK to YES.  You must also
  275. ;  edit the macro and clock reading code below for your system needs.
  276. ;
  277. CLOCK    EQU    no        ;*Yes, you have a clock, but aren't
  278.                 ;  running NUBYE/BYE5 and want a clock
  279.                 ;  display.
  280. ;
  281.      IF    CLOCK
  282. ;
  283. ; CKCLOK is used to check the clock's existence.  If it is turned off
  284. ;  (i.e. the clock is in your external modem, which is turned off) or
  285. ;  not present, it will skip putting the time in the prompt.  Also allows
  286. ;  easy assembly of ZCMD for machines in which the clock might be an
  287. ;  optional item to be added later (i.e. Kaypro's).  CKCLOK should 
  288. ;  initialize and check the real-time clock.  If it is present and
  289. ;  functioning, call TIME, else fall through without doing anything (just
  290. ;  displays the normal du> prompt).
  291. ;
  292. ; NOTE: Example code is for Kaypro internal clock
  293. ;
  294. CKCLOK     MACRO
  295.     MVI    A,0FH        ; Initialize PIO port to clock
  296.     OUT    22H
  297.     MVI    A,0CH        ; Check 'clock initialized' flag set
  298.     OUT    20H        ;  by TIME.COM and CLOCK.BAS
  299.     IN    24H        ; Get flag value
  300.     CPI    29H        ; Initialized?
  301.     CZ    TIME        ; Yes, so print [hh:mm]
  302.      ENDM
  303. ;
  304. ; RDCLOK is used to read the clock.  Defined as a macro, it will be located
  305. ;  at TIME:, and should get the HH and MM in BCD, call ASCII (as in the
  306. ;  sample below) to set up the prompt and then jump to PRIN1 to print it
  307. ;  and return.  Modify this to fit your system requirements if CLOCK is YES.
  308. ;
  309. ; NOTE: Example code is for Kaypro internal clock
  310. ;
  311. RDCLOK     MACRO
  312.     MVI    A,4        ; Get hours register
  313.     OUT    20H        ; Set that into latch
  314.     IN    24H        ; Input BCD value into A
  315.     ORA    A        ; Midnight (0)?
  316.     JRNZ    RDCLK1        ; No, skip fix
  317.     MVI    A,12H        ; Load 12 (midnight)
  318. RDCLK1:    CPI    13H        ; PM (13-23 o'clock)?
  319.     JRC    RDCLK2        ; No, so print it else...
  320.     SUI    12H        ; Subtract 12 to make it 12-hour time
  321.     DAA            ; BCD adjustment of subtract
  322. RDCLK2:    LXI    H,ANSHH        ; Set pointer to HH in prompt memory
  323.     CALL    ASCII        ; And put HH into it in ASCII
  324.     LDA    ANSHH        ; Get tens of hours
  325.     CPI    '0'        ; Leading zero?
  326.     JRNZ    RDCLK3        ; No, so skip fix
  327.     MVI    A,' '        ; Fix with space
  328.     STA    ANSHH        ; Put it in message
  329. RDCLK3:    MVI    A,3        ; Get minutes register
  330.     OUT    20H        ; Set that into latch
  331.     IN    24H        ; Input BCD value to A
  332.     LXI    H,ANSMM        ; Set pointer to MM in prompt memory
  333.     CALL    ASCII        ; And put MM into it in ASCII
  334.     MVI    A,16        ; Set to R/O register
  335.     OUT    20H        ; Put in latch to protect clock on power-down
  336.     LXI    H,TMSG
  337.     JP    PRIN1        ; And print it -- done.
  338.      ENDM
  339.      ENDIF            ; CLOCK AND (NOT BYCLOCK) and (NOT BYTLOS) 
  340. ;
  341. ; NOTE: Either specify BYCLOCK and BYTLOS as NO, or one as YES and the 
  342. ;  other as NO -- but -- don't specify both as YES.
  343. ;
  344. ; The following equates (BYCLOCK/BYTLOS/SHOW) enable the appearance of
  345. ;  [hh:mm], [Left:nn] and [On:nn] before the drive/user prompt, if you
  346. ;  have a clock and are running NUBYE or BYE5.  A check is made to see
  347. ;  if NUBYE/BYE5 is running and skips the clock read if not.
  348. ;
  349. BYCLOCK    EQU    NO        ;*Yes, if NYBYE/BYE5 has a clock installed
  350.                  ;   and you want the [HH:MM] displayed before
  351.                  ;   the du>.
  352.                 ;   PRIDRIV must be NO for this to work.
  353.                 ;
  354. BYTLOS    EQU    yes        ;*Yes, if NUBYE/BYE5 has a clock installed
  355.                  ;   and you want the [Left:nn] displayed
  356.                  ;   before the du>, where nn will indicate
  357.                  ;   time-left-on-system.
  358. SHOW    EQU    yes        ;*Yes, if WHEEL is set, or user has
  359.                 ;  unlimited time and you wish to show
  360.                 ;  time-on-system as: '[On:nn]'.
  361.                 ; NO, if you want to disable display when
  362.                 ;  WHEEL is set or user has unlimited time.
  363. ;
  364. ; WARNING -- BYTLOS takes more code than BYCLOCK -- You may have to
  365. ;  set SUBON to NO in order to keep the size below 800H.
  366. ;
  367. ; If you set one of the three transient command equates from above 
  368. ;  (i.e. ERAON, SAVEON, OR RENON) to NO, this should keep you well within
  369. ;  the 800H limit... The CP/M utility NSWEEP provides you with all three
  370. ;  functions.  If you wish to keep these transient commands and use BYTLOS,
  371. ;  you will probably have to set SUBON to NO. [tmb]
  372. ;
  373. ; The MULTCMD equate enables the feature of having more than
  374. ;  one command on the same line, separated by a separation char
  375. ;  which is defined by the CMDSEP equate. 
  376. ;
  377. ;  If SUBON is YES, then MULTCMD must be NO - a bug for future fix...? 
  378. ;
  379. MULTCMD    EQU    yes        ;*Yes, allow multiple commands
  380. CMDSEP    EQU    ';'        ; Command separator
  381. ;
  382. ; The following equate allows selection of using an internal or an ex-
  383. ; ternal command buffer.
  384. ;
  385. EXCBUF    EQU    yes        ; YES to use external command buffer
  386. ;
  387.      IF    MULTCMD    AND EXCBUF
  388. CLBASE    EQU    0F093H        ; Base address of buffer
  389. BUFLEN    EQU    164        ; 164 bytes in input buffer
  390.      ENDIF
  391. ;
  392. ; The following flags enable or disable various ZCMD2-resident commands.
  393. ;  The user may invoke these as desired, but should keep in mind the size
  394. ;  of the resulting ZCMD2 and make sure it does not exceed the required
  395. ;  limits.
  396. ;
  397. DIRON    EQU    NO        ; DIR
  398. LTON    EQU    NO        ; LIST, TYPE
  399. GOON    EQU    NO        ; GO
  400. ERAON    EQU    yes        ;*ERA  \    Can't have all 3 and stay <800H
  401. SAVEON    EQU    yes        ;*SAVE  --> (with BYTLOS and SUBON set YES)
  402. RENON    EQU    yes        ;*REN  /    Use NSWP to replace either/all.
  403. GETON    EQU    NO        ; GET
  404. JUMPON    EQU    NO        ; JUMP
  405. ; When the WHEEL byte (low memory byte, normally located at 3EH) is
  406. ;  used, certain system functions can have restricted access (i.e.
  407. ;  ERA may only be used when the WHEEL is ON -- Sysop access).  If this
  408. ;  byte is not zero, then the command proceeds.    If it is zero, then the
  409. ;  command is not allowed to proceed and is exited with an error message.
  410. ;
  411. WHEEL    EQU    YES        ; Set YES for RCP/M use always and most
  412.                 ;   all other applications
  413. WHLADR    EQU    3EH        ; Normal address of WHEEL byte
  414. ;
  415. ; The following set of equates make each of the indicated commands
  416. ;  selectable to respond to the WHEEL byte or not (i.e. if WERA is YES,
  417. ;  then the ERAse function works when the WHEEL byte is on/set as for
  418. ;  Sysop privileges.)
  419. ;
  420. WERA    EQU    YES        ; ERA only if/when WHEEL is on/set?
  421. WREN    EQU    YES        ; REN  "     "         "     "    "
  422. WLT    EQU    YES        ; TYPE "     "         "     "    "
  423. WGO    EQU    YES        ; GO   "     "         "     "    "
  424. WSAVE    EQU    YES        ; SAVE "     "         "     "    "
  425. WGET    EQU    YES        ; GET  "     "         "     "    "
  426. WJUMP    EQU    YES        ; JUMP "     "         "     "    "
  427. WDU    EQU    NO        ; DU:  "     "         "     "    "
  428. ;
  429. PRIVDIR    EQU    NO        ; No, for most everybody (especially RCP/M's)
  430.                 ; If YES, do not allow users to access
  431.                 ;    other's directories unless the
  432.                 ;    WHEEL byte is on/set.  This disables
  433.                 ;    DU's in the FCB, DRVPREFIX and also
  434.                 ;    the printing of the current DU.
  435. ;
  436. ; The INTSTACK equate is used to specify if the stack is internal or
  437. ; external to ZCMD2.  Naturally, quite a bit of space is saved if the
  438. ; stack is placed external to ZCMD2.  If such is the case, the user
  439. ; should set the STKBASE equate to the beginning of the stack area
  440. ; (bottom of the stack).
  441. ;
  442. ; NOTE: THIS IS THE BOTTOM OF THE STACK, NOT THE TOP OF THE STACK.
  443. ;
  444. ; If INTSTACK is YES, the stack is internal to ZCMD2.  If INTSTACK is NO
  445. ; the stack is external to ZCMD2, and the base of the stack (bottom of
  446. ; the stack) is located at STKBASE.
  447. ;
  448. INTSTACK EQU    no        ; Enable or disable internal stack
  449. ;
  450.      IF    NOT INTSTACK
  451. STKBASE    EQU    0F043H        ; Address of bottom of external stack
  452. STACK    EQU    STKBASE+4FH    ; Address of top of stack
  453.                 ; (stack size should be at least 48 bytes)
  454.      ENDIF
  455. ;
  456. ; *** Terminal and 'type' customization equates
  457. ;
  458. NLINES    EQU    24        ;*Number of lines on crt screen
  459. WIDE    EQU    YES        ; Yes for normal directory display
  460. FENCE    EQU    '|'        ;*Separation character between files
  461. HBCON    EQU    NO        ;*Yes, ok to send characters with Hi bit
  462.                 ;   set (i.e. file attribute bits) to
  463.                 ;   screen unchanged.
  464. HBLST    EQU    NO        ;*Yes, ok to send characters with Hi bit
  465.                 ;   set to LST device unchanged.
  466. PGDFLT    EQU    NO        ; Yes, pauses at each screenful of output
  467. PGDFLG    EQU    'P'        ; For type command: page or not (dep on
  468.                 ;   PGDFLT).  This flag reverses the
  469.                 ;   default effect.
  470. ; other general equates
  471. ;
  472. MAXDISK    EQU    16        ;*Maximum number of drives
  473.                 ; (i.e. 8 = drives A through H available)
  474. USRMAX    EQU    3FH        ; *** 3FH is recommended, if used *** 
  475.                 ; Location of byte in memory containing
  476.                 ;   number of highest allowable user
  477.                 ;   code +1.  This is set to MAXUSR if BYE
  478.                 ;   is not present, and after that it is con-
  479.                 ;   trolled by system programs.  Then if
  480.                 ;   USRMAX=0, MAXUSR cannot be dynamically
  481.                  ;   changed, and should be permanently set.
  482. MAXUSR    EQU    15        ; Maximum user number accessable (0-15)
  483.                 ;
  484. DRVMAX    EQU    3DH        ; *** 03DH is reccomended, if used ***
  485.                 ; Location of byte in memory containing
  486.                 ;   maximum legal drive, this value is
  487.                 ;   set to MAXDISK if BYE is not present
  488.                 ;   After that controlled by system programs.
  489.                 ;   If DRVMAX=0 then MAXDISK cannot be
  490.                 ;   changed by external programs, and
  491.                 ;   should be permanently set.
  492. SYSFLG    EQU    'A'        ; For dir command: list $SYS and $DIR
  493. SOFLG    EQU    'S'        ; For dir command: list $SYS files only
  494. SPRMPT    EQU    '$'        ; CCP prompt indicating submit command
  495. NPROMPT    EQU    '>'        ; CCP prompt when WHEEL byte is OFF
  496.                 ;   NOTE: With ZEX, add +80H
  497. WPROMPT    EQU    '}'        ; CCP prompt if WHEEL byte is ON
  498.                 ;   (Set to '>' if you want both the same)
  499.                 ;   NOTE: With ZEX, add +80H
  500. NUMBASE    EQU    'H'        ; Switches from default to number base
  501. SECTFLG    EQU    'S'        ; Option character for save command
  502. CURIND    EQU    '$'        ; Symbol for current disk or user
  503. COMMENT    EQU    ';'        ; Depicts comment lines
  504. ;
  505. ; CCP command name table - each table entry is composed of the 4-byte
  506. ; command and 2-byte address
  507. ;
  508. NCHARS    EQU    4        ; Number of chars/command
  509. ;
  510. CTABLE     MACRO
  511. ;
  512.      IF    DIRON
  513.     DB    'ODIR'
  514.     DW    DIR        ; Directory display command
  515.      ENDIF
  516. ;
  517.      IF    LTON
  518.     DB    'LIST'
  519.     DW    LIST        ; List file on printer command
  520.     DB    'TYPE'
  521.     DW    TYPE        ; Type file on console command
  522.      ENDIF
  523. ;
  524.      IF    GOON
  525.     DB    'GO  '
  526.     DW    GO        ; Execute current tpa command
  527.      ENDIF
  528. ;
  529.      IF    ERAON
  530.     DB    'ERA '
  531.     DW    ERA        ; Erase files command
  532.      ENDIF
  533. ;
  534.      IF    SAVEON
  535.     DB    'SAVE'
  536.     DW    SAVE        ; Save tpa command
  537.      ENDIF
  538. ;
  539.      IF    RENON
  540.     DB    'REN '
  541.     DW    REN        ; Rename files command
  542.      ENDIF            ; RENON
  543. ;
  544.      IF    GETON
  545.     DB    'GET '
  546.     DW    GET        ; Load file into TPA command
  547.      ENDIF            ; GETON
  548. ;
  549.      IF    JUMPON
  550.     DB    'JUMP'
  551.     DW    JUMP        ; Jump to any memory location command
  552.      ENDIF
  553.      ENDM
  554. ;
  555. ; This equate determines if the ZCMD2 FCB is located internal to or ex-
  556. ; ternal to ZCMD2.  If EXTFCB is YES, FCBADR defines where it is found.
  557. ; Placing the ZCMD2 FCB external to ZCMD2, more space is left for other
  558. ; uses within ZCMD2.
  559. ;
  560. EXTFCB    EQU    NO        ; Allow external FCB
  561. ;
  562.      IF    EXTFCB
  563. FCBADR    EQU    0EFD0H        ; Address of external FCB
  564.      ENDIF
  565. ;
  566. ; CMDRUN - ZCMD2 Extended Command Processing Facility
  567. ;
  568. ; This equate enables the ZCMD2 CMDRUN facility.  If CMDRUN is YES, then
  569. ; another stage of command processing is invoked should ZCMD2 fail to
  570. ; find a COM file when the user gives a command.  This stage involves
  571. ; invoking the .COM file specified by CMDFCB and giving it the current
  572. ; command line as an argument.    In this way, if, say, M80 PROG2 fails as
  573. ; a command, a new command like LRUNZ M80 PROG2, SUB M80 PROG2, or ZEX
  574. ; M80 PROG2 may be processed.  If the new command fails, an appropriate
  575. ; error message is given.
  576. ;
  577. ; The ROOTONLY option causes ZCMD2 to only look at the Root (bottom of
  578. ; path) for the Extended Command Processor if it is set to YES.  If it
  579. ; is set to NO, the path is searched for the Extended Command Processor.
  580. ; The tradeoff here is that ROOTONLY = YES is less flexible but somewhat
  581. ; faster than ROOTONLY = NO.
  582. ;
  583. CMDRUN    EQU    NO        ; Enable the facility
  584. ;
  585.      IF    CMDRUN
  586. ROOTONLY EQU    YES        ; True if look at root only for extended
  587.                 ;   command processor, NO if look along
  588.                 ;   path
  589. CMDFCB     MACRO
  590.     DB    0
  591.     DB    'CMDRUN  '    ; Name of program
  592.     DB    'COM'        ; File type
  593.      ENDM
  594.      ENDIF
  595. ;
  596. ; end of customization section
  597. ;-----
  598. ;
  599. CR    EQU    0DH
  600. LF    EQU    0AH
  601. TAB    EQU    9
  602. ;
  603. WBOOT    EQU    0        ; CP/M warm boot address
  604. UDFLAG    EQU    4        ; User num in high nybble, disk in low
  605. BDOS    EQU    5        ; BDOS function call entry point
  606. TFCB    EQU    5CH        ; Default FCB buffer
  607. TBUFF    EQU    80H        ; Default disk I/O buffer
  608. TPA    EQU    100H        ; Base of TPA
  609. ;
  610. ; MACROS to provide Z80 extensions - MACROS include:
  611. ;
  612.     $-MACRO            ; First turn off the expansions
  613. ;
  614. ;    JR    - JUMP RELATIVE
  615. ;    JRC    - JUMP RELATIVE IF CARRY
  616. ;    JRNC    - JUMP RELATIVE IF NO CARRY
  617. ;    JRZ    - JUMP RELATIVE IF ZERO
  618. ;    JRNZ    - JUMP RELATIVE IF NO ZERO
  619. ;    DJNZ    - DECREMENT B AND JUMP RELATIVE IF NO ZERO
  620. ;    LDIR    - MOV @HL TO @DE FOR COUNT IN BC
  621. ;    LXXD    - LOAD DOUBLE REG DIRECT
  622. ;    SXXD    - STORE DOUBLE REG DIRECT
  623. ;
  624. ;    @GENDD macro used for checking and generating
  625. ;           8-bit jump relative displacements.
  626. ;
  627. @GENDD     MACRO    ?DD        ; ; Checks range of 8-bit displacements
  628. ;
  629.      IF    (?DD GT    7FH) AND (?DD LT 0FF80H)
  630.     DB    100H        ; Displacement range error on jump rel.
  631.      ELSE
  632.     DB    ?DD
  633.      ENDIF            ; ; Range error
  634.      ENDM            ; ; MACRO
  635. ;
  636. ;-----
  637. ;
  638. ; Z80 macro extensions
  639. ;
  640. JR     MACRO    ?N        ; ; Jump relative
  641.     DB    18H
  642.     @GENDD    ?N-$-1
  643.      ENDM
  644. ;
  645. JRC     MACRO    ?N        ; ; Jump relative on carry
  646.     DB    38H
  647.     @GENDD    ?N-$-1
  648.      ENDM
  649. ;
  650. JRNC     MACRO    ?N        ; ; Jump relative on no carry
  651.     DB    30H
  652.     @GENDD    ?N-$-1
  653.      ENDM
  654. ;
  655. JRZ     MACRO    ?N        ; ; Jump relative on zero
  656.     DB    28H
  657.     @GENDD    ?N-$-1
  658.      ENDM
  659. ;
  660. JRNZ     MACRO    ?N        ; ; Jump relative on no zero
  661.     DB    20H
  662.     @GENDD    ?N-$-1
  663.      ENDM
  664. ;
  665. DJNZ     MACRO    ?N        ; ; Decrement B and jump relative
  666.     DB    10H
  667.     @GENDD    ?N-$-1
  668.      ENDM
  669. ;
  670. LDIR     MACRO            ; ; LDIR
  671.     DB    0EDH,0B0H
  672.      ENDM
  673. ;
  674. LDED     MACRO    ?N        ; ; Load DE direct
  675.     DB    0EDH,5BH
  676.     DW    ?N
  677.      ENDM
  678. ;
  679. LBCD     MACRO    ?N        ; ; Load BC direct
  680.     DB    0EDH,4BH
  681.     DW    ?N
  682.      ENDM
  683. ;
  684. SDED     MACRO    ?N        ; ; Store DE direct
  685.     DB    0EDH,53H
  686.     DW    ?N
  687.      ENDM
  688. ;
  689. SBCD     MACRO    ?N        ; ; Store BC direct
  690.     DB    0EDH,43H
  691.     DW    ?N
  692.      ENDM
  693. ;
  694. ; end of Z80 macro extensions
  695. ;-----
  696. ;
  697. ; **** Section 0 ****
  698. ;
  699. ; Entry point into ZCMD2
  700. ;
  701. ; IF MULTCMD (MULTIPLE COMMANDS ON ONE LINE) is NO:  If ZCMD2 is entered
  702. ; at location CCPLOC (at the JMP to CCP), then the default command in
  703. ; CMDLIN will be processed.  If ZCMD2 is entered at location CCPLOC+3
  704. ; (at the JMP to CCP1), then the default command in CMDLIN will NOT be
  705. ; processed.  NOTE:  Entry into ZCMD2 at CCPLOC is permitted, but in
  706. ; order for this to work, CMDLIN MUST be initialized to contain the
  707. ; command line (ending in 0) and the C-register MUST contain a valid
  708. ; user/disk flag (the most significant nybble contains the user number
  709. ; and the least significant nybble contains the disk number.  Some user
  710. ; programs (such as SYNONYM3) attempt to use the default command fa-
  711. ; cility.  Under the original CCP, it was necessary to initialize the
  712. ; pointer after the reserved space for the command buffer to point to
  713. ; the first byte of the command buffer.  The NXTCHR (NeXT CHaRacter
  714. ; pointer) is located to be compatable with such programs (if they de-
  715. ; termine the buffer length from the byte at BUFSIZ [CCPLOC + 6]), but
  716. ; under ZCMD2 this is no longer necessary.  ZCMD2 automatically initial-
  717. ; izes this buffer pointer in all cases if MULTCMD is not enabled.
  718. ;
  719. ; IF MULTCMD is YES: Entry at CCP or CCP1 has the same effect.    Multiple
  720. ; command processing will still continue.  Hence, if MULTCMD is NO, a
  721. ; user program need only load the buffer CMDLIN with the desired command
  722. ; line, terminated by a zero, in order to have this command line exe-
  723. ; cuted.  If MULTCMD is YES, a user program must load this buffer as be-
  724. ; fore, but he must also set the NXTCHR pointer to point to the first
  725. ; character of the command line.  NOTE:  ***** (BIG STAR) ***** Programs
  726. ; such as SYNONYM3 will fail if multiple commands are enabled, but this
  727. ; feature is so very useful that it is worth the sacrifice.  The ZCMD2
  728. ; utilities of STARTUP and MENU require multiple commands, and this
  729. ; feature also permits simple chaining of programs to be possible under
  730. ; the ZCMD2 environment.
  731. ;
  732.      IF    NOT MAKESPR
  733.     ORG    CCPLOC
  734.      ENDIF
  735. ;
  736. ENTRY:     IF    NOT OZFLOP
  737.     JMP    CCP        ; Process potential default command
  738.      ENDIF
  739. ;
  740.      IF    OZFLOP
  741.     JMP    BOOTJMP        ; Used to properly set the Osborne CCP
  742.                 ; if using ZCMD from the floppy disk system
  743.                 ; tracks  the first two bytes must
  744.                 ; be C3H, 5CH
  745.      ENDIF
  746. ;
  747.     JMP    CCP1        ; Do not process potential default cmd
  748. ;
  749. ;-----
  750. ;
  751. ; **** Section 1 ****
  752. ;
  753. ; Buffers et al - input command line and default command
  754. ;
  755. ; The command line to be executed is stored here.  This command line is
  756. ; generated in one of 3 ways:
  757. ;
  758. ;    (1) by the user entering it through the BDOS READLN function at
  759. ;        the DU> prompt [user input from keyboard]
  760. ;    (2) by the SUBMIT File Facility placing it there from a $$$.SUB
  761. ;        file
  762. ;    (3) by an external program or user placing the required command
  763. ;        into this buffer
  764. ;
  765. ; In all cases, the command line is placed into the buffer starting at
  766. ; CMDLIN.  This command line is terminated by a binary zero.  ZCMD2 then
  767. ; parses, interprets, and executes the command line.  Case is not signi-
  768. ; ficant in the command line.  ZCMD2 converts all lower-case letters to
  769. ; upper-case.  If MULTCMD is YES, then the user must set a pointer to
  770. ; the first character of the command line into the buffer NXTCHR.  If
  771. ; MULTCMD is NO, no action other than placing a zero-terminated command
  772. ; line into the buffer starting at CMDLIN is required on the part of the
  773. ; user.  For multiple commands, the command line buffer (CMDLIN) is lo-
  774. ; cated external to ZCMD2 so that it is not overlayed during warm boots;
  775. ; the same is YES for NXTCHR, the 2nd key buffer.  BUFSIZ and CHRCNT are
  776. ; not important and are provided so the BDOS READLN function can load
  777. ; CMDLIN directly and a user program can see how much space is available
  778. ; in CMDLIN for its text.
  779. ;
  780.      IF    MULTCMD    AND EXCBUF
  781. NXTCHR    EQU    CLBASE        ; Nxtchr stored externally (2 bytes)
  782. BUFSIZ    EQU    NXTCHR+2    ; Bufsiz stored externally (1 byte)
  783. CHRCNT    EQU    BUFSIZ+1    ; Chrcnt stored externally (1 byte)
  784. CMDLIN    EQU    CHRCNT+1    ; Cmdlin stored externally (long)
  785.      ENDIF
  786. ;
  787. ; These buffers are left internal to ZCMD2 so that the original CCP
  788. ; command line facility (as used by programs like SYNONYM3) can be left
  789. ; intact.
  790. ;
  791. ; **** NOTE: Change the two lines marked with an asterisk (*) in the
  792. ;      comment field for command execution on cold boot (i.e. system
  793. ;      resets).
  794. ;
  795.      IF    NOT EXCBUF
  796. BUFLEN    EQU    80            ; Maximum buffer length
  797. BUFSIZ:    DB    BUFLEN            ; Maximum buffer length
  798. CHRCNT:    DB    0            ;*Number of valid chars in command line
  799. CMDLIN:    DB    '           '       ;*Default (cold boot) command
  800.     DB    0            ; Command string terminator
  801.     DS    BUFLEN-($-CMDLIN)+1 ; Total is 'BUFLEN' bytes
  802. NXTCHR:    DW    CMDLIN            ; Pointer to command input buffer
  803.      ENDIF
  804. ;
  805. ; File type for command
  806. ;
  807. COMMSG:    COMTYP            ; Use macro
  808. ;
  809. ; Submit file control block
  810. ;
  811.      IF    SUBON
  812. SUBFCB:    DB    1        ; Disk name set to default to drive A:
  813.     DB    '$$$'        ; File name
  814.     DB    '     '
  815.     SUBTYP            ; Use macro from ZCMDHDR.LIB
  816.     DB    0        ; Extent number
  817.     DB    0        ; S1
  818. SUBFS2:    DS    1        ; S2
  819. SUBFRC:    DS    1        ; Record count
  820.     DS    16        ; Disk group map
  821. SUBFCR:    DS    1        ; Current record number
  822.      ENDIF
  823. ;
  824. ; Command file control block
  825. ;
  826.      IF    EXTFCB
  827. FCBDN    EQU    FCBADR        ; Disk name
  828. FCBFN    EQU    FCBDN+1        ; File name
  829. FCBFT    EQU    FCBFN+8        ; File type
  830. FCBDM    EQU    FCBFT+7        ; Disk group map
  831. FCBCR    EQU    FCBDM+16    ; Current record number
  832.      ENDIF
  833. ;
  834.      IF    NOT EXTFCB
  835. FCBDN:    DS    1        ; Disk name
  836. FCBFN:    DS    8        ; File name
  837. FCBFT:    DS    3        ; File type
  838.     DS    1        ; Extent number
  839.     DS    2        ; S1 and S2
  840.     DS    1        ; Record count
  841. FCBDM:    DS    16        ; Disk group map
  842. FCBCR:    DS    1        ; Current record number
  843.      ENDIF
  844. ;
  845. ; Line count buffer
  846. ;
  847. PAGCNT:    DB    NLINES-2    ; Lines left on page
  848. ;
  849. ; CCP command name table - each table entry is composed of the four-byte
  850. ; command and two-byte address.
  851. ;
  852. CMDTBL:    CTABLE            ; Define command table via macro
  853. ;
  854. NCMNDS    EQU    ($-CMDTBL)/(NCHARS+2)
  855. ;
  856. ;-----
  857. ;
  858. ; **** Section 2 ****
  859. ;
  860. ; ZCMD2 starting points
  861. ;
  862. ; Now see if BYE is running
  863. ;
  864. CCP:    LXI    SP,STACK    ; Set the stack
  865.     PUSH    B
  866.     PUSH    D
  867.     MVI    A,CR
  868.     CALL    CONOUT        ; This is required to make BYE's BDCHEK
  869.     MVI    C,32        ; Reset locations 6 and 7 after warmboot
  870.     MVI    E,241
  871.     CALL    BDOS        ; Call BYE's BDOS
  872.     POP    D
  873.     POP    B
  874.     CPI    77        ; Running?
  875.     JRZ    CCP2        ; Yes, continue without setting defaults
  876. ;
  877.      IF    USRMAX
  878.     MVI    A,MAXUSR+1    ; Set USRMAX on cold boot
  879.     STA    USRMAX
  880.      ENDIF
  881. ;
  882.      IF    DRVMAX
  883.     MVI    A,MAXDISK-1    ; Set DRVMAX on cold boot
  884.     STA    DRVMAX
  885.      ENDIF
  886. ;
  887.      IF    USRMAX OR DRVMAX
  888.     MVI    A,0FFH
  889.     STA    WHLADR        ; Set WHEEL
  890.      ENDIF
  891. ;
  892.     JR    CCP2        ; On to coldboot routine
  893. ;
  894. ; Start ZCMD2 and don't process default command stored if multiple com-
  895. ; mands are not allowed.  This is the warmboot entry.
  896. ;
  897. CCP1:     IF    NOT MULTCMD
  898.     XRA    A        ; For no default command
  899.     STA    CMDLIN        ; First char of buffer
  900.      ENDIF
  901. ;
  902. ; Start ZCMD2 and possibly process default command
  903. ;
  904. ; NOTE: BDOS returns 0FFH in A-register whenever it logs in a directory,
  905. ; if any file name contains a '$' in it.  This is now used as a clue to
  906. ; determine whether or not to do a search for submit file, in order to
  907. ; eliminate wasteful searches.
  908. ;
  909. ; Process default command if present (this is the cold boot entry).
  910. ;
  911. CCP2:    LXI    SP,STACK    ; Reset stack
  912. ;
  913.      IF    NOT MULTCMD
  914.     LXI    H,CMDLIN    ; Set ptr to beginning of command line
  915.     SHLD    NXTCHR
  916.      ENDIF
  917. ;
  918.     PUSH    B
  919.     MOV    A,C        ; C=user/disk number (see loc 4)
  920.     RAR            ; Extract user number
  921.     RAR
  922.     RAR
  923.     RAR
  924.     ANI    0FH
  925.     STA    CURUSR        ; Set user
  926.     CALL    SETUSR
  927.     CALL    RESET        ; Reset disk system
  928. ;
  929.      IF    SUBON
  930.     STA    RNGSUB        ; Save submit clue from drive a:
  931.      ENDIF
  932. ;
  933.      IF    MAKESPR
  934. BIOS    EQU    0        ; So we don't get assembler errors <wm>
  935.     PUSH    H
  936.     LHLD    0000H+1        ; Get BIOS vector
  937.     LXI    B,3
  938.     DAD    B        ; Point to BIOS+6 (console status)
  939.     SHLD    BIOCAL2+1
  940.     DAD    B        ; Point to BIOS+9 (console input)
  941.     SHLD    BIOCAL1+1
  942.     SHLD    BIOCAL3+1
  943.     SHLD    BIOCAL4+1
  944.     POP    H        ; This was missing from v2.0  < wm >
  945.      ENDIF
  946. ;
  947.     POP    B
  948.     MOV    A,C        ; C=user/disk number (see loc 4)
  949.     ANI    0FH        ; Extract current disk drive
  950.     STA    CURDR        ; Set it
  951.     CALL    LOGIN        ; Log in default disk
  952.     CALL    SETUD        ; Set user/disk flag
  953.     CALL    DEFDMA        ; Set default dma address
  954. ;
  955.      IF    SUBON
  956.     LXI    D,SUBFCB    ; Check for $$$.sub on current disk
  957. ;
  958. RNGSUB    EQU    $+1        ; Pointer for in-the-code modification
  959.     MVI    A,0        ; 2nd byte (immediate arg)
  960.     ORA    A        ; Set flags on clue
  961.     CNZ    SEAR1
  962.     STA    RNGSUB        ; Set flag (0=no $$$.sub)
  963.      ENDIF
  964. ;
  965. ; Test for next command in continuous loop if multiple command line buf-
  966. ; fer is enabled.
  967. ;
  968.      IF    MULTCMD
  969. CONT:
  970.      ENDIF
  971. ;
  972.     LHLD    NXTCHR        ; Point to next character to process
  973.     MOV    A,M        ; Get it
  974.     CPI    3        ; Restart if CTL-C
  975.     JRZ    RESTRT
  976.     ORA    A        ; 0 if no command line present
  977.     JRNZ    RS1
  978. ;
  979. ; Test for any default command before continuous loop entered if mul-
  980. ; tiple command line buffer is disabled.
  981. ;
  982.      IF    NOT MULTCMD
  983. CONT:
  984.      ENDIF
  985. ;
  986. ; Ppompt user and input command line from him
  987. ;
  988. RESTRT:    LXI    SP,STACK    ; Reset stack
  989. ;
  990. ; The following code added to dynamically set INTPATH to extra search
  991. ; level if WHEEL is ON, and reset that level if Wheel is off.
  992. ;
  993.      IF    WHEEL AND INTPATH
  994.     LDA    WHLADR        ; Get wheel byte
  995.     ORA    A
  996.     MVI    A,0        ; Reset search path if off
  997.     JZ    $+5
  998.     MVI    A,SYSDRV    ; Set search drive if wheel on
  999.     STA    WHLPTH        ; Into the search path
  1000.      ENDIF
  1001. ;
  1002. ; Print prompt: DU>
  1003. ;
  1004.     CALL    CRLF        ; Print prompt
  1005. ;
  1006.      IF    PRIVDIR        ; If private directories
  1007.     LDA    WHLADR        ; Don't print drive/user prompt
  1008.     ORA    A        ; If wheel not enabled
  1009.     JRZ    RS000
  1010.      ENDIF
  1011. ;
  1012.      IF    (BYCLOCK OR BYTLOS) AND (NOT CLOCK)
  1013.     MVI    C,32
  1014.     MVI    E,241
  1015.     CALL    BDOS
  1016.     CPI    77        ; Is NUBYE/BYE5 running?
  1017.     CZ    TIME        ; Yes, display time prompts
  1018.      ENDIF
  1019. ;
  1020.      IF    CLOCK AND (NOT BYCLOCK) AND (NOT BYTLOS)
  1021.     CKCLOK            ; Predefined macro for clock check 
  1022.      ENDIF
  1023. ;
  1024.      IF    BYCLOCK OR BYTLOS OR CLOCK
  1025.     LDA    CURUSR
  1026.     CALL    SETUSR        ; Fixes the submit function
  1027.      ENDIF
  1028. ;
  1029.     LDA    CURDR        ; Current drive is part of prompt
  1030.     ADI    'A'        ; Convert to ASCII A-P
  1031.     CALL    CONOUT
  1032.     LDA    CURUSR        ; Get user number
  1033. ;
  1034.      IF    SUPRES
  1035.     ORA    A
  1036.     JRZ    RS000
  1037.      ENDIF
  1038. ;
  1039.     CPI    10        ; User < 10?
  1040.     JRC    RS00
  1041.     SUI    10        ; Subtract 10 from it
  1042.     PUSH    PSW        ; Save it
  1043.     MVI    A,'1'        ; Output 10's digit
  1044.     CALL    CONOUT
  1045.     POP    PSW
  1046. ;
  1047. RS00:    ADI    '0'        ; Output 1's digit (convert to ASCII)
  1048.     CALL    CONOUT
  1049. ;
  1050. ; Read input line from user or $$$.SUB
  1051. ;
  1052. RS000:    LXI    H,CMDLIN    ; Set pointer to first character
  1053.     SHLD    NXTCHR        ; Pointer to next character to process
  1054.     MVI    M,0        ; Zero out command line
  1055.     PUSH    H        ; Save pointer
  1056.     CALL    REDBUF        ; Input command line from user
  1057.     POP    H        ; Get pointer
  1058.     MOV    A,M        ; Check for comment line
  1059.     CPI    COMMENT        ; Begins with comment character?
  1060.     JRZ    RESTRT        ; Input another line if so
  1061.     ORA    A        ; No input?
  1062.     JRZ    RESTRT
  1063. ;
  1064. ; Process input line - HL points to first letter of command
  1065. ;
  1066. RS1:    LXI    SP,STACK    ; Reset stack
  1067. ;
  1068.      IF    MULTCMD
  1069.     MOV    A,M        ; Get first char of command
  1070.     CPI    CMDSEP        ; Is it a command separator?
  1071.     JRNZ    RS2
  1072.     INX    H        ; Skip it if it is
  1073.     SHLD    NXTCHR        ; Set pointer back
  1074.      ENDIF
  1075. ;
  1076. ; Set pointer fro multiple command line processing to first character of
  1077. ; new command
  1078. ;
  1079. RS2:    SHLD    CMDCH1        ; Set pointer to first character
  1080. ;
  1081. ; Capitalize command line
  1082. ;
  1083. CAPBUF:    MOV    A,M        ; Capitalize command character
  1084.     CALL    UCASE
  1085.     MOV    M,A
  1086.     INX    H        ; Point to next character
  1087.     ORA    A        ; Eol?
  1088.     JRNZ    CAPBUF
  1089.     CALL    SCANER        ; Parse command name from command line
  1090.     JRNZ    ERROR        ; Error if command name contains a '?'
  1091.     LXI    D,RSTCCP    ; Put return address of command
  1092.     PUSH    D        ; On the stack
  1093. ;
  1094. COLON    EQU    $+1        ; Flag for in-the-code modification
  1095.     MVI    A,0        ; Command of the form 'DU:command'?
  1096.     ORA    A        ; 0=no
  1097.     JNZ    COM        ; Process as com file if not
  1098.     CALL    CMDSER        ; Scan for cpr-resident command
  1099.     JNZ    COM        ; Not cpr-resident
  1100.     MOV    A,M        ; Found it:  get low-order part
  1101.     INX    H        ; Get high-order part
  1102.     MOV    H,M        ; Store high
  1103.     MOV    L,A        ; Store low
  1104.     PCHL            ; Execute cpr routine
  1105. ;
  1106. ; Entry point for restarting CCP and logging in default drive
  1107. ;
  1108. RSTCCP:    CALL    DLOGIN        ; Log in current user/disk
  1109. ;
  1110. ; Entry point for restarting CCP without logging in default drive
  1111. ;
  1112. RCCPNL:    CALL    SCANER        ; Extract next token from command line
  1113.     LDA    FCBFN        ; Get first char of token
  1114.     CPI    ' '        ; Any char?
  1115.     JZ    CONT        ; Continue with next command if no error
  1116. ;
  1117. ; Invalie command - print it
  1118. ;
  1119. ERROR:    CALL    CRLF        ; New line
  1120. ;
  1121. CURTOK    EQU    $+1        ; Pointer for in-the-code modification
  1122.     LXI    H,0        ; Pt to beginning of command line
  1123. ;
  1124. ERR1:    MOV    A,M        ; Get character
  1125.     CPI    ' '+1        ; Simple '?' if <sp> or less
  1126.     JRC    ERR2
  1127.     CALL    CONOUT        ; Print command char
  1128.     INX    H        ; Pt to next char
  1129.     JR    ERR1        ; Continue
  1130. ;
  1131. ERR2:    CALL    PRINT        ; Show input error
  1132.     DB    ' <-- Erro','r'+80H
  1133. ;
  1134. ERR3:    CALL    DLOGIN        ; Panic restore of default user/disk
  1135. ;
  1136.      IF    SUBON
  1137.     CALL    SUBKIL        ; Terminate active $$$.SUB if any
  1138.      ENDIF
  1139. ;
  1140.     JMP    RESTRT        ; Restart CCP
  1141. ;
  1142. ; No File Error Message
  1143. ;
  1144. PRNNF:    CALL    PRINTC        ; No file message
  1145.     DB    'No Fil','e'+80H
  1146.     RET
  1147. ;
  1148. ;-----
  1149. ;
  1150. ; * Section 3 ****
  1151. ;
  1152. ; I/O utilities
  1153. ;
  1154. ; Output character in A-register to CRT and don't change 'BC'
  1155. ; Output <CRLF>
  1156. ;
  1157. CRLF:    MVI    A,CR
  1158.     CALL    CONOUT
  1159.     MVI    A,LF
  1160.     JR    CONOUT
  1161. ;
  1162. CONIN:    MVI    C,1        ; Input character
  1163.     CALL    BDOS        ; Get input character with ^S
  1164.     JMP    UCASE        ; Capitalize
  1165. ;
  1166. CONOUT:    PUSH    B
  1167.     PUSH    D
  1168.     PUSH    H
  1169.     MVI    C,2
  1170. ;
  1171.      IF    HBLST AND (NOT HBCON)
  1172.     ANI    7FH        ; Wipe out Hi bit for CON, not LST
  1173.      ENDIF
  1174. ;
  1175. OUTPUT:     IF    NOT (HBCON AND HBLST)
  1176.     ANI    7FH        ; Wipe out Hi bit for CON and LST
  1177.      ENDIF
  1178. ;
  1179.     MOV    E,A
  1180.     CALL    BDOS
  1181.     POP    H
  1182.     POP    D
  1183.     POP    B
  1184.     RET
  1185. ;
  1186. LCOUT:    PUSH    PSW        ; Output character to CRT
  1187. ;
  1188. PRFLG    EQU    $+1        ; Pointer for in-the-code modification
  1189.     MVI    A,0        ; 2nd byte (immediate argument)
  1190.     ORA    A        ; 0=type
  1191.     JRZ    LC1
  1192.     POP    PSW        ; Get character
  1193. ;
  1194. ; Output character in A-register to list device
  1195. ;
  1196. LSTOUT:    PUSH    B        ; Save regs
  1197.     PUSH    D
  1198.     PUSH    H
  1199.     MVI    C,5
  1200. ;
  1201.      IF    HBCON AND (NOT HBLST)
  1202.     ANI    7FH        ; Wipe out Hi bit for LST but not CON
  1203.      ENDIF
  1204. ;
  1205.     JR    OUTPUT
  1206. ;
  1207. LC1:    POP    PSW        ; Get character
  1208.     PUSH    PSW
  1209.     CALL    CONOUT        ; Output to CRT
  1210.     POP    PSW
  1211.     CPI    LF        ; Check for paging
  1212.     RNZ
  1213. ;
  1214. ; Paging routines - PAGER counts down lines and pauses for direct input
  1215. ; if count expires, PAGSET sets lines per page count.
  1216. ;
  1217. PAGER:    PUSH    H
  1218.     LXI    H,PAGCNT    ; Count down
  1219.     DCR    M
  1220.     JRNZ    PAGER1        ; Jump if not end of page
  1221.     MVI    M,NLINES-2    ; Refill counter
  1222. ;
  1223. PGFLG    EQU    $+1        ; Pointer to in-the-code buffer pgflg
  1224.     MVI    A,0        ; 0 may be changed by pgflg equate
  1225.     CPI    PGDFLG        ; Page default override option wanted?
  1226. ;
  1227.      IF    PGDFLT
  1228.     JRZ    PAGER1        ; PGDFLG means no paging, please
  1229.      ENDIF
  1230. ;
  1231.      IF    NOT PGDFLT
  1232.     JRNZ    PAGER1        ; Pgdflg means please paginate
  1233.      ENDIF
  1234. ;
  1235.     PUSH    B        ; Save registers
  1236. ;
  1237. BIOCAL1:CALL    BIOS+9        ; BIOS console input routine
  1238.     POP    B        ; Get register
  1239.     CPI    'C'-'@'        ; ^C
  1240.     JZ    RSTCCP        ; Restart CCP
  1241. ;
  1242. PAGER1:    POP    H        ; Restore HL
  1243.     RET
  1244. ;
  1245. ; Read file block function
  1246. ;
  1247. READF:    LXI    D,FCBDN        ; Fall through to read
  1248. ;
  1249. READ:    MVI    C,14H        ; Fall through to BDOSB
  1250. ;
  1251. ; Call BDOS and save 'BC'
  1252. ;
  1253. BDOSB:    PUSH    B
  1254.     CALL    BDOS
  1255.     POP    B
  1256.     ORA    A
  1257.     RET
  1258. ;
  1259. ; Print string (ending in character with MSB set) pointed to by return
  1260. ; address - start with <CRLF>
  1261. ;
  1262. PRINTC:    CALL    CRLF        ; New line
  1263. ;
  1264. PRINT:    XTHL            ; Get ptointer to string
  1265.     CALL    PRIN1        ; Print string
  1266.     XTHL            ; Restore HL and return address
  1267.     RET
  1268. ;
  1269. ; Print string (ending in 0 or byte with MSB set) pointed to by 'HL'
  1270. ;
  1271. PRIN1:    MOV    A,M        ; Get next byte
  1272.     INX    H        ; Point to next byte
  1273.     ORA    A        ; End of string?
  1274.     RZ            ; String terminated by binary 0
  1275.     PUSH    PSW        ; Save flags
  1276.     ANI    7FH        ; Mask out MSG
  1277.     CALL    CONOUT        ; Print character
  1278.     POP    PSW        ; Get flags
  1279.     RM            ; String terminated by MSB set
  1280.     JR    PRIN1
  1281. ;
  1282. ; BDOS function routines
  1283. ;
  1284. ; Return number of current disk in 'A'
  1285. ;
  1286. GETDRV:    MVI    C,19H
  1287.     JR    BDOSJP
  1288. ;
  1289. ; Set 80H as DMA address
  1290. ;
  1291. DEFDMA:    LXI    D,TBUFF        ; 80H=TBUFF
  1292. ;
  1293. DMASET:    MVI    C,1AH
  1294.     JR    BDOSJP
  1295. ;
  1296. RESET:    MVI    C,0DH
  1297. ;
  1298. BDOSJP:    JMP    BDOS
  1299. ;
  1300. LOGIN:    MOV    E,A
  1301.     MVI    C,0EH
  1302.     JR    BDOSJP        ; Save some code space
  1303. ;
  1304. OPENF:    XRA    A
  1305.     STA    FCBCR
  1306.     LXI    D,FCBDN        ; Fall thrrough to OPEN
  1307. ;
  1308. OPEN:    MVI    C,0FH        ; Fall through to GRBDOS
  1309. ;
  1310. GRBDOS:    CALL    BDOS
  1311.     INR    A        ; Set zero flag for error return
  1312.     RET
  1313. ;
  1314. CLOSE:    MVI    C,10H
  1315.     JR    GRBDOS
  1316. ;
  1317. SEARF:    LXI    D,FCBDN        ; Specify FCB
  1318. ;
  1319. SEAR1:    MVI    C,11H
  1320.     JR    GRBDOS
  1321. ;
  1322. SEARN:    MVI    C,12H
  1323.     JR    GRBDOS
  1324. ;
  1325. ; Check for submit file in execution and abort if so
  1326. ;
  1327.      IF    SUBON
  1328. SUBKIL:    LXI    H,RNGSUB    ; Check for submit file in execution
  1329.     MOV    A,M
  1330.     ORA    A        ; 0=no
  1331.     RZ
  1332.     MVI    M,0        ; Abort submit file
  1333.     LXI    D,SUBFCB    ; Delete $$$.SUB
  1334.      ENDIF
  1335. ;
  1336. DELETE:    MVI    C,13H
  1337.     JR    BDOSJP        ; Save more space
  1338. ;
  1339. ; Get/set user number
  1340. ;
  1341. GETUSR:    MVI    A,0FFH        ; Get current user number
  1342. ;
  1343. SETUSR:    MOV    E,A        ; User number in 'E'
  1344.     MVI    C,20H        ; Set user number to value in 'E'
  1345.     JR    BDOSJP        ; More space saving
  1346. ;
  1347. ; end of BDOS Functions
  1348. ;-----
  1349. ;
  1350. ; * Section 4 ****
  1351. ;
  1352. ; ZCMD2 utilities
  1353. ;
  1354. ; Set user/disk flag to current user and default disk
  1355. ;
  1356. SETUD:    CALL    GETUSR        ; Get number of current user
  1357.     ANI    0FH        ; Mask sure 4 bits
  1358.     ADD    A        ; Place it in high nybble
  1359.     ADD    A
  1360.     ADD    A
  1361.     ADD    A
  1362.     LXI    H,CURDR        ; Mask in current drive number
  1363.     ORA    M        ; Mask in
  1364.     STA    UDFLAG        ; Set user/disk number
  1365.     RET
  1366. ;
  1367. ; Convert character in 'A' to upper-case
  1368. ;
  1369. UCASE:    ANI    7FH        ; Mask out MSB
  1370.     CPI    61H        ; Lower-case 'A'
  1371.     RC
  1372.     CPI    7BH        ; Greater than lower-case Z?
  1373.     RNC
  1374.     ANI    5FH        ; Capitalize
  1375.     RET
  1376. ;
  1377. ; Input next command to CCP - This routine determines if a SUBMIT file
  1378. ; is being processed and extracts the command line from it if so or from
  1379. ;  the user's console
  1380. ;
  1381. REDBUF:     IF    SUBON
  1382.     LDA    RNGSUB        ; Submit file currently in execution?
  1383.     ORA    A        ; 0=no
  1384.     JRZ    RB1        ; Get line from console if not
  1385.     LXI    D,SUBFCB    ; Open $$$.SUB
  1386.     PUSH    D        ; Save DE
  1387.     CALL    OPEN
  1388.     POP    D        ; Restore DE
  1389.     JRZ    RB1        ; Erase $$$.SUB if end of file
  1390.     LDA    SUBFRC        ; Get value of last record in file
  1391.     DCR    A        ; Pt to next to last record
  1392.     STA    SUBFCR        ; New value of last record in $$$.SUB
  1393.     CALL    READ        ; DE=SUBFCB
  1394.     JRNZ    RB1        ; Abort $$$.SUB if error
  1395.     LXI    D,CHRCNT    ; Copy last record (next submit cmnd)
  1396.     LXI    H,TBUFF        ; From TBUFF
  1397.     LXI    B,BUFLEN    ; Number of bytes
  1398.     LDIR
  1399.     LXI    H,SUBFS2    ; Point to S2 of $$$.SUB FCB
  1400.     MVI    M,0        ; Set S2 to zero
  1401.     INX    H        ; Point to record count
  1402.     DCR    M        ; Decrement record count of $$$.SUB
  1403.     LXI    D,SUBFCB    ; Close $$$.SUB
  1404.     CALL    CLOSE
  1405.     JRZ    RB1        ; Abort $$$.SUB if error
  1406.     MVI    A,SPRMPT    ; Print submit prompt
  1407.     CALL    CONOUT
  1408.     LXI    H,CMDLIN    ; Print command line from $$$.SUB
  1409.     CALL    PRIN1
  1410.     CALL    BREAK        ; Check for abort (any char)
  1411.     RNZ            ; If no ^C, return to caller and run
  1412.     CALL    SUBKIL        ; Kill $$$.SUB if abort
  1413.     JMP    RESTRT        ; Restart CCP
  1414. ;
  1415. ; Input command line from user console
  1416. ;
  1417. RB1:    CALL    SUBKIL        ; Erase $$$.sub if present
  1418.      ENDIF
  1419. ;
  1420.     MVI    A,':'
  1421.     CALL    CONOUT
  1422. ;
  1423.      IF    WHEEL
  1424.     LDA    WHLADR
  1425.     ORA    A        ; WHEEL on?
  1426.      ENDIF
  1427. ;
  1428.     MVI    A,NPROMPT    ; Normal prompt
  1429. ;
  1430.      IF    WHEEL
  1431.     JRZ    RB2        ; No, show normal prompt
  1432.     MVI    A,WPROMPT    ; ...else, show WHEEL prompt
  1433.      ENDIF
  1434. ;
  1435. RB2:    CALL    CONOUT
  1436.     MVI    C,0AH        ; Read command line from user
  1437.     LXI    D,BUFSIZ
  1438.     CALL    BDOS
  1439. ;
  1440. ; Store zero at end of command line
  1441. ;
  1442.     LXI    H,CHRCNT    ; Point to character count
  1443.     MOV    A,M        ; Get character count
  1444.     INX    H        ; Pt to first character of command line
  1445.     CALL    ADDAH        ; Pt to after last char of command line
  1446.     MVI    M,0        ; Store ending zero
  1447.     RET
  1448. ;
  1449. ; Check for any character from user console, return with zero set if
  1450. ; none.
  1451. ;
  1452. BREAK:    PUSH    B        ; Save registers
  1453.     PUSH    D
  1454.     PUSH    H
  1455. ;
  1456. BIOCAL2:CALL    BIOS+6        ; Console status check
  1457.     ORA    A        ; Set flags
  1458. ;
  1459. BIOCAL3:CNZ    BIOS+9        ; Get input char with ^s processing
  1460.     CPI    'S'-'@'        ; Pause if ^S
  1461. ;
  1462. BIOCAL4:CZ    BIOS+9        ; Get next character
  1463.     POP    H        ; Restore registers
  1464.     POP    D
  1465.     POP    B
  1466.     CPI    'C'-'@'        ; Check for abort
  1467.     RET
  1468. ;
  1469. ; Check to see if DE points to delimiter, if so return with zero flag
  1470. ; set.
  1471. ;
  1472. SDELM:    LDAX    D
  1473.     ORA    A        ; 0=delimiter
  1474.     RZ
  1475.     CPI    ' '+1        ; Delim if <= <SP>
  1476.     JRC    ZERO
  1477.     CPI    '='        ; '='=delimiter
  1478.     RZ
  1479.     CPI    5FH        ; Underscore=delimiter
  1480.     RZ
  1481.     CPI    '.'        ; '.'=delimiter
  1482.     RZ
  1483.     CPI    ':'        ; ':'=delimiter
  1484.     RZ
  1485.     CPI    ','        ; ','=delimiter
  1486.     RZ
  1487.     CPI    ';'        ; ';'=delimiter
  1488.     RZ
  1489.     CPI    '<'        ; '<'=delimiter
  1490.     RZ
  1491.     CPI    '>'        ; '>'=delimiter
  1492. ;
  1493.      IF    MULTCMD
  1494.     RZ
  1495.     CPI    CMDSEP        ; Command separator
  1496.      ENDIF
  1497. ;
  1498.     RET
  1499. ;
  1500. ZERO:    XRA    A        ; Set zero flag
  1501.     RET
  1502. ;
  1503. ; Advance input pointer to first non-blank and fall through to SBLANK
  1504. ;
  1505. ADVAN:    LDED    NXTCHR        ; Point to next character
  1506. ;
  1507. ; Skip string pointed to by DE (string ends in 0 OR CMDSEP) until end of
  1508. ; string or non-delimited encounterd (beginning of token).
  1509. ;
  1510. SBLANK:    LDAX    D        ; Get character
  1511.     ORA    A        ; Zero?
  1512.     RZ
  1513. ;
  1514.      IF    MULTCMD
  1515.     CPI    CMDSEP        ; Command separator?
  1516.     RZ
  1517.      ENDIF
  1518. ;
  1519.     CALL    SDELM        ; Skip over delimiter
  1520.     RNZ
  1521.     INX    D        ; Advance to next char
  1522.     JR    SBLANK
  1523. ;
  1524. ; Add A ro HL (HL=HL+A)
  1525. ;
  1526. ADDAH:    ADD    L
  1527.     MOV    L,A
  1528.     RNC
  1529.     INR    H
  1530.     RET
  1531. ;
  1532. ; Extract decimal number from command line - return with value in A-reg.
  1533. ; All registers may be affected.
  1534. ;
  1535. NUMBER:    CALL    SCANER        ; Parse number and place in fcbfn
  1536.     LXI    H,FCBFN+10    ; Pt to end of token for conversion
  1537.     MVI    B,11        ; 11 characters maximum
  1538. ;
  1539. ; Check for suffix for hexadecimal number
  1540. ;
  1541. NUMS:    MOV    A,M        ; Get character from end
  1542.     DCX    H        ; Back up
  1543.     CPI    ' '        ; Space?
  1544.     JRNZ    NUMS1        ; Check for suffix
  1545.     DJNZ    NUMS        ; Count down
  1546.     JR    NUM0        ; By default, process
  1547. ;
  1548. NUMS1:    CPI    NUMBASE        ; Check against base switch flag
  1549.     JRZ    HNUM0
  1550. ;
  1551. ; Process decimal number
  1552. ;
  1553. NUM0:    LXI    H,FCBFN        ; Point to beginning of token
  1554. ;
  1555. NUM0A:    LXI    B,1100H        ; C=accumulated value, b=char count
  1556. ;                ; (c=0, b=11)
  1557. NUM1:    MOV    A,M        ; Get character
  1558.     CPI    ' '        ; Done if <SP>
  1559.     JRZ    NUM2
  1560.     CPI    ':'        ; Done if colon
  1561.     JRZ    NUM2
  1562.     INX    H        ; Pt to next char
  1563.     SUI    '0'        ; Convert to binary
  1564.     CPI    10        ; Error if >= 10
  1565.     JRNC    NUMERR
  1566.     MOV    D,A        ; Digit in d
  1567.     MOV    A,C        ; New value = old value * 10
  1568.     RLC            ; *2
  1569.     JRC    NUMERR
  1570.     RLC            ; *4
  1571.     JRC    NUMERR
  1572.     RLC            ; *8
  1573.     JRC    NUMERR
  1574.     ADD    C        ; *9
  1575.     JRC    NUMERR
  1576.     ADD    C        ; *10
  1577.     JRC    NUMERR
  1578.     ADD    D        ; New value = old value * 10 + digit
  1579.     JRC    NUMERR        ; Check for range error
  1580.     MOV    C,A        ; Set new value
  1581.     DJNZ    NUM1        ; Count down
  1582. ;
  1583. ; Return from number
  1584. ;
  1585. NUM2:    MOV    A,C        ; Get accumulated value
  1586.     RET
  1587. ;
  1588. ; Number error routine for space conservation
  1589. ;
  1590. NUMERR:    JMP    ERROR        ; Use error routine
  1591. ;
  1592. ; Extract hexadecimal number from command line - return with value in
  1593. ; A-reg, all registers may be affected.
  1594. ;
  1595. HEXNUM:    CALL    SCANER        ; Parse number and place in FCBFN
  1596. ;
  1597. HNUM0:    LXI    H,FCBFN        ; Point to token for conversion
  1598.     LXI    D,0        ; De=accumulated value
  1599.     MVI    B,11        ; B=character
  1600. ;
  1601. HNUM1:    MOV    A,M        ; Get character
  1602.     CPI    ' '        ; Done?
  1603.     JRZ    HNUM3        ; Return if so
  1604.     CPI    NUMBASE        ; Done if numbase suffix
  1605.     JRZ    HNUM3
  1606.     SUI    '0'        ; Convert to binary
  1607.     JRC    NUMERR        ; Return and done if error
  1608.     CPI    10        ; 0-9?
  1609.     JRC    HNUM2
  1610.     SUI    7        ; A-F?
  1611.     CPI    10H        ; Error?
  1612.     JRNC    NUMERR
  1613. ;
  1614. HNUM2:    INX    H        ; Point to next characer
  1615.     MOV    C,A        ; Digit in 'C'
  1616.     MOV    A,D        ; Get accumulated value
  1617.     RLC            ; Exchange nybbles
  1618.     RLC
  1619.     RLC
  1620.     RLC
  1621.     ANI    0F0H        ; Mask out low nybble
  1622.     MOV    D,A
  1623.     MOV    A,E        ; Switch low-order nybbles
  1624.     RLC
  1625.     RLC
  1626.     RLC
  1627.     RLC
  1628.     MOV    E,A        ; High nybble of e=new high of e
  1629.     ANI    0FH        ; Get new low of d
  1630.     ORA    D        ; Mask in high of d
  1631.     MOV    D,A        ; New high byte in d
  1632.     MOV    A,E
  1633.     ANI    0F0H        ; Mask out low of e
  1634.     ORA    C        ; Mask in new low
  1635.     MOV    E,A        ; New low byte in e
  1636.     DJNZ    HNUM1        ; Count down
  1637. ;
  1638. ; Return from HEXNUM
  1639. ;
  1640. HNUM3:    XCHG            ; Returned value in hl
  1641.     MOV    A,L        ; Low-order byte in a
  1642.     RET
  1643. ;
  1644. ; point to directory entry in TBUFF whose offset is specified by A and C
  1645. ;
  1646. DIRPTR:    LXI    H,TBUFF        ; Point to temporary buffer
  1647.     ADD    C        ; Point to 1st byte of directory entry
  1648.     CALL    ADDAH        ; Point to desired byte in dir entry
  1649.     MOV    A,M        ; Get desired byte
  1650.     RET
  1651. ;
  1652. ; Check for specified drive and log it in
  1653. ;
  1654. SLOGIN:    XRA    A        ; A=0 for default disk
  1655.     STA    FCBDN        ; Select default disk since user/disk
  1656. ;
  1657. TEMPDR    EQU    $+1        ; Pointer for in-the-code modification
  1658.     MVI    A,0        ; 2nd byte (immediate arg) is tempdr
  1659.     ORA    A        ; 0=current drive
  1660.     JRNZ    SLOG1
  1661.     LDA    CURDR        ; Log in current drive
  1662.     INR    A        ; Add 1 for next dcr
  1663. ;
  1664. SLOG1:    DCR    A        ; Adjust for proper disk number (a=0)
  1665.     CALL    LOGIN        ; Log in new drive
  1666. ;
  1667. TEMPUSR    EQU    $+1        ; Pointer for in-the-code modification
  1668.     MVI    A,0        ; 2nd byte is user to be selected
  1669.     JMP    SETUSR        ; Log in new user
  1670. ;
  1671. ; Check for specified drive and log in default drive
  1672. ;
  1673. DLOGIN:    DS    0
  1674. ;
  1675. CURDR    EQU    $+1        ; Pointer for in-the-code modification
  1676.     MVI    A,0        ; Prep to log in current drive
  1677.     CALL    LOGIN        ; Login current drive
  1678. ;
  1679. CURUSR    EQU    $+1        ; Pointer for in-the-code modification
  1680.     MVI    A,0        ; Prep to log in current user number
  1681.     JMP    SETUSR        ; Log in new user
  1682. ;
  1683. ; Routine to check for a wheel byte as non-zero, if wheel byte is zero,
  1684. ; then abort (pop stack and return).
  1685. ;
  1686.      IF    WHEEL
  1687. WHLCHK:    LDA    WHLADR        ; Get wheel byte
  1688.     ORA    A        ; Zero?
  1689.     RNZ            ; Ok if not
  1690.     JMP    ERROR        ; Process as error
  1691.      ENDIF
  1692. ;
  1693. ; Extract token from command line and place it into FCBDN, format FCBDN
  1694. ; FCB if token resembles file name and type (filename.typ).  On input,
  1695. ; MXTCHR points to character at which to start scan.  On output, NXTCHR
  1696. ; points to character at which to continue and zero flag is reset if
  1697. ; if '?' is in token
  1698. ;
  1699. ; Entry points:
  1700. ;    SCANLOG - load token into first FCB and log in temp user/disk
  1701. ;    SCANER    - load token into first FCB
  1702. ;    SCANX    - load token into FCB pointed to by 'HL'
  1703. ;
  1704. SCANLOG:CALL    SCANER        ; Do scan
  1705.     PUSH    PSW        ; Save flag
  1706.     CALL    SLOGIN        ; Log in temporary user/disk
  1707.     POP    PSW        ; Get flag
  1708.     RET
  1709. ;
  1710. SCANER:    LXI    H,FCBDN        ; Point to FCBDN
  1711. ;
  1712. SCANX:    XRA    A        ; A=0
  1713.     STA    TEMPDR        ; Set temporary drive number to default
  1714.     MOV    M,A        ; Set first byte of FCBDN
  1715.     STA    COLON        ; Set no colon flag
  1716.     LDA    CURUSR        ; Get current user
  1717.     STA    TEMPUSR        ; Set tempusr
  1718.     CALL    ADVAN        ; Skip to non-blank or end of line
  1719.     SDED    CURTOK        ; Set ptr to non-blank or end of line
  1720.     MVI    B,11        ; Prep for possible space fill
  1721.     JRZ    SCAN4        ; Done if eol
  1722. ;
  1723. ; Scan token for DU: form, which means we have a user/disk specification
  1724. ; DE points to next character in line, HL points ro FCBDN.
  1725. ;
  1726.     PUSH    D        ; Save pointer to first character
  1727.     CALL    SDELM        ; Check for delimiter and get first char
  1728.     CPI    'A'        ; In letter range?
  1729.     JRC    SCAN1
  1730.     CPI    'P'+1        ; In letter range?
  1731.     JRC    SCAN1A
  1732. ;
  1733. SCAN1:    CPI    '0'        ; Check for digit range
  1734.     JRC    SCAN2
  1735.     CPI    '9'+1        ; In digit range?
  1736.     JRNC    SCAN2
  1737. ;
  1738. SCAN1A:    INX    D        ; Pt to next char
  1739.     CALL    SDELM        ; Check for delimiter, else digit
  1740.     JR    SCAN1
  1741. ;
  1742. SCAN2:    POP    D        ; Restore ptr to first char
  1743.     CPI    ':'        ; Was delimiter a colon?
  1744.     JRNZ    SCAN3        ; Done if no colon
  1745.     STA    COLON        ; Set colon found
  1746. ;
  1747.      IF    PRIVDIR
  1748.     CALL    WHLCHK        ; Mod by PST to not allow ':' in FCB
  1749.      ENDIF
  1750. ;
  1751. ; Scan for and extract user/disk info - on entry, HL point to FCBDN, DE
  1752. ; points to first character and A-register contains the first character.
  1753. ;
  1754.     LDAX    D        ; Get first character
  1755.     CPI    'A'        ; Convert possible drive spec to number
  1756.     JRC    SUD1        ; If less than 'a', must be digit
  1757. ;
  1758. ; Set disk number (A=1)
  1759. ;
  1760.     SUI    'A'-1
  1761. ;
  1762.      IF    DRVMAX
  1763.     PUSH    B        ; Save 'BC'
  1764.     PUSH    PSW        ; Save drive request
  1765.     LDA    DRVMAX        ; Get maximum legal drive
  1766.     ADI    2        ; Bump it two for the compare
  1767.     MOV    B,A        ; Save maximum drive in 'B'
  1768.     POP    PSW        ; Restore drive request
  1769.     CMP    B        ; See if illegal drive
  1770.     POP    B        ; Restore bc
  1771.      ENDIF
  1772. ;
  1773.      IF    NOT DRVMAX
  1774.     CPI    MAXDISK+1    ; Within range?
  1775.      ENDIF
  1776. ;
  1777.     JNC    ERROR        ; Invalid disk number
  1778.     STA    TEMPDR        ; Set temporary drive number
  1779.     MOV    M,A        ; Set fcbdn
  1780.     INX    D        ; Pt to next char
  1781.     LDAX    D        ; See if it is a colon (:)
  1782.     CPI    ':'
  1783.     JRZ    SUD2        ; Done if no user number (it is a colon)
  1784. ;
  1785. ; Set user number
  1786. ;
  1787. SUD1:    PUSH    H        ; Save pointer to FCBDN
  1788.     XCHG            ; Hl pts to first digit
  1789.     CALL    NUM0A        ; Get number
  1790.     XCHG            ; De pts to terminating colon
  1791. ;
  1792.      IF    USRMAX
  1793.     LXI    H,USRMAX
  1794.     CMP    M
  1795.      ENDIF
  1796. ;
  1797.      IF    NOT USRMAX
  1798.     CPI    MAXUSR+1    ; Within limit?
  1799.      ENDIF
  1800. ;
  1801.     POP    H        ; Get pointer to FCBDN
  1802.     JNC    ERROR
  1803. ;
  1804.      IF    USERON
  1805.     STA    TEMPUSR        ; Save user number
  1806.      ENDIF
  1807. ;
  1808. SUD2:    INX    D        ; Point to character after colon
  1809. ;
  1810. ; Extract filename from possible FILENAME.TYP - DE points to next char-
  1811. ; acter to process, HL points tao FCBDN.
  1812. ;
  1813. SCAN3:    XRA    A        ; A=0
  1814.     STA    QMCNT        ; Init question mark count
  1815.     MVI    B,8        ; Max of 8 chars in file name
  1816.     CALL    SCANF        ; Fill FCB file name
  1817. ;
  1818. ; Extract file type from possible FILENAME.TYP
  1819. ;
  1820.     MVI    B,3        ; Prepare to extract type
  1821.     LDAX    D        ; Get last char which stopped scan
  1822.     CPI    '.'        ; Have a type if de) delimiter is a '.'
  1823.     JRNZ    SCAN4        ; Fill file type bytes with <sp>
  1824.     INX    D        ; Pt to char in command line after '.'
  1825.     CALL    SCANF        ; Fill fcb file type
  1826.     JR    SCAN5        ; Skip to next processing
  1827. ;
  1828. SCAN4:    CALL    SCANF4        ; Space fill
  1829. ;
  1830. ; Fill in EX, S1, S2, and RC with zeroes
  1831. ;
  1832. SCAN5:    MVI    B,4        ; 4 bytes
  1833.     XRA    A        ; A=0
  1834.     CALL    SCANF5        ; Fill with zeroes
  1835. ;
  1836. ; Scan complete -- DE points to delimiter byte after token
  1837. ;
  1838.     SDED    NXTCHR
  1839. ;
  1840. ; Set zero flag to indicate presence of '?' in FILENAME.TYPE
  1841. ;
  1842. QMCNT    EQU    $+1        ; Pointer for in-the-code modification
  1843.     MVI    A,0        ; Number of question marks
  1844.     ORA    A        ; Set zero flag to indicate any '?'
  1845.     RET
  1846. ;
  1847. ; Scan token pointed to by DE for a max of B bytes; place it into file
  1848. ; name field pointed to by HL; expand and interpret wild cards of '*'
  1849. ; '?'; on exit, DE points to terminating delimiter.
  1850. ;
  1851. SCANF:    CALL    SDELM        ; Done if delimiter encountered
  1852.     JRZ    SCANF4
  1853.     INX    H        ; Point to next byte in FCBDN
  1854.     CPI    '*'        ; Is (DE) a wild card?
  1855.     JRNZ    SCANF1        ; Continue if not
  1856.     MVI    M,'?'        ; Place '?' in FCB
  1857.     CALL    SCQ        ; Scanner count question marks
  1858.     JR    SCANF2
  1859. ;
  1860. SCANF1:    MOV    M,A        ; Store filename char in fcb
  1861.     INX    D        ; Pt to next char in command line
  1862.     CPI    '?'        ; Check for question mark (wild)
  1863.     CZ    SCQ        ; Scanner count question marks
  1864. ;
  1865. SCANF2:    DJNZ    SCANF        ; Decrement char count until 8 elapsed
  1866. ;
  1867. SCANF3:    CALL    SDELM        ; 8 chars or more - skip until delimiter
  1868.     RZ            ; Zero flag set if delimiter found
  1869.     INX    D        ; Pt to next char in command line
  1870.     JR    SCANF3
  1871. ;
  1872. ; Fill memory pointed to by HL with spaces for B bytes
  1873. ;
  1874. SCANF4:    MVI    A,' '        ; Fill with spaces
  1875. ;
  1876. SCANF5:    INX    H        ; Point to next byte in FCB
  1877.     MOV    M,A        ; Fill with byte in A-reg.
  1878.     DJNZ    SCANF5
  1879.     RET
  1880. ;
  1881. ; Increment question mark count for scanner - this routine increments
  1882. ; the count of the number of question marks in the current FCB entry.
  1883. ;
  1884. SCQ:    PUSH    H        ; Save HL
  1885.     LXI    H,QMCNT        ; Get count
  1886.     INR    M        ; Increment
  1887.     POP    H        ; Get HL
  1888.     RET
  1889. ;
  1890. ; CMDTBL (command table) scanner
  1891. ;   On return, HL points to address of command if CCP-resident
  1892. ;   On return, zero flag set means CCP-resident command
  1893. ;
  1894. CMDSER:    LXI    H,CMDTBL    ; Point to command table
  1895.     MVI    C,NCMNDS    ; Set command counter
  1896.     MOV    A,C        ; Check number of commands
  1897.     ORA    A        ; If none, then abort
  1898.     JRZ    CMS5
  1899. ;
  1900. CMS1:    LXI    D,FCBFN        ; Point to stored command name
  1901.     MVI    B,NCHARS    ; Number of chars/command (8 max)
  1902. ;
  1903. CMS2:    LDAX    D        ; Compare against table entry
  1904.     CMP    M
  1905.     JRNZ    CMS3        ; No match
  1906.     INX    D        ; Point to next character
  1907.     INX    H
  1908.     DJNZ    CMS2        ; Count down
  1909.     LDAX    D        ; Next char must be a space
  1910.     CPI    ' '
  1911.     JRNZ    CMS4
  1912.     RET            ; Command is CCP-resident
  1913. ;
  1914. CMS3:    INX    H        ; Skip to next command table entry
  1915.     DJNZ    CMS3
  1916. ;
  1917. CMS4:    INX    H        ; Skip address
  1918.     INX    H
  1919.     DCR    C        ; Decrement table entry number
  1920.     JRNZ    CMS1
  1921. ;
  1922. CMS5:    INR    C        ; Clear zero flag
  1923.     RET            ; Command is disk-resident
  1924. ;
  1925. ;-----
  1926. ;
  1927. ; **** section 5 ****
  1928. ;
  1929. ; CCP-resident commands
  1930. ;
  1931. ; Section:  5A
  1932. ; Command:  DIR
  1933. ; Function: To display a directory of the files on disk
  1934. ; Forms:
  1935. ;    DIR <AFN>    displays the DIR files
  1936. ;    DIR <AFN> s    displays the SYS files
  1937. ;    DIR <AFN> a    display both DIR and SYS files
  1938. ;
  1939. ;   NOTES:
  1940. ;    the flag SYSFLG defines the letter used to display both DIR and
  1941. ;        SYS files (A in the above forms section)
  1942. ;    the flag SOFLG defines the letter used to display only the SYS
  1943. ;        files (S in the above forms section)
  1944. ;    the flag WIDE determines if the file names are spaced further
  1945. ;        apart (wide=yes) for 80-col screens
  1946. ;    the flag FENCE defines the character used to separate the file
  1947. ;        names
  1948. ;
  1949.      IF    DIRON        ; Dir enabled
  1950. DIR:    CALL    SCANLOG        ; Extract possible D:FILENAME.TYP token
  1951.     LXI    H,FCBFN        ; Make FCB wild (all '?') if no NAME.TYP
  1952.     MOV    A,M        ; Get first chararacter of NAME.TYPE
  1953.     CPI    ' '        ; If space, all wild
  1954.     CZ    FILLQ
  1955.     CALL    ADVAN        ; Look at next input char
  1956.     MVI    B,80H        ; Prepare for dir-only selection
  1957.     JRZ    DIRDN        ; There is no flag, so dir only
  1958.     MVI    B,1        ; Set for both dir and sys files
  1959.     CPI    SYSFLG        ; System and dir flag specifier?
  1960.     JRZ    GOTFLG        ; Got system specifier
  1961.     CPI    SOFLG        ; Sys only?
  1962.     JRNZ    DIRDN
  1963.     DCR    B        ; B=0 for sys files only
  1964. ;
  1965. GOTFLG:    INX    D        ; Pt to char after flag
  1966. ;
  1967. DIRDN:    SDED    NXTCHR        ; Set pointer for next pass then drop
  1968.                 ;   DIRRPR to print directory and go
  1969.                 ;   restart CCP
  1970.      ENDIF
  1971. ;
  1972. ; Directory print routine; on entry, B- reg is set as follows:
  1973. ;    0 for only system files, 80H for only DIR files, 1 for both
  1974. ;
  1975.      IF    DIRON OR ERAON
  1976. DIRPR:    MOV    A,B        ; Get flag
  1977.     STA    SYSTST        ; Set system test flag
  1978.     MVI    E,0        ; Set column counter to zero
  1979.     PUSH    D        ; Save column counter (e)
  1980.     CALL    SEARF        ; Search for specified file
  1981.     JRNZ    DIR3
  1982.     CALL    PRNNF        ; Print no file msg; reg a not changed
  1983.     XRA    A        ; Set zero flag
  1984.     POP    D        ; Restore de
  1985.     RET
  1986. ;
  1987. ; Entry selection loop; on entry, A=offset from SEARF or SEARN
  1988. ;
  1989. DIR3:    CALL    GETSBIT        ; Get and test for type of files
  1990.     JRZ    DIR6
  1991.     POP    D        ; Get entry count (=<CR> counter)
  1992.     MOV    A,E        ; Add 1 to it
  1993.     INR    E
  1994.     PUSH    D        ; Save it
  1995.     ANI    03H        ; Output <CRLF> if 4 entries printed
  1996.     JRNZ    DIR4
  1997.     CALL    CRLF        ; New line
  1998.     JR    DIR5
  1999. ;
  2000. DIR4:    CALL    PRINT
  2001. ;
  2002.      IF    WIDE
  2003.     DB    '  '        ; 2 spaces
  2004.     DB    FENCE        ; Then fence char
  2005.     DB    ' ',' '+80H    ; Then 2 more spaces
  2006.      ENDIF
  2007. ;
  2008.      IF    NOT WIDE
  2009.     DB    ' '        ; Space
  2010.     DB    FENCE        ; Then fence char
  2011.     DB    ' '+80H        ; Then space
  2012.      ENDIF
  2013. ;
  2014. DIR5:    MVI    B,01H        ; Pt to 1st byte of file name
  2015.     MOV    A,B        ; A=offset
  2016.     CALL    DIRPTR        ; Hl now pts to 1st byte of file name
  2017.     CALL    PRFN        ; Print file name
  2018. ;
  2019. DIR6:    CALL    BREAK        ; Check for abort
  2020.     JRZ    DIR7
  2021.     CALL    SEARN        ; Search for next file
  2022.     JRNZ    DIR3        ; Continue if file found
  2023. ;
  2024. DIR7:    POP    D        ; Restore stack
  2025.     MVI    A,0FFH        ; Set nz flag
  2026.     ORA    A
  2027.     RET
  2028.      ENDIF
  2029. ;
  2030. ; Print file name pointed to by HL
  2031. ;
  2032. PRFN:    MVI    B,8        ; 8 chars
  2033.     CALL    PRFN1
  2034.     MVI    A,'.'        ; Dot
  2035.     CALL    CONOUT
  2036.     MVI    B,3        ; 3 chars
  2037. ;
  2038. PRFN1:    MOV    A,M        ; Get char
  2039.     INX    H        ; Pt to next
  2040.     CALL    CONOUT        ; Print char
  2041.     DCR    B        ; Count down
  2042.     JRNZ    PRFN1
  2043.     RET
  2044. ;
  2045. ; After a search, return NZ set if desired type of file found, Z if not.
  2046. ; This algorithm looks at the system bit of the located file.  This bit
  2047. ; is set to 1 if the file is a system file and 0 if not a system file.
  2048. ; The following exclusive or masks are applied to return Z or NZ as re-
  2049. ; quired by the calling program:
  2050. ;
  2051. ;   System byte: x 0 0 0  0 0 0 0    after 80H mask, x=1 if SYS
  2052. ;
  2053. ;   SYS-only   : 0 0 0 0  0 0 0 0    XOR 0   = 0 if X=0   (or 80H if X=1)
  2054. ;   DIR-only   : 1 0 0 0  0 0 0 0    XOR 80H = 80H if X=0 (or 0 if X=1)
  2055. ;    both   : 0 0 0 0  0 0 0 1    XOR 1   = 81H or 1H  (or NZ for both)
  2056. ;
  2057. GETSBIT:DCR    A        ; Adjust to returned value
  2058.     RRC            ; Convert number to offset into tbuff
  2059.     RRC
  2060.     RRC
  2061.     ANI    60H
  2062.     MOV    C,A        ; Offset into TBUFF in c
  2063.     MVI    A,10        ; Add 10 to point to SYS file attribute
  2064.     CALL    DIRPTR        ; A=system byte
  2065.     ANI    80H        ; Look at only system bit
  2066. ;
  2067. SYSTST    EQU    $+1        ; In-the-code variable
  2068.     XRI    0        ; If SYSTST=0, sys only; if =80h, DIR
  2069.     RET            ; NZ if ok, Z if not ok
  2070. ;
  2071. ; Fill FCB @HL with '?'
  2072. ;
  2073. FILLQ:    MVI    B,11        ; Number of characters in FN & FT
  2074. ;
  2075. FQLP:    MVI    M,'?'        ; Store '?'
  2076.     INX    H
  2077.     DJNZ    FQLP
  2078.     RET
  2079. ;
  2080. ; Section:  5B
  2081. ; Command:  ERA
  2082. ; Function: Erase files
  2083. ; Forms:
  2084. ;    ERA <AFN>    erase specified files and print their names
  2085. ;    ERA <AFN> V    erase specified files and print their names,
  2086. ;              but ask for verification before erase is done
  2087. ;   NOTES::
  2088. ;    Several key flags affect this command:
  2089. ;        ERAV  - if yes, the V- option is enabled, and the char-
  2090. ;              acter which turns it on (the V) is defined by
  2091. ;              ERDFLG.
  2092. ;        ERACK - if yes, the ok? prompt is enabled
  2093. ;              If ERAO is NO, the verification feature is
  2094. ;                disabled regardless of what value ERAV has
  2095. ;              If ERAOK is yes, then:
  2096. ;                If ERAV is yes, verification is request-
  2097. ;                  ed only if the V-flag (actual letter
  2098. ;                  defined by ERDFLG) is in the cmd line
  2099. ;                If ERAV is NO, verification is always
  2100. ;                   requested, and a V-flag in the com-
  2101. ;                   mand line will cause an error message
  2102. ;                   to be printed (v?) after the ERA is
  2103. ;                   completed.
  2104. ;
  2105.      IF    ERAON
  2106. ERA:     IF    WERA
  2107.     CALL    WHLCHK        ; Check for it
  2108.      ENDIF
  2109. ;
  2110.     CALL    SCANLOG        ; Parse file specification
  2111. ;
  2112.      IF    ERAV AND ERAOK
  2113.     CALL    ADVAN        ; Get ERAFLG if it's there
  2114.     STA    ERAFLG        ; Save it as a flag
  2115.     JRZ    ERA1        ; Jump if input ended
  2116.     INX    D        ; Put new buffer pointer
  2117. ;
  2118. ERA1:    XCHG            ; Put pointer into HL
  2119.     SHLD    NXTCHR        ; Set pointer to byte for next command
  2120.      ENDIF
  2121. ;
  2122.     MVI    B,1        ; Display all matching files
  2123.     CALL    DIRPR        ; Print directory of erased files
  2124.     RZ            ; Abort if no files
  2125. ;
  2126.      IF    ERAOK
  2127.      IF    ERAV
  2128. ERAFLG    EQU    $+1        ; Address of flag
  2129.     MVI    A,0        ; 2nd byte is flag
  2130.     CPI    ERDFLG        ; Is it a verify option?
  2131.     JRNZ    ERA2        ; Skip prompt if it is not
  2132.      ENDIF
  2133. ;
  2134.     CALL    PRINTC
  2135.     DB    'OK to Erase','?'+80H
  2136.     CALL    CONIN        ; Get reply
  2137.     CPI    'Y'        ; Yes?
  2138.     RNZ            ; Abort if not
  2139.      ENDIF
  2140. ;
  2141. ERA2:    LXI    D,FCBDN        ; Delete file specified
  2142.     CALL    DELETE
  2143.     RET            ; Reenter cpr
  2144.      ENDIF
  2145. ;
  2146. ; Section:  5C
  2147. ; Command:  LIST
  2148. ; Function: Print out specified file on the lst device
  2149. ; Fforms:
  2150. ;    LIST <UFN>    print file (no paging)
  2151. ;
  2152. ; NOTES: The flags which apply to type do not take effect with list
  2153. ;
  2154.      IF    LTON
  2155. LIST:    MVI    A,0FFH        ; Turn on printer flag
  2156.     JR    TYPE0
  2157. ;
  2158. ; Section:  5D
  2159. ; Command:  TYPE
  2160. ; Function: Print out specified file on the con: device
  2161. ; Forms:
  2162. ;    TYPE <UFN>    print file
  2163. ;    TYPE <UFN> P    print file with paging flag
  2164. ;
  2165. ;   NOTES:
  2166. ;    The flag PGDFLG defines the letter which toggles the paging
  2167. ;        facility (P in the forms section above)
  2168. ;    The flag PGDFLT determines if type is to page by default
  2169. ;        (PGDFLT=YES if type pages by default); combined with
  2170. ;        PGDFLG, the following events occur --
  2171. ;            If PGDFLT = YES, PGDFLG turns off paging
  2172. ;            If PGDFLT = NO, PGDFLG turns on paging
  2173. ;
  2174. TYPE:    XRA    A        ; Turn off printer flag
  2175. ;
  2176. ; Entry point for CCP list function (list)
  2177. ;
  2178. TYPE0:    STA    PRFLG        ; Set flag
  2179. ;
  2180.      IF    WLT
  2181.     CALL    WHLCHK        ; Check wheel byte
  2182.      ENDIF
  2183. ;
  2184.     CALL    SCANLOG        ; Extract FILENAME.TYP toden
  2185.     JNZ    ERROR        ; Error if any question marks
  2186.     CALL    ADVAN        ; Get pgdflg if it's there
  2187.     STA    PGFLG        ; Save it as a flag
  2188.     JRZ    TYPE1        ; Jump if input ended
  2189.     INX    D        ; Put new buf pointer
  2190. ;
  2191. TYPE1:    SDED    NXTCHR        ; Set pointer for next command
  2192.     CALL    OPENF        ; Open selected file
  2193.     JZ    ERROR        ; Abort if error
  2194.     CALL    CRLF        ; New line
  2195.     MVI    A,NLINES-1    ; Set line count
  2196.     STA    PAGCNT
  2197.     LXI    B,80H        ; Set character position and tab count
  2198. ;
  2199. ; Main loop for loading next block
  2200. ;
  2201. TYPE2:    MOV    A,C        ; Get character count
  2202.     CPI    80H
  2203.     JRC    TYPE3
  2204.     PUSH    H        ; Read next block
  2205.     PUSH    B
  2206.     CALL    READF
  2207.     POP    B
  2208.     POP    H
  2209.     JRNZ    TYPE7        ; Error?
  2210.     MVI    C,0        ; Set character count
  2211.     LXI    H,TBUFF        ; Poin to first character
  2212. ;
  2213. ; Main loop for printing character in TBUFF
  2214. ;
  2215. TYPE3:    MOV    A,M        ; Get next char
  2216.     ANI    7FH        ; Mask out msb
  2217.     CPI    1AH        ; End of file (^z)?
  2218.     RZ            ; Restart cpr if so
  2219. ;
  2220. ; Output character to CRT or list device with tabulation
  2221. ;
  2222.     CPI    CR        ; Reset tab count?
  2223.     JRZ    TYPE4
  2224.     CPI    LF        ; Reset tab count?
  2225.     JRZ    TYPE4
  2226.     CPI    TAB        ; Tab?
  2227.     JRZ    TYPE5
  2228. ;
  2229. ; Output character and increment character count
  2230. ;
  2231.     CALL    LCOUT        ; Output char
  2232.     INR    B        ; Increment tab count
  2233.     JR    TYPE6
  2234. ;
  2235. ; Output <CR> or <LF> and reset tab count
  2236. ;
  2237. TYPE4:    CALL    LCOUT        ; Output <CR> or <LF>
  2238.     MVI    B,0        ; Reset tab counter
  2239.     JR    TYPE6
  2240. ;
  2241. ; Tabulate
  2242. ;
  2243. TYPE5:    MVI    A,' '        ; Space
  2244.     CALL    LCOUT
  2245.     INR    B        ; Increment position count
  2246.     MOV    A,B
  2247.     ANI    7
  2248.     JRNZ    TYPE5
  2249. ;
  2250. ; Continue processing
  2251. ;
  2252. TYPE6:    INR    C        ; Increment char count
  2253.     INX    H        ; Pt to next char
  2254.     CALL    BREAK        ; Check for abort
  2255.     RZ            ; Restart if so
  2256.     JR    TYPE2
  2257. ;
  2258. TYPE7:    DCR    A        ; No error?
  2259.     RZ            ; Restart cpr
  2260.     JMP    ERROR
  2261.      ENDIF
  2262. ;
  2263. ; Section:  5E
  2264. ; Command:  SAVE
  2265. ; Function: To save the contents of the TPA onto disk as a file
  2266. ; Forms:
  2267. ;    SAVE <number of pages> <UFN>
  2268. ;        save specified number of pages (start at 100H)
  2269. ;        from TPA into specified file; <number of pages> in DEC
  2270. ;    SAVE <number of sectors> <UFN> s
  2271. ;        like SAVE above, but numeric argument specifies number
  2272. ;        of sectors rather than pages
  2273. ;NOTES:
  2274. ;    The MULTCMD flag (multiple commands allowed) expands the code
  2275. ;        slightly, but is required to support multiple commands
  2276. ;         with SAVE
  2277. ;    The SECTFLG defines the letter which indicates a sector count
  2278. ;        (S in the forms section above)
  2279. ;
  2280.      IF    SAVEON
  2281. SAVE:     IF    WSAVE
  2282.     CALL    WHLCHK        ; Check for wheel byte
  2283.      ENDIF
  2284. ;
  2285.     CALL    NUMBER        ; Extract number from command line
  2286.     MOV    L,A        ; HL=page count
  2287.     MVI    H,0
  2288.     PUSH    H        ; Save page count
  2289.     CALL    EXTEST        ; Test for existence of file
  2290.     MVI    C,16H        ; Bdos make file
  2291.     CALL    GRBDOS
  2292.     POP    H        ; Get page count
  2293.     JRZ    SAVE3        ; Error?
  2294.     XRA    A        ; Set record count field
  2295.     STA    FCBCR
  2296.     CALL    ADVAN        ; Look for 's' for sector option
  2297.     INX    D        ; Pt to after 's' token
  2298.     CPI    SECTFLG
  2299.     JRZ    SAVE0
  2300.     DCX    D        ; No 's' token, so back up
  2301.     DAD    H        ; Double it for HL=record (128 bytes)
  2302. ;
  2303. SAVE0:    SDED    NXTCHR        ; Set pointer to bad token
  2304.     LXI    D,TPA        ; Point to start of SAVE area (TPA)
  2305. ;
  2306. SAVE1:    MOV    A,H        ; Done with save?
  2307.     ORA    L        ; HL=0 if so
  2308.     JRZ    SAVE2
  2309.     DCX    H        ; Count down on record
  2310.     PUSH    H        ; Save pointer to block to save
  2311.     LXI    H,128        ; 128 bytes per record
  2312.     DAD    D        ; Point to next record
  2313.     PUSH    H        ; Save on stack
  2314.     CALL    DMASET        ; Set DMA address for write (addr in DE)
  2315.     LXI    D,FCBDN        ; Write record
  2316.     MVI    C,15H        ; Bdos write record
  2317.     CALL    BDOSB        ; Save bc
  2318.     POP    D        ; Get ptr to next record in DE
  2319.     POP    H        ; Get record count
  2320.     JRNZ    SAVE3        ; Write error?
  2321.     JR    SAVE1        ; Continue
  2322. ;
  2323. SAVE2:    LXI    D,FCBDN        ; Close saved file
  2324.     CALL    CLOSE
  2325.     INR    A        ; Error?
  2326.     JRNZ    SAVE4
  2327. ;
  2328. SAVE3:    CALL    PRNLE        ; Print 'no space' error
  2329. ;
  2330. SAVE4:    JMP    DEFDMA        ; Set DMA to 80 and restart cpr
  2331.      ENDIF
  2332. ;
  2333. ; Test file in FCB for existence, ask user to delete if so, and abort if
  2334. ; he chooses not to.
  2335. ;
  2336.      IF    SAVEON OR RENON
  2337. EXTEST:    CALL    SCANLOG        ; Extract file name and log in user/disk
  2338.     JNZ    ERROR        ; '?' is not permitted
  2339.     CALL    SEARF        ; Look for specified file
  2340.     LXI    D,FCBDN        ; Point to file FCB
  2341.     RZ            ; Ok if not found
  2342.     PUSH    D        ; Save pointer to FCB
  2343.     CALL    PRINTC
  2344.     DB    'Erase',' '+80H
  2345.     LXI    H,FCBFN        ; Point to file name field
  2346.     CALL    PRFN        ; Print it
  2347.     MVI    A,'?'        ; Print question
  2348.     CALL    CONOUT
  2349.     CALL    CONIN        ; Get response
  2350.     POP    D        ; Get ptr to fcb
  2351.     CPI    'Y'        ; Key on yes
  2352.     JNZ    ERR3        ; Restart as error if no
  2353.     PUSH    D        ; Save ptr to fcb
  2354.     CALL    DELETE        ; Delete file
  2355.     POP    D        ; Get ptr to fcb
  2356.     RET
  2357.      ENDIF
  2358. ;
  2359. ; Section:  5F
  2360. ; Command:  REN
  2361. ; Function: To change the name of an existing file
  2362. ; Forms:
  2363. ;    REN <new UFN>=<old UFN> perform function
  2364. ;
  2365.      IF    RENON
  2366. REN:     IF    WREN
  2367.     CALL    WHLCHK        ; Check for wheel byte
  2368.      ENDIF
  2369. ;
  2370.     CALL    EXTEST        ; Test for file existence and return
  2371.     LDA    TEMPDR        ; Save selected disk
  2372.     PUSH    PSW        ; Save on stack
  2373. ;
  2374. REN0:    LXI    H,FCBDN        ; Save new file name
  2375.     LXI    D,FCBDM
  2376.     LXI    B,16        ; 16 bytes
  2377.     LDIR
  2378.     CALL    ADVAN        ; Advance to next character (non-delim)
  2379.     JRZ    REN4        ; Error if none
  2380. ;
  2381. ; Perform rename function
  2382. ;
  2383. REN1:    SDED    NXTCHR        ; Save pointer to old file name
  2384.     CALL    SCANER        ; Extract FILENAME.TYP token
  2385.     JRNZ    REN4        ; Error if any '?'
  2386.     POP    PSW        ; Get old default drive
  2387.     MOV    B,A        ; Save it
  2388.     LXI    H,TEMPDR    ; Compare it against selected drive
  2389.     MOV    A,M        ; Default?
  2390.     ORA    A
  2391.     JRZ    REN2
  2392.     CMP    B        ; Check for drive error
  2393.     JRNZ    REN4
  2394. ;
  2395. REN2:    MOV    M,B
  2396.     XRA    A
  2397.     STA    FCBDN        ; Set default drive
  2398.     LXI    D,FCBDN        ; Rename file
  2399.     MVI    C,17H        ; BDOS rename FCT
  2400.     CALL    GRBDOS
  2401.     RNZ
  2402. ;
  2403. REN3:    CALL    PRNNF        ; Print NO FILE message
  2404. ;
  2405. REN4:    JMP    ERROR
  2406.      ENDIF
  2407. ;
  2408. RSTJMP:    JMP    RCCPNL        ; Restart CCP
  2409. ;
  2410. ; Section:  5G
  2411. ; Command:  JUMP
  2412. ; Function: To call the program (subroutine) at the specified address
  2413. ;         without loading from disk
  2414. ; Forms:
  2415. ;    JMMP <adr>        call at <ADR>;<ADR> is in hex
  2416. ;
  2417.      IF    JUMPON
  2418. JUMP:     IF    WJUMP
  2419.     CALL    WHLCHK        ; Check for wheel byte
  2420.        ENDIF
  2421. ;
  2422.     CALL    HEXNUM        ; Get load address in HL
  2423.     JR    CALLPROG    ; Perform call
  2424.      ENDIF
  2425. ;
  2426. ; Section:  5H
  2427. ; Command:  GO
  2428. ; Function: To call the program in the TPA without loading from disk.
  2429. ;        Same as JMP 100H, but much more convenient, especially
  2430. ;        when used with parameters for programs like STAT.  Also,
  2431. ;        can be allowed on remote-access systems.
  2432. ; Form:
  2433. ;    GO <parameters like for command>
  2434. ;
  2435.      IF    GOON
  2436. GO:     IF    WGO
  2437.     CALL    WHLCHK        ; Check for wheel byte
  2438.      ENDIF
  2439. ;
  2440.     LXI    H,TPA        ; Always to TPA
  2441.     JR    CALLPROG    ; Perform call
  2442.      ENDIF
  2443. ;
  2444. ; Section:  5I
  2445. ; Command:  COM file processing
  2446. ; Function: To load the specified .COM file from disk and execute it
  2447. ; Forms:    <command line>
  2448. ; NOTES:    .COM files are processed as follows --
  2449. ;        1. file name buffers are initialized and a preliminary
  2450. ;            error check is done
  2451. ;        2. MLOAD is used to search for the file along the path
  2452. ;            and load it into the TPA
  2453. ;        3. CALLPROG is used to set up the buffers to be used by
  2454. ;            the transient (FCB at 5CH, FCB at 6CH, TBUFF at
  2455. ;            80H) and run the program
  2456. ;    The flag MULTCMD comes into play frequently here; it mainly
  2457. ;        serves to save space if MULTCMD is NO and and enables
  2458. ;        multiple commands on the same line if MULTCMD is YES.
  2459. ;
  2460. COM:    LDA    FCBFN        ; Any command?
  2461.     CPI    ' '        ; ' ' means command was 'D:' to switch
  2462.     JRNZ    COM1        ; Must be transient or error
  2463. ;
  2464. ; Entry point to select user/disk
  2465. ;
  2466.      IF    WDU
  2467.     CALL    WHLCHK        ; Check for wheel byte
  2468.      ENDIF
  2469. ;
  2470.     LDA    COLON        ; Look for colon flag
  2471.     ORA    A        ; If zero, just blank
  2472.     RZ            ; Return to main routine
  2473. ;
  2474. ; Command is DU:, so log in user/disk
  2475. ;
  2476.     LDA    TEMPUSR        ; Get selected user
  2477.     CPI    10H        ; Make sure 4 bits
  2478.     JNC    ERROR        ; Range error?
  2479.     STA    CURUSR        ; Set current user
  2480.     CALL    SLOGIN        ; Log in user/disk as if temporarily
  2481. ;
  2482. ; Now, make login permanent
  2483. ;
  2484.     LDA    TEMPDR        ; Get selected drive
  2485.     ORA    A        ; If 0 (default), no change
  2486.     JRZ    COM0
  2487.     DCR    A        ; Adjust for log in
  2488.     STA    CURDR        ; Set current drive
  2489. ;
  2490. COM0:    JMP    SETUD        ; Set current user/disk
  2491. ;
  2492. ; Process command
  2493. ;
  2494. COM1:    LXI    D,FCBFT        ; Point to file type
  2495.     LDAX    D        ; Get first character of file type
  2496.     CPI    ' '        ; Must be blank, or error
  2497.     JNZ    ERROR
  2498.     LXI    H,COMMSG    ; Place default file type (com) into fcb
  2499.     LXI    B,3        ; 3 bytes
  2500.     LDIR
  2501.     LXI    H,TPA        ; Set execution/load address
  2502.     PUSH    H        ; Save for execution
  2503. ;
  2504.      IF    CMDRUN
  2505.     MVI    A,0FFH        ; Use it if available
  2506.      ENDIF
  2507. ;
  2508.     CALL    MLOAD        ; Load memory with file specified
  2509.     POP    H        ; Get execution address
  2510. ;
  2511. ; Entry point for the execution of the loaded program; on entry to this
  2512. ; routine, HL must contain the execution address of the program (subrou-
  2513. ; tine) to execute.
  2514. ;
  2515. CALLPROG:
  2516.     SHLD    EXECADR        ; Perform in-line code modification
  2517.     CALL    SCANER        ; Search command line for next token
  2518.     LXI    H,TEMPDR    ; Save pointer to drive specification
  2519.     PUSH    H
  2520.     MOV    A,M        ; Set drive specification
  2521.     STA    FCBDN
  2522.     LXI    H,FCBDN+10H    ; Pt to 2nd file name
  2523.     CALL    SCANX        ; Scan for it and load it into fcb+16
  2524.     POP    H        ; Set up drive specs
  2525.     MOV    A,M
  2526.     STA    FCBDM
  2527.     XRA    A
  2528.     STA    FCBCR
  2529.     LXI    D,TFCB        ; Copy to default FCB
  2530.     LXI    H,FCBDN        ; From FCBDN
  2531.     LXI    B,33        ; Set up default FCB
  2532.     LDIR
  2533. ;
  2534. CMDCH1    EQU    $+1        ; In-the-code buffer address of 1st char
  2535.     LXI    H,CMDLIN
  2536. ;
  2537. CALLP1:    MOV    A,M        ; Skip to end of 2nd file name
  2538.     ORA    A        ; End of line?
  2539.     JRZ    CALLP2
  2540. ;
  2541.      IF    MULTCMD
  2542.     CPI    CMDSEP        ; Command separator?
  2543.     JRZ    CALLP2
  2544.      ENDIF
  2545. ;
  2546.     CPI    ' '        ; End of token?
  2547.     JRZ    CALLP2
  2548.     INX    H
  2549.     JR    CALLP1
  2550. ;
  2551. ; Load command line into TBUFF
  2552. ;
  2553. CALLP2:    MVI    B,0        ; Set character count
  2554.     LXI    D,TBUFF+1    ; Point to character position
  2555. ;
  2556. CALLP3:    MOV    A,M        ; Copy command line to TBUFF
  2557.     STAX    D
  2558.     ORA    A        ; Done if zero
  2559.     JRZ    CALLP5
  2560. ;
  2561.      IF    MULTCMD
  2562.     CPI    CMDSEP        ; Done if command separator
  2563.     JRZ    CALLP4
  2564.      ENDIF
  2565. ;
  2566.     INR    B        ; Increment character count
  2567.     INX    H        ; Point to next
  2568.     INX    D
  2569.     JR    CALLP3
  2570. ;
  2571.      IF    MULTCMD
  2572. CALLP4:    XRA    A        ; Store ending zero
  2573.     STAX    D        ; Instead of cmdsep
  2574.      ENDIF
  2575. ;
  2576. ; Run loaded transient program
  2577. ;
  2578. CALLP5:     IF    MULTCMD
  2579.     SHLD    NXTCHR        ; Save pointer to continue processing
  2580.      ENDIF
  2581. ;
  2582.     MOV    A,B        ; Save character count
  2583.     STA    TBUFF
  2584.     CALL    CRLF        ; New line
  2585.     CALL    DEFDMA        ; Set DMA to 80
  2586. ;
  2587. ; Execution (call) of program (subroutine) occurs here
  2588. ;
  2589. EXECADR    EQU    $+1        ; Change address for in-line code mod.
  2590.     CALL    TPA        ; Call transient
  2591.     CALL    DEFDMA        ; Set DMA to 80 in case it was changed
  2592.     CALL    DLOGIN        ; Login current user/disk
  2593.     JMP    CONT        ; Restart CCP and continue command
  2594. ;
  2595. ; Section:  5J
  2596. ; Command: GET
  2597. ; Function: To load the specified file from disk to the specified
  2598. ;         address
  2599. ; Forms:
  2600. ;    GET <adr> <UFN> load the specified file at the specified page;
  2601. ;        <adr> is in hex
  2602. ;
  2603.      IF    GETON
  2604. GET:     IF    WGET
  2605.     CALL    WHLCHK        ; Check wheel byte
  2606.      ENDIF
  2607. ;
  2608.     CALL    HEXNUM        ; Get load address in hl
  2609.     PUSH    H        ; Save address
  2610.     CALL    SCANER        ; Get file name
  2611.     POP    H        ; Restore address
  2612.     JNZ    ERROR        ; Must be unambiguous
  2613. ;
  2614. ;
  2615. ; Fall through to MLOAD
  2616. ;
  2617.      IF    CMDRUN
  2618.     XRA    A        ; No cmdrun if facility is there
  2619.      ENDIF
  2620.      ENDIF
  2621. ;
  2622. ;
  2623. ; Memory load subroutine
  2624. ;
  2625. ; Load memory with the file whose name is specified in the command line.
  2626. ; On input, HL contains starting address to load.  Exit points are a re-
  2627. ; turn and log-in current user/disk if no error, a jmp to error if .COM
  2628. ; file not found or a message and abort if memory full.
  2629. ;
  2630. MLOAD:     IF    CMDRUN
  2631.     STA    CRFLAG        ; Save flag
  2632.      ENDIF
  2633. ;
  2634.     SHLD    LOADADR        ; Set load address
  2635. ;
  2636. ; Reentry point for a non-standard CP/M modification.  The path command-
  2637. ; search is implemented by this routine
  2638. ;
  2639. MLA:     IF    DRVPREFIX
  2640.      IF    PRIVDIR
  2641.     LDA    WHLADR        ; Don't allow prefixes unless
  2642.     ORA    A        ; User is a wheel
  2643.     LXI    H,PATH
  2644.     JRZ    MLA0
  2645.      ENDIF
  2646. ;
  2647.     MVI    A,DRVPFATT    ; Set flag per user spec for sys/non-sys
  2648.     STA    SYSTST        ; Test flag in getsbit
  2649.     CALL    SLOGIN        ; Look under temporary user/disk
  2650.     CALL    SEARF        ; Look for file
  2651. ;
  2652. MLARUN:    LXI    H,PATH        ; Point to path for failure possibility
  2653.     JRNZ    MLA4        ; Found it -- load it and run
  2654.      ENDIF
  2655. ;
  2656.      IF    NOT DRVPREFIX
  2657. MLARUN:    LXI    H,PATH        ; Point to path
  2658.      ENDIF
  2659. ;
  2660. MLA0:    MOV    A,M        ; Get drive
  2661.     ORA    A        ; 0=done=command not found
  2662. ;
  2663.      IF    CMDRUN
  2664.     JRNZ    NOCRUN        ; Not ready for cmd run yet
  2665. ;
  2666. CRFLAG    EQU    $+1        ; Pointer for in-the-code modification
  2667.     MVI    A,0        ; Check crflag
  2668.     ORA    A        ; 0=no
  2669.     JZ    ERROR        ; Process as error
  2670. ;
  2671.      IF    ROOTONLY
  2672.     PUSH    H
  2673.      ENDIF
  2674. ;
  2675.     XRA    A        ; Do not reenter this code
  2676.     STA    CRFLAG        ; Set zero for no entry
  2677.     LHLD    CMDCH1        ; Get pointer to first char of command
  2678.     DCX    H        ; Pt to char count
  2679.     MVI    M,' '        ; Store leading space
  2680.     SHLD    CMDCH1        ; Point to leading space as first char
  2681.     SHLD    NXTCHR        ; Next char is first char of command
  2682.     LXI    H,CFCB        ; Set cfcb as command
  2683.     LXI    D,FCBDN        ; By copying it into fcbdn
  2684.     LXI    B,12        ; Only 12 bytes required
  2685.     LDIR
  2686. ;
  2687.      IF    ROOTONLY
  2688.     JR    MLA3RT
  2689.      ENDIF
  2690. ;
  2691.      IF    NOT ROOTONLY
  2692.     XRA    A        ; A=0
  2693.     JR    MLARUN        ; Now try the run
  2694.      ENDIF
  2695. ;
  2696. CFCB:    CMDFCB            ; FCB defining initial command
  2697. ;
  2698. NOCRUN:     ENDIF            ; CMDRUN
  2699. ;
  2700.      IF    NOT CMDRUN
  2701.     JZ    ERROR        ; Transient load error -- file not found
  2702.      ENDIF
  2703. ;
  2704. ; Look for command in directory pointed to by HL; drive in 'A:'
  2705. ;
  2706.     CPI    CURIND        ; Current drive specified?
  2707.     JRNZ    MLA1        ; Skip default drive selection if so
  2708.     LDA    CURDR        ; Get current drive
  2709.     INR    A        ; Set a=1
  2710. ;
  2711. MLA1:    STA    TEMPDR        ; Select different drive if not current
  2712.     MVI    A,1        ; Accept both SYS and DIR files
  2713.     STA    SYSTST        ; Test flag is 1 for both
  2714.     INX    H        ; Point to user number
  2715.     MOV    A,M        ; Get user number
  2716.     INX    H        ; Poin to next entry in path
  2717.     PUSH    H        ; Save pointer
  2718.     ANI    7FH        ; Mask out system bit
  2719.     CPI    CURIND        ; Current user specified?
  2720.     JRNZ    MLA2        ; Do not select current user if so
  2721.     LDA    CURUSR        ; Get current user number
  2722. ;
  2723. MLA2:    STA    TEMPUSR        ; Set temporary user number
  2724.     CMA            ; System bit is 0 if SYS-only
  2725.     ANI    80H
  2726.     JRNZ    MLA3        ; Flag not set if system bit=0
  2727.     STA    SYSTST        ; Flag is 0 for SYS-only, 1 for both
  2728. ;
  2729. MLA3:    CALL    SLOGIN        ; Log in path-specified user/disk
  2730. ;
  2731. MLA3RT:    CALL    SEARF        ; Look for file
  2732.     POP    H        ; Get ptr to next path entry
  2733.     JRZ    MLA0        ; Continue path search if search failed
  2734.                 ; Load if search succeeded
  2735. ;
  2736. ; File found -- perform system test and proceed if approved
  2737. ;
  2738. MLA4:    PUSH    H        ; Save pointer
  2739.     CALL    GETSBIT        ; Check system bit
  2740.     POP    H        ; Get pointer
  2741.     JRZ    MLA0        ; Continue if no match
  2742.     CALL    OPENF        ; Open file for input
  2743. ;
  2744. LOADADR    EQU    $+1        ; Memory load address (in-line code mod)
  2745.     LXI    H,TPA        ; Set start address of memory load
  2746. ;
  2747. MLA5:     IF    NOT MAKESPR    ; Can't reconcile the MVI if SPR
  2748.     MVI    A,ENTRY/256-1    ; Get high-order adr of just below CCP
  2749.      ENDIF
  2750. ;
  2751.      IF    MAKESPR        ; Do different way
  2752.     PUSH    B
  2753.     LXI    B,ENTRY
  2754.     MOV    A,B        ; Put high order address in A
  2755.     DCR    A        ; Minus 1
  2756.     POP    B        ; Restore B
  2757.      ENDIF
  2758. ;
  2759.     CMP    H        ; Are we going to overwrite the CCP?
  2760.     JRC    PRNLE        ; Error if so
  2761.     PUSH    H        ; Save address of next sector
  2762.     XCHG            ; In DE
  2763.     CALL    DMASET        ; Set DMA address for load
  2764.     LXI    D,FCBDN        ; Read next sector
  2765.     CALL    READ
  2766.     POP    H        ; Get address of next sector
  2767.     JRNZ    MLA6        ; Read error or EOF?
  2768.     LXI    D,128        ; Move 128 bytes per sector
  2769.     DAD    D        ; Point to next sector in HL
  2770.     JR    MLA5
  2771. ;
  2772. MLA6:    DCR    A        ; Load complete
  2773.     JZ    DLOGIN        ; Ok if zero, else fall thru to prnle
  2774. ;
  2775. ; Load error
  2776. ;
  2777. PRNLE:    CALL    PRINTC
  2778.     DB    'Ful','l'+80H
  2779.     CALL    DLOGIN        ; Restore current user/disk
  2780.     JMP    RESTRT        ; Restart zcmd
  2781. ;
  2782. ; The following routine will fetch HHMM from NUBYE/BYE5 (or your clock
  2783. ;  if BYCLOCK/BYTLOS is NO and CLOCK is YES) and display it as [hh:mm]
  2784. ;  in front of your du> prompt.
  2785. ;
  2786.      IF    BYCLOCK    AND (NOT BYTLOS) AND (NOT CLOCK)
  2787. TIME:    MVI    C,79
  2788.     CALL    BDOS        ; Get BYE's RTC address
  2789.     MOV    A,M        ; Get HH (it's in BCD)
  2790.     PUSH    H        ; Save address
  2791.     LXI    H,ANSHH        ; Storage location
  2792.     CALL    ASCII        ; Convert and store ascii
  2793.     POP    H        ; Get address back
  2794.     INX    H
  2795.     MOV    A,M        ; Get MM, also in bcd
  2796.     LXI    H,ANSMM        ; Storage location
  2797.     CALL    ASCII        ; Convert and store ascii
  2798.     LXI    H,TMSG
  2799.     JMP    PRIN1        ; And print it, return from prin1
  2800.      ENDIF
  2801. ;
  2802.      IF    CLOCK AND (NOT BYCLOCK) AND (NOT BYTLOS)
  2803. TIME:    RDCLOK            ; Predefined macro clock read code
  2804.      ENDIF
  2805. ;
  2806.      IF    (BYCLOCK AND (NOT BYTLOS)) OR CLOCK
  2807. ASCII:    PUSH    PSW        ; Save BCD pair
  2808.     RAR
  2809.     RAR
  2810.     RAR
  2811.     RAR
  2812.     ANI    0FH        ; Get MSB of BCD pair
  2813.     ADI    '0'        ; Make ASCII
  2814.     MOV    M,A        ; Store it
  2815.     INX    H        ; Point to next store location
  2816.     POP    PSW
  2817.     ANI    0FH        ; Get LSB of BCD pair
  2818.     ADI    '0'        ; Convert to ASCII
  2819.     MOV    M,A        ; Store it
  2820.     RET
  2821. ;
  2822. TMSG:    DB    '['
  2823. ANSHH:    DB    '00:'
  2824. ANSMM:    DB    '00] ',0
  2825.      ENDIF
  2826. ;
  2827. ; The following routine will display [Left:nn] or [On:nn], depending
  2828. ;  on your equate settings (BYTLOS and SHOW).  Normal users will be
  2829. ;  shown their time-left-on-system (i.e. [Left:nn]), while those with
  2830. ;  WHEEL privileges or unlimited time will be shown their time-on-system
  2831. ;  (i.e. [On:nn]). 
  2832. ;
  2833.      IF    BYTLOS AND (NOT    BYCLOCK) AND (NOT CLOCK)
  2834. TIME:    MVI    C,79
  2835.     CALL    BDOS        ; Get current time-on-system
  2836.     PUSH    PSW        ; And save it
  2837.     MVI    C,81
  2838.     MVI    E,255        ; Get maxtime allowed
  2839.     CALL    BDOS
  2840.     MOV    B,A        ; Put it in B
  2841.     ORA    A
  2842.     JRZ    TIME1        ; User has unlimited time
  2843.     LDA    WHLADR
  2844.     ORA    A
  2845.     JRNZ    TIME1        ; Wheel byte is on
  2846.     POP    PSW        ; TOS in A
  2847.     MOV    C,A        ; Now in C
  2848.     MOV    A,B        ; Maxtime in A
  2849.     SUB    C        ; Maxtime-TOS=TLOS
  2850.     LXI    H,TLOS        ; Storage area
  2851.     CALL    DEC8        ; Convert/store to ascii
  2852.     LXI    H,TLOSM
  2853.     CALL    PRIN1        ; Print first part
  2854.     LXI    H,TLOS2
  2855.     JMP    PRIN1        ; And second part, exit from prin1
  2856. ;
  2857. TIME1:    POP    PSW        ; Get TOS for wheel or unlimited time users
  2858. ;
  2859.      IF    NOT SHOW
  2860.     RET
  2861.      ENDIF
  2862. ;
  2863.      IF    SHOW
  2864.     LXI    H,TLOS1        ; Storage area
  2865.     CALL    DEC8        ; Convert/ store to ascii
  2866.     LXI    H,TLOSM1
  2867.     CALL    PRIN1        ; Print first part [On:xx 
  2868.     LXI    H,TLOS2
  2869.     JMP    PRIN1        ; second part, then exit from prin1    
  2870.      ENDIF
  2871. ;
  2872. TLOSM:    DB    '[Left:'
  2873. TLOS:    DB    '   ',0        ; Buffer for tlos or tos
  2874. ;
  2875.      IF    SHOW
  2876. TLOSM1:    DB    '[On:'
  2877. TLOS1:    DB    '   ',0        ; Buffer for tlos or tos
  2878.      ENDIF
  2879. ;
  2880. TLOS2:    DB    '] ',0
  2881. ;
  2882. ;-----
  2883. ;
  2884. ; DEC8 will convert an 8-bit binary number in a to three ASCII bytes.
  2885. ; HL points to the MSB location where the ASCII bytes will be stored.
  2886. ; Leading zeros are suppressed.
  2887. ;
  2888. DEC8:    PUSH    PSW
  2889.     PUSH    H
  2890.     XRA    A
  2891.     MOV    M,A        ; Clear destination
  2892.     INX    H
  2893.     MOV    M,A
  2894.     INX    H
  2895.     MOV    M,A
  2896.     POP    H
  2897.     POP    PSW
  2898.     PUSH    B
  2899.     PUSH    D
  2900.     MVI    E,0        ; Leading zero flag
  2901.     MVI    D,100
  2902. ;
  2903. DEC81:    MVI    C,'0'-1
  2904. ;JDEBª⌐dÆöñÆ媬äêv@b``@▐Σ@b`ö£åêèåpdv@ªΦ╥╪╪@VéêêêRH£╥∞@┬╚╔D╥Φ@─┬╞╓₧¼äXév@ñ╩┌┬╥▄╚╩ΣÜ₧¼éXåv@Ä╩Φ@b``^b`åáÆ'1'        ; Zero?
  2905.     JNC    DEC84        ; Yes
  2906.     MOV    A,E        ; Check flag
  2907.     ORA    A        ; Reset?
  2908.     MOV    A,C        ; Restore byte
  2909.     JZ    DEC85        ; Leading zeros are skipped
  2910. ;
  2911. DEC84:    MOV    M,A        ; Store it in buffer pointed at by HL
  2912.     INX    H        ; Increment storage location
  2913.     MVI    E,0FFH        ; Set zero flag
  2914. ;
  2915. DEC85:    MOV    A,D
  2916.     SUI    90        ; 100 to 10
  2917.     MOV    D,A
  2918.     MOV    A,B        ; Remainder
  2919.     JNC    DEC81        ; Do it again
  2920.     ADI    '0'        ; Make ASCII
  2921.     MOV    M,A        ; And store it
  2922.     POP    D
  2923.     POP    B
  2924.     RET
  2925.      ENDIF            ; BYTLOS AND NOT BYCLOCK
  2926. ;
  2927. ;-----
  2928. ;
  2929. ; Default path used for path command-search
  2930. ;
  2931.      IF    INTPATH
  2932. PATH:    IPATH            ; Macro defined up front
  2933. ;
  2934.      IF    WHEEL
  2935. WHLPTH:    DB    0,SYSUSR    ; Filled dynamically based on wheel byte
  2936.      ENDIF
  2937. ;
  2938.     DB    0        ; Terminating 0 for last pair
  2939.      ENDIF
  2940. ;
  2941. ; Stack area
  2942. ;
  2943.      IF    INTSTACK    ; Internal stack
  2944.     DS    48        ; Stack area
  2945. ;
  2946. STACK    EQU    $        ; Top of stack
  2947.      ENDIF
  2948. ;
  2949. ; The following will cause an error message to appear if the size of
  2950. ; ZCMD2 is over 2k bytes.
  2951. ;
  2952.      IF    NOT MAKESPR
  2953.      IF    ($ GT CCPLOC+800H)
  2954. ZCMDER1    EQU    NOVALU1        ;    *** WARNING ***
  2955. ZCMDER2    EQU    NOVALU2        ; ZCMD2 is larger than 2k
  2956.      ENDIF
  2957.      ENDIF
  2958. ;
  2959.     END
  2960.