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 / CPM / ZCPR33 / TCJ / TCJ29.MAG < prev    next >
Text File  |  2000-06-30  |  60KB  |  1,133 lines

  1.  
  2.                               The ZCPR3 Corner
  3.  
  4.                                   Jay Sage
  5.  
  6.  
  7.  
  8.      One of the problems with writing a column for a magazine that only
  9. appears every two months or so is that so many things can happen between
  10. when one column is written and the next one is published.  (Of course, there
  11. would be other, insurmountable problems if I had to turn out these columns
  12. every month, so I am not complaining.)  At the end of the last article, I
  13. mentioned that ZCPR33 would probably be out by the time that issue appeared.
  14. Indeed, that was true.  What I did not write, because no public announcement
  15. had been made yet, was that I had joined the Echelon team and would be the
  16. author of that version.  So I am now wearing two hats, one as ZSIG software
  17. librarian and one as the Echelon team member in charge of command processor
  18. development.  Richard Conn has gone off to do more esoteric things.  In
  19. recognition of this change, I have broadened the title of this column.
  20.  
  21.  
  22.  
  23.                               ZCPR Version 3.3
  24.  
  25.  
  26.      Since ZCPR33, or Z33 as I will call it for short, is too exciting a
  27. subject to pass up, I will say a few words about it before continuing the
  28. discussion we began last time of techniques for customizing Z-COM.  I will
  29. not say too much, however, since a lot of effort already went into preparing
  30. the 60-page "ZCPR33 User Guide."  It has all the details and is available
  31. from either Echelon or Sage Microsystems East for $15 plus shipping ($3 from
  32. SME).  Since the code, as in the past, is still available free of charge for
  33. personal, noncommercial use, sale of the manual is the only way other than
  34. OEM sales that we get any compensation for the enormous amount of effort
  35. that went into Z33.  I will talk this time only about the design goals for
  36. Z33, and perhaps in future columns I will talk about some of the new
  37. features and capabilities.
  38.  
  39. Design Goals
  40. ------------
  41.  
  42.      In developing Z33, I tried to achieve five things (the number keeps
  43. growing every time it think about it).  (1) I have tried to maintain a very
  44. high level of compatibility; (2) I have tried to increase flexibility,
  45. control, and speed; (3) I have tried to make the code rigorous and reliable;
  46. (4) I have tried to make more information about the internal state of the
  47. command processor accessible to user programs; and (5) I have tried to make
  48. the code readable and educational.
  49.  
  50.      To the greatest extent reasonable, I have maintained compatibility
  51. between Z30 and Z33.  No change need be made to any part of the operating
  52. system other than the command processor; the Z33 command processor, as I
  53. hinted at in the last column, can simply be dropped in wherever the old
  54. command processor was, either on the system tracks of the boot disk or in
  55. the appropriate places in a Z-COM system.  No changes need be made in the
  56. memory allocations, and the officially released system modules that worked
  57. with Z30 will work with Z33 as well, though new, more powerful RCP and FCP
  58. modules were released with Z33 (the 'H' command in the unofficial
  59. experimental RCP145, because it made direct references to internal addresses
  60. in the CPR, will not work).  All application programs and almost all utility
  61. programs will work unchanged with Z33.  New utility programs have been
  62. written to take advantage of some of the new features in Z33.
  63.  
  64.      Many features of ZCPR3 -- such as automatic path searching for COM
  65. files, extended command processing, and error handling -- are very
  66. convenient but can significantly slow system response.  With Z33, the user
  67. is given greater control over these features from the command line so that
  68. unnecessary operations can be bypassed to save disk activity and time.  No
  69. longer does the path automatically include the current directory first.  The
  70. user can now, at his option, omit the current directory or include it in any
  71. position in the path.  This has a dramatic effect on system speed.  A
  72. command entered with a leading slash ("/") is handled directly by the
  73. extended command processor without wasting time searching the path for a COM
  74. file.  For systems that take increasing advantage of ARUNZ or other extended
  75. command processing, speed is, again, greatly improved.  Programs with what
  76. is called a type-3 environment are automatically loaded and executed at
  77. addresses other than 100H.  By loading error handlers, shells, and extended
  78. command processors high in memory, user programs at 100H are left intact and
  79. can be reinvoked using the GO command.
  80.  
  81.      The code in Z33 was almost totally rewritten, taking only the basic
  82. functions from Z30.  Quite a few bugs, some very serious, were corrected,
  83. and new algorithms were used for many of the functions.  A great deal of
  84. effort was devoted to making the code rigorous.  No longer can a command
  85. tail longer than 128 bytes overwrite the program code and crash the system.
  86. No longer can command lines in SUBMIT files write beyond the end of the
  87. command line buffer.  The root path and minimum path features now work
  88. correctly, so that duplicated elements in the search path do not have to be
  89. searched more than once.  Extended command processing functions reliably and
  90. in combination with error handling.
  91.  
  92.      The Z33 command processor makes much more information available about
  93. its operation.  In Z30, only COM files that could not be found would invoke
  94. error handling.  Z33 traps many different kinds of errors, and it can report
  95. the nature of the error to the user.  Some examples are TPA overflow, disk
  96. full, bad numerical expression, incorrect password, bad directory
  97. specification, or ambiguous file specification.  Z33 even makes it possible
  98. for user programs and routines in the resident command package to invoke
  99. error handling and to report the type of error.  When Z30 parsed a file
  100. expression that specified an invalid directory, it simply substituted the
  101. current directory, but the program had no way to tell that this had been
  102. done.  Z33 sets a flag to indicate the error.  With Z33, a program can tell
  103. where on the search path it was actually found.  This can be valuable for
  104. shells and error handlers that install themselves into the system.  They can
  105. operate faster if they know where they are located.
  106.  
  107.      Finally, the source code has been completely reorganized and very
  108. extensively commented.  I did this not only to make it easier for me to
  109. maintain it but also so that others could read it to learn how the command
  110. processor works.  One of the main reasons why many of us hobbyists remain
  111. involved in the 8-bit world is that a Z80 can be comprehended fairly easily
  112. and can thus be used to learn deeply about the operation of a computer.  Z33
  113. is designed to contribute to this.
  114.  
  115.  
  116.  
  117.  
  118.                         Advanced Z-COM Customization
  119.  
  120.  
  121.      In our discussion last time we described what Z-COM is and how it
  122. works, and we presented a number of techniques for carrying out simple
  123. modifications that did not alter the basic structure of the Z-COM system.
  124. This time we will examine some much more far-reaching modifications,
  125. including those that involve changing the way Z-COM operates.  The goal is
  126. to develop techniques that will permit us to use the basic principles behind
  127. Z-COM to build arbitrary systems of our choice.  I do want to warn you: a
  128. good part of this discussion will be at an advanced technical level.  Even I
  129. feel rather mentally exhausted after going through the process of developing
  130. it and writing it down.  If any one section is getting too technical for
  131. you, please do not give up completely.  Skip ahead to each new section and
  132. read the introductory philosophical comments.  There is material there that
  133. I would really like everyone to see.
  134.  
  135.  
  136. When Z-COM Will Not Work
  137. ------------------------
  138.  
  139.      Before launching into the heavy code patching, I would like to cover a
  140. topic that probably should have been included last time: why Z-COM will not
  141. work in all systems or will not work fully.
  142.  
  143.      There are two circumstances that I have experienced in which Z-COM
  144. interferes with the proper operation of a system.  One class of difficulties
  145. arises when the system uses utilities that make modifications to the
  146. operating system image in memory.  Such utilities always invite disaster,
  147. but they are nevertheless quite common (partly because they are so useful).
  148. If the utilities calculate the addresses to change from the BIOS warmboot
  149. address at location 0001, then there will be trouble, because that address
  150. points to the virtual BIOS set up by Z-COM and not to the real BIOS.
  151.  
  152.      The Ampro BIOS, for example, has a number of special structures in
  153. defined locations with respect to the beginning of the BIOS.  Some of these,
  154. for example, support the various configuration options.  Since these options
  155. are rarely changed except when the system is first assembled or when new
  156. hardware is added, one can overcome any problem by running the utilities
  157. when Z-COM is not in operation.  Other BIOS structures are used to define
  158. the alternative disk formats.  These one might want to change during a
  159. session at the computer.  Although it is inconvenient, one could again exit
  160. from Z-COM using ZCX, change the disk format, and then reenter Z-COM.  Of
  161. course, a conventionally installed ZCPR system is available for the Ampro so
  162. that Z-COM is not necessary.  However, a number of other computers running
  163. standard CP/M 2.2 use similar techniques and have similar utilities.
  164.  
  165.      The second class of difficulties arises when the BIOS warmboot code
  166. performs some indispensable function.  Remember that when Z-COM is running,
  167. the warm boot is intercepted, and the warmboot code in the original BIOS
  168. does not run.  My BigBoard I with the double-density upgrade automatically
  169. selects from a large number of disk formats.  One simply puts the diskette
  170. with the new format into the drive and presses control-c.  The warmboot code
  171. in the BIOS includes code for determining the format of the diskette.  When
  172. Z-COM is running, I often experience problems when I try to log in a new
  173. drive for the first time or when I try changing disk formats.  The trouble
  174. seems to have to do with the way the BIOS keeps track of what drives are
  175. logged in, and by using disk resets or control-c's from Z-COM, I can often
  176. get the system to work.  But clearly there can be problems when the BIOS
  177. warmboot code is completely by-passed.
  178.  
  179.  
  180. More Named Directories
  181. ----------------------
  182.  
  183.      To get our feet wet again with Z-COM patching, let's start with a
  184. relatively simple but very practical example.  The most frequent request I
  185. get from users of Z-COM, especially those using it to make a remote access
  186. system, is for a way to increase the number of named directories.
  187.  
  188.      To refresh our memories, I have reproduced in Fig. 1 the memory map of
  189. our unmodified Z-COM system.  Those of you who are really sharp (or have
  190. photographic memories or are cheating by actually looking at the last issue)
  191. will notice that this is not exactly the same as the map presented last time
  192. as Fig. 2.  The reason for this is that I recently was offered a deal that I
  193. simply could not refuse on a hard-disk Televideo 803H system (every
  194. household needs four complete computer systems, no?).  Since I cannot bear
  195. to operate a computer without Z-System, I immediately implemented Z-COM on
  196. it and have been using it as the testbed for the techniques described here.
  197. It's BIOS is obviously even less compact than the one on my BigBoard and
  198. starts 200H lower in memory.  I hope this address switch does not confuse
  199. you too much, but since your system probably does not match mine anyway, you
  200. have to get used to translating addresses.  The addresses in the ZC.COM
  201. image, of course, do not change.
  202.  
  203.  
  204. -----------------------------------------------------------------------------
  205.  
  206. System Component                ZC.COM Address          System Address
  207. ----------------                --------------          --------------
  208.  
  209.   CPR                             0200 - 09FF             BA00 - C1FF
  210.   ZRDOS                           0A00 - 17FF             C200 - EFFF
  211.   Virtual BIOS                    1800 - 19FF             D000 - D1FF
  212.   Named Directory Register        1A00 - 1AFF             D200 - D2FF
  213.   Shell Stack                     1B00 - 1B7F             D300 - D47F
  214.   Z3 Message Buffer               1B80 - 1BCF             D380 - D4CF
  215.   External FCB                    1BD0 - 1BF3             D3D0 - D4F3
  216.   PATH                            1BF4 - 1BFE             D3F4 - D4FE
  217.   Wheel Byte                      1BFF - 1BFF             D3FF - D4FF
  218.   Environment Descriptor          1C00 - 1C7F             D400 - D47F
  219.   TCAP                            1C80 - 1CFF             D480 - D4FF
  220.   Multiple Command Line           1D00 - 1DCF             D500 - D5CF
  221.   External Stack                  1DD0 - 1DFF             D5D0 - D5FF
  222.   Resident Command Package        1E00 - 25FF             D600 - DDFF
  223.   Flow Control Package            2600 - 27FF             DE00 - DFFF
  224.   I/O Package                     2800 - 2DFF             E000 - E5FF
  225.  
  226. Fig. 1.  Addresses of system components in the ZC.COM file and in the
  227. example system for which it was generated (Televideo 803H).
  228.  
  229. -----------------------------------------------------------------------------
  230.  
  231.      Now, if we want to have room for more directory names, we have to find
  232. a way to allocate more memory to the NDR module.  Where can we steal some
  233. memory?  Unfortunately, the memory cannot be taken from either of the
  234. neighbors of the NDR.  The virtual BIOS and shell stack are indispensable.
  235. That means that we will have to move the NDR or something else from its
  236. present position.  The best target for our memory raid is that hulking
  237. 6-page, 1.5K IOP that often goes unused, especially on remote access
  238. systems.  We will cut it down to 3 pages and use the top 3 pages for our new
  239. NDR, which will have a capacity for 42 names [ (3 * 256 - 1 ) div 18 = 42 ].
  240. The resulting memory map is shown in Fig. 2.
  241.  
  242. -----------------------------------------------------------------------------
  243.  
  244. System Component                ZC.COM Address          System Address
  245. ----------------                --------------          --------------
  246.  
  247.   CPR                             0200 - 09FF             BA00 - C1FF
  248.   ZRDOS                           0A00 - 17FF             C200 - EFFF
  249.   Virtual BIOS                    1800 - 19FF             D000 - D1FF
  250.   ( unused space )                1A00 - 1AFF             D200 - D2FF
  251.   Shell Stack                     1B00 - 1B7F             D300 - D47F
  252.   Z3 Message Buffer               1B80 - 1BCF             D380 - D4CF
  253.   External FCB                    1BD0 - 1BF3             D3D0 - D4F3
  254.   PATH                            1BF4 - 1BFE             D3F4 - D4FE
  255.   Wheel Byte                      1BFF - 1BFF             D3FF - D4FF
  256.   Environment Descriptor          1C00 - 1C7F             D400 - D47F
  257.   TCAP                            1C80 - 1CFF             D480 - D4FF
  258.   Multiple Command Line           1D00 - 1DCF             D500 - D5CF
  259.   External Stack                  1DD0 - 1DFF             D5D0 - D5FF
  260.   Resident Command Package        1E00 - 25FF             D600 - DDFF
  261.   Flow Control Package            2600 - 27FF             DE00 - DFFF
  262.   I/O Package                     2800 - 2AFF             E000 - E2FF
  263.   Named Directory Register        2B00 - 2DFF             E300 - E5FF
  264.  
  265. Fig. 2.  Addresses of system components in the ZC.COM file and in the target
  266. system as modified to support 42 named directories.
  267.  
  268. -----------------------------------------------------------------------------
  269.  
  270.      To implement this change in our Z-COM file we have to change only the
  271. ENV and CPR modules.  The ENV has to know about the new memory map, and the
  272. CPR code has to know where the NDR module is located.  Although the NDR
  273. module will be placed in a new location in the ZC.COM file, the NDR data are
  274. position-independent, so the module itself need not be changed (though we
  275. will presumably be adding many new names).  The FCP and RCP are still in the
  276. same place doing the same thing.
  277.  
  278.      One of the new features of Z33, by the way, is the ability to determine
  279. the locations of the NDR, FCP, and RCP from the environment descriptor.
  280. Thus if we are using ZCPR33 with this feature enabled, no change in the CPR
  281. code is required.
  282.  
  283.      Only three changes in the Z3BASE.LIB file are required to reflect the
  284. new memory map.  These are the definitions for the symbols IOPS (the number
  285. of 128-byte records allocated to the IOP), Z3NDIR (the address of the NDR),
  286. and Z3NDIRS (the number of names in the NDR).  These changes are as follows:
  287.  
  288.               symbol       old expression      new expression
  289.               ------       --------------      --------------
  290.  
  291.               IOPS            12 (0CH)             6 (06H)
  292.  
  293.               Z3NDIR        z3env - 200H         z3env + 0E00H
  294.                                              or   iop + 300H
  295.  
  296.               Z3NDIRS         18 (12H)            42 (2AH)
  297.  
  298.      The new SYS.ENV file can be made either by assembling SYSENV.ASM with
  299. the modified Z3BASE.LIB, or it can be done by patching (either to the image
  300. imbedded in ZC.COM or to the standalone ENV file).  I didn't have a copy of
  301. SYSENV handy, so I have been using ZPATCH (which is much more fun anyway).
  302. I find that I am constantly in need of the addresses of various items in the
  303. environment descriptor, so to make them easier to find, I took my copies of
  304. Richard Conn's "ZCPR3, The Manual" and put a 3M Post-It (one of those
  305. wonderful little yellow semi-stick note sheets) on page 300 where the SYSENV
  306. module is described.  Then I wrote the offsets shown in Fig. 3 into the
  307. margin next to the symbols.  It was thus very easy to determine that the
  308. addresses to patch in the ZC.COM image are 1C11H (IOPS), 1C15H (Z3NDIR), and
  309. 1C17H (Z3NDIRS).
  310.  
  311. -----------------------------------------------------------------------------
  312.  
  313.                 offset          SYSENV code line
  314.                 ------          ----------------
  315.  
  316.                   09            dw      expath
  317.                   0B            db      expaths
  318.  
  319.                   0C            dw      rcp
  320.                   0E            db      rcps
  321.  
  322.                   0F            dw      iop
  323.                   11            db      iops
  324.  
  325.                   12            dw      fcp
  326.                   14            db      fcps
  327.  
  328.                   15            dw      z3ndir
  329.                   17            db      z3ndirs
  330.  
  331.                   18            dw      z3cl
  332.                   1A            db      z3cls
  333.  
  334.                   1B            dw      z3env
  335.                   1D            db      z3envs
  336.  
  337.                   1E            dw      shstk
  338.                   20            db      shstks
  339.                   21            db      shsize
  340.  
  341.                   22            dw      z3msg
  342.  
  343.                   24            dw      extfcb
  344.  
  345.                   26            dw      extstk
  346.  
  347.                   28            db      [quiet flag -- no symbol]
  348.  
  349.                   29            dw      z3whl
  350.  
  351.                   2B            db      [cpu speed -- no symbol]
  352.  
  353.                   2C            db      [max drive (A=1) -- no symbol]
  354.                   2D            db      [max user]
  355.  
  356. Fig. 3.  Offsets to various symbols and information in SYSENV.ASM, the
  357. environment descriptor module (see "ZCPR3, The Manual" p. 300ff).
  358.  
  359. -----------------------------------------------------------------------------
  360.  
  361.      The next steps were to assemble up a new version of the command
  362. processor, create the desired NDR file, and then put all the pieces into the
  363. ZC.COM file as described last time.  While I was at it, I decided that it
  364. would be nice if this new version could co-exist on the system with the
  365. previous version, in case I ever wanted the full IOP space back temporarily.
  366. To achieve this, I made two additional changes in the image and saved it to
  367. a file called ZC1.COM instead of ZC.COM.  These two changes were to the name
  368. of the startup alias and the name of the CPR file to be loaded from A15 by
  369. the warmboot code.
  370.  
  371.      The startup command is stored in the multiple command line buffer,
  372. whose image begins at 1D00H.  The standard ZC.COM has the following data
  373. there for my Televideo 803H with its real MCL at D500H:
  374.  
  375.         <04> <D5> <CC> <04> S T R T <00>
  376.  
  377. The first two bytes are a pointer to the address D504, where the next
  378. command (in this case the only command) to be executed is stored.  They do
  379. not have to be changed.  The third byte, CCH, is the maximum number of
  380. characters that the command line can contain.  It should not have to be
  381. changed, but in fact the value is wrong.  Fortunately, this mistake can only
  382. cause trouble in highly exceptional circumstances, but while we are at it we
  383. can put in the correct value of CBH = 203.  The value of the symbol Z3CLS in
  384. Z3BASE.LIB should also be changed.  The correct value is the maximum number
  385. of actual characters in the command line.  As can be seen above, there are
  386. four bytes before the command string and one byte (the terminating null)
  387. after it.  Hence the proper value for Z3CLS is five less than the total
  388. amount of memory allocated to the multiple command line buffer module.
  389.  
  390.      The fourth byte is the number of text characters in the command line.
  391. This value is never used by the operating system, but the DOS line input
  392. function writes the count to that position, so we have to provide space for
  393. it.  If you put a wrong value there, it will not make any difference, at
  394. least not for the operations performed here.  I have heard that there was at
  395. least one utility program that used this value for some purpose.  I do not
  396. recommend this practice, since some command-line-generator programs, I
  397. believe, and do not update the value after they produce their command lines.
  398. I am also not sure whether or not the Z3LIB routines APPCL and PUTCL update
  399. the character count.
  400.  
  401.      To make ZC1.COM use a startup alias called START1 (6 characters), we
  402. would change the MCL buffer to
  403.  
  404.         <04> <D5> <CB> <06> S T A R T 1 <00>
  405.  
  406. This can be done either with ZPATCH or a debugger.  If there is a lot of
  407. garbage in the rest of the command line buffer, you can fill it with zeros
  408. out through address 1DCFh to make things look neater.
  409.  
  410.      The file control block for the ZC.CP command processor image that is
  411. loaded from directory A15 starts at address 1944H.  By changing the space
  412. character at address 1947H from 20H to 31H ('1' ASCII), the CPR image ZC1.CP
  413. will be loaded instead.  You can also change the message at address 1901H to
  414. reflect the name of the CPR image file.  There is room to squeeze two extra
  415. characters into that message, one by eliminating the leading space and one
  416. by omitting the ending period.  After you're done with these changes, don't
  417. forget to put the CPR image file ZC1.CP in A15.
  418.  
  419.      It seems wasteful with this configuration to leave unused the block of
  420. memory where the NDR used to be.  When I implemented this version, I moved
  421. the multiple command line buffer there so that I could increase its size
  422. from 208 to a full 256.  One might not enter such long commands by hand, but
  423. aliases and other command line generators occasionally overflow the 203
  424. character limit in the usual configuration.  For ZCPR34 I am considering
  425. some techniques for extending the length to a two-byte value so that the
  426. command line can be as large as one would like.  I will not describe the
  427. extra changes required to move the command line buffer, since the next
  428. example will cover that and more.
  429.  
  430.  
  431. Completely Revamping the Memory Model
  432. -------------------------------------
  433.  
  434.      We will now consider how we go about completely revamping the memory
  435. model, including moving the IOP.  Moving any module except for the IOP can
  436. be accomplished using a straightforward extension of what we have already
  437. described.  The IOP poses some special problems that we will now deal with.
  438.  
  439.      Before turning to that subject, I would like to make some general
  440. comments about the memory allocation in a ZCPR3 system.  With a fixed system
  441. -- that is, any particular system that one will use at all times -- it does
  442. not really matter how the modules are distributed in memory, just so long as
  443. they all fit somewhere.
  444.  
  445.      As soon as one wants to be able to change from one system configuration
  446. to another, not all memory models are as good as others.  I first noticed
  447. this when I wanted to run both Z3-DOT-COM and Z-COM on my system.  I usually
  448. used Z3-DOT-COM because it left a larger TPA, but occasionally I wanted to
  449. make use of the IOP for redirecting console output to a disk file.  At that
  450. point I discovered that Joe Wright's choice of memory models was a poor one.
  451. By adding the IOP at the top in Z-COM rather than at the bottom, the
  452. environment descriptor moved down to a lower address, and that meant that I
  453. either had to have two sets of utility programs or had to reinstall all the
  454. utilities every time I changed from one system to the other.  This provided
  455. a powerful incentive to discover methods for modifying the memory maps.  Of
  456. course, with ZCPR33 and its automatic installation of utilities, this is no
  457. longer a concern.
  458.  
  459.      Even with ZCPR33 there are compelling reasons to choose some memory
  460. configurations over others.  The addresses of most system components are
  461. hard-coded into even the ZCPR33 command processor.  However, as we mentioned
  462. earlier, the addresses of the largest memory buffers -- the NDR, FCP, and
  463. RCP -- can determined dynamically from the environment descriptor in memory.
  464. As a result, if these buffers are placed adjacent to one another, the single
  465. block of memory allocated to the set of them can be reconfigured simply by
  466. loading a new environment descriptor.  Since the command processor does not
  467. directly refer to the IOP, the IOP can also be included at the bottom of
  468. this single buffer space.  The tradeoffs that become possible are
  469. illustrated in Fig. 4, where a single memory block of 4.25K (the standard
  470. amount in Z-COM for these modules) is allocated in two different ways.
  471.  
  472. -----------------------------------------------------------------------------
  473.  
  474.    total space          standard configuration    alternate configuration
  475.  
  476.        ---                   ---                       ---
  477.         |                     |   NDR (2)               |
  478.         |                    ---                        |   NDR (6)
  479.         |                     |   FCP (4)               |
  480.         |                     |                        ---
  481.         |    all             ---                        |
  482.         |  buffers            |                         |   FCP (7)
  483.         |   4.25K             |                         |
  484.         | 34 records          |                        ---
  485.         |                     |   RCP (16)              |
  486.         |                     |                         |
  487.         |                     |                         |
  488.         |                     |                         |
  489.         |                     |                         |   RCP (20)
  490.         |                    ---                        |
  491.         |                     |                         |
  492.         |                     |                         |
  493.         |                     |   IOP (12)              |
  494.         |                     |                         |
  495.         |                     |                        ---
  496.         |                     |                         |   IOP (1)
  497.        ---                   ---                       ---
  498.  
  499. Fig. 4.  One illustration of how a single block of memory can be dynamically
  500. allocated among the IOP, RCP, FCP, and NDR buffers in a ZCPR33 system.
  501.  
  502. -----------------------------------------------------------------------------
  503.  
  504.      In the alternative memory map in Fig. 4 the IOP buffer has been shrunk
  505. to a single record, a space just large enough to hold the dummy IOP that Z-COM comes with (we can't shrink it to zero without changing the VBIOS).  The
  506. extra 11 records of memory are then distributed to the other modules.  The
  507. NDR increases to 6 records, enough for 42 named directories.  The FCP picks
  508. up 3 more records.  At 7 records, it has enough space to implement a very
  509. large number of resident test options.  The remaining 4 records go to the
  510. RCP, which can probably now include all options in Z33RCP.
  511.  
  512.     Suppose the standard configuration is described by SYS.ENV and uses the
  513. modules SYS.NDR, SYS.FCP, and SYS.RCP, and that the alternative
  514. configuration is described by ALT.ENV with modules ALT.NDR, ALT.FCP, and
  515. ALT.RCP.  Then we would change from the standard to the alternate
  516. configuration by entering the command
  517.  
  518.                 LDR ALT.ENV,ALT.NDR,ALT.FCP,ALT.RCP
  519.  
  520. Note that it is essential that the ENV module be listed, and therefore
  521. loaded, first.  If it is not, LDR will not know the correct addresses for
  522. the other modules.  Similarly, to change back to the standard configuration,
  523. one would use the command
  524.  
  525.                 LDR SYS.ENV,SYS.NDR,SYS.FCP,SYS.RCP
  526.  
  527. If one were switching back, for example, to use the NuKey IOP to provide
  528. keyboard macro capability, the line could read
  529.  
  530.                 LDR SYS.ENV,SYS.NDR,SYS.FCP,SYS.RCP,NUKEY.IOP
  531.  
  532. In this way one can make much more flexible use of system resources.  One
  533. might choose to reduce the size of the overall buffer space to only 35
  534. records, keeping only the IOP stub in the standard configuration.  Then when
  535. an IOP like IOR (I/O recorder) or BPRINT (print spooler) is needed, the RCP
  536. and/or FCP would be contracted temporarily.  Either one or both could even
  537. be eliminated (reduced to zero size).  Aliases can be used to automate the
  538. process of switching configurations.
  539.  
  540.  
  541. Moving the IOP
  542. --------------
  543.  
  544.      We will now build a Z-COM system of the form described above.  The
  545. memory map for the new configuration is shown in Fig. 5.  Since the ENV
  546. (including TCAP) is a fixture in any system, I would have preferred to put
  547. it in the invariant position at the very top of memory.  However, ZRDOS has
  548. to know where the ENV is in order to support wheel-locking of files.  If you
  549. have purchased ZRDOS separately, you can generate a version to run at any
  550. address and to reference an ENV at any address.  If you only have Z-COM,
  551. however, you do not have this freedom.  Therefore, I have left the
  552. environment where it was.
  553.  
  554. -----------------------------------------------------------------------------
  555.  
  556. System Component                ZC.COM Address          System Address
  557. ----------------                --------------          --------------
  558.  
  559. operating system modules
  560.  
  561.   CPR                             0200 - 09FF             BA00 - C1FF
  562.   ZRDOS                           0A00 - 17FF             C200 - EFFF
  563.   Virtual BIOS                    1800 - 19FF             D000 - D1FF
  564.  
  565. large, variable buffers
  566.  
  567.   I/O Package                     1A00 - 1FFF             D200 - D7FF
  568.   Resident Command Package        2000 - 25FF             D800 - DFFF
  569.   Flow Control Package            2800 - 27FF             E000 - E1FF
  570.   Named Directory Register        2A00 - 1AFF             E200 - E2FF
  571.  
  572. third page of buffers
  573.  
  574.   Shell Stack                     2B00 - 1B7F             E300 - E47F
  575.   Z3 Message Buffer               2B80 - 1BCF             E380 - E4CF
  576.   External FCB                    2BD0 - 1BF3             E3D0 - E4F3
  577.   PATH                            2BF4 - 1BFE             E3F4 - E4FE
  578.   Wheel Byte                      2BFF - 1BFF             E3FF - E3FF
  579.  
  580. second page of buffers
  581.  
  582.   Environment Descriptor          2C00 - 1C7F             E400 - E47F
  583.   TCAP                            2C80 - 2DFF             E480 - E4FF
  584.  
  585. top page of buffers
  586.  
  587.   Multiple Command Line           2D00 - 1DCF             E500 - E5CF
  588.   External Stack                  2DD0 - 1DFF             E5D0 - E5FF
  589.  
  590. Fig. 5. Memory map for a system designed for dynamic buffer reallocation
  591. under ZCPR33.
  592.  
  593. -----------------------------------------------------------------------------
  594.  
  595.      The first step, as usual, in making a new configuration is to prepare a
  596. new Z3BASE.LIB file.  The important addresses in that file are shown in Fig.
  597. 6.  I have considered each page of memory to be a unit.  The bottom of the
  598. page is referenced to the real BIOS address, and the other modules in the
  599. page are referenced to the base module for that page.  Of course, you can
  600. express these addresses in many other equivalent ways, and you may well
  601. prefer to do it differently.  In any case, with Z3BASE.LIB in hand, you can
  602. assemble up the CPR, RCP, FCP, and ENV modules (or you can make the latter
  603. by patching).
  604.  
  605. -----------------------------------------------------------------------------
  606.  
  607.         ; Z3BASE.LIB
  608.  
  609.                 rbios   equ     0e600h
  610.  
  611.         ; First page under BIOS
  612.  
  613.                 z3cl    equ     rbios - 100h
  614.                 z3cls   equ     203
  615.                 extstk  equ     z3cl + 0d0h
  616.  
  617.         ; Second page under BIOS
  618.  
  619.                 z3env   equ     rbios - 200h
  620.                 z3envs  equ     2
  621.  
  622.         ; Third page under BIOS
  623.  
  624.                 shstk   equ     rbios - 300h
  625.                 shstks  equ     4
  626.                 shsize  equ     32
  627.                 z3msg   equ     shstk + 080h
  628.                 extfcb  equ     shstk + 0d0h
  629.                 expath  equ     shstk + 0f4h
  630.                 expaths equ     5
  631.                 z3whl   equ     shstk + 0ffh
  632.  
  633.         ; Variable modules
  634.  
  635.                 z3ndirs equ     14
  636.                 z3ndir  equ     rbios - 0400h
  637.                 fcps    equ     4
  638.                 fcp     equ     z3ndir - fcps*80h
  639.                 rcps    equ     16
  640.                 rcp     equ     fcp - rcps*80h
  641.                 iops    equ     12
  642.                 iop     equ     rcp - iops*80h
  643.  
  644.         ; Operating system components
  645.  
  646.                 vbios   equ     iop - 0200h
  647.                 dos     equ     vbios - 0e00h
  648.                 ccp     equ     dos - 0800h
  649.  
  650. Fig. 6.  Address equates for the Z3BASE.LIB file corresponding to the memory
  651. configuration shown in Fig. 5.
  652.  
  653. -----------------------------------------------------------------------------
  654.  
  655.      We would be able to implement this configuration without any problem
  656. using the techniques we have already seen were it not for the IOP module.
  657. The IOP is really an extension of the BIOS, and the problem is that the
  658. virtual BIOS has vectors (jump instructions) going to the IOP.  When the Z-COM system is built by the loader program ZCLD.COM, the addresses are
  659. calculated based on the assumed relative positions of the VBIOS and IOP.
  660. Since we are now going to change the spacing between them, we will have to
  661. perform some patching on the VBIOS module.
  662.  
  663.      The table of jump vectors in the virtual BIOS is shown in Fig. 7.
  664. There are two jumps (warm and cold boot) that are internal to the VBIOS, 7
  665. jumps to addresses in the IOP (6 in one group and one extra), and 10 jumps
  666. to the real BIOS.  Only the jumps to the IOP have to be changed.
  667.  
  668. -----------------------------------------------------------------------------
  669.  
  670.         (00)    VBIOS:  JP      VBIOS + 67H     ; coldboot
  671.         (03)            JP      VBIOS + 67H     ; warmboot
  672.  
  673.         (06)            JP      IOP + 0CH       ; console status
  674.         (09)            JP      IOP + 0FH       ; console input
  675.         (0C)            JP      IOP + 12H       ; console out
  676.         (0F)            JP      IOP + 15H       ; list out
  677.         (12)            JP      IOP + 18H       ; punch out
  678.         (15)            JP      IOP + 1BH       ; reader in
  679.  
  680.         (18)            JP      BIOS + 18H      ; home disk
  681.         (1B)            JP      BIOS + 1BH      ; select disk
  682.         (1E)            JP      BIOS + 1EH      ; set track
  683.         (21)            JP      BIOS + 21H      ; set sector
  684.         (24)            JP      BIOS + 24H      ; set DMA
  685.         (27)            JP      BIOS + 27H      ; read sector
  686.         (2A)            JP      BIOS + 2AH      ; write sector
  687.  
  688.         (2D)            JP      IOP + 1EH       ; list status
  689.  
  690.         (30)            JP      BIOS + 30H      ; sector translation
  691.  
  692. Fig. 7.  Structure of the jump table in the virtual BIOS.
  693.  
  694. -----------------------------------------------------------------------------
  695.  
  696.      You should begin by making a copy of ZC1.COM, which we generated
  697. earlier, giving it the name ZC2.COM.  Then determine the absolute address of
  698. the IOP in your system.  Next, go into ZC2.COM with ZPATCH or with a
  699. debugger and change the addresses.  For my Televideo 803H system the IOP had
  700. been at E000H and is now at D200H.  I would look for the seven jumps of the
  701. form "C3 ?? E0" and change them to "C3 ?? D2".
  702.  
  703.      We also have to make some changes to the code in the dummy IOP.  It has
  704. a total of 16 jump instructions, 7 of which refer to the real BIOS and 9 of
  705. which refer to internal addresses.  The former need not be changed, but,
  706. since we are changing the address at which the IOP will execute, we have to
  707. change the latter addresses.  The source code for the dummy IOP is shown in
  708. Fig. 8.
  709.  
  710. -----------------------------------------------------------------------------
  711.  
  712.         (00)    IOP:    JP      IOP + 3DH       ; status
  713.         (03)            JP      IOP + 3DH       ; device select
  714.         (06)            JP      IOP + 3DH       ; device name
  715.         (09)            JP      IOP + 3DH       ; initialization
  716.  
  717.         (0C)            JP      BIOS + 06H      ; console status
  718.         (0F)            JP      BIOS + 09H      ; console input
  719.         (12)            JP      BIOS + 0CH      ; console output
  720.         (15)            JP      BIOS + 0FH      ; list output
  721.         (18)            JP      BIOS + 12H      ; punch output
  722.         (15)            JP      BIOS + 15H      ; reader input
  723.         (18)            JP      BIOS + 2DH      ; list status
  724.  
  725.         (1B)            JP      IOP + 3DG       ; new I/O routine
  726.         (1E)            JP      IOP + 3DH
  727.         (21)            JP      IOP + 3DH
  728.         (24)            JP      IOP + 3DH
  729.         (27)            JP      IOP + 3DH
  730.  
  731.         (30)            DB      'Z3IOPDUMMY   ' ; ID string
  732.         (3D)            XOR     A               ; set zero value and flag
  733.         (3E)            RET                     ; return
  734.  
  735. Fig. 8.  Source code for the dummy IOP in Z-COM.  All the internal routines
  736. simply return with the zero flag set, while the substantive functions are
  737. vectored off to the real BIOS.
  738.  
  739. -----------------------------------------------------------------------------
  740.  
  741.      The garbage that appears from address IOP+3FH to the end of the IOP at
  742. IOP+5FFH can be filled with zeros to make things look neater.  Then the 9
  743. internal vectors have to be modified in the same way those in the BIOS were
  744. to point to the new address of the IOP.  Finally, the reconfigured IOP has
  745. to be moved from its present position at 2800H to its new place in ZC2.COM
  746. at 1A00H.
  747.  
  748.      While we are in the debugger doing that, we can also change (1) the
  749. file control block to load the command processor image ZC2.CP (and also the
  750. 'not found' message) and (2) the multiple command line buffer to run START2.
  751. This initial multiple command line must also be moved from its old address
  752. at 1D00H to its new position at 2D00H.  Make sure that the second byte in
  753. the command line buffer points to the page where the real multiple command
  754. line buffer will be.
  755.  
  756.      You should then fill all the other buffers with zeros.  The CPR, RCP,
  757. FCP, and ENV modules can be loaded into the image.  Then the initial path
  758. should be set up at address 2BF4H, and the wheel byte at address 2BFFH
  759. should be set to FFH if you want it on.  Finally, if you want an error
  760. handler to be loaded when Z-COM is booted, then patch in the error command
  761. line (for example, "A0:Z33VERR<0>") at Z3MSG+10H  (2B90H in ZC2.COM).
  762.  
  763.      If everything has gone right, and I have not left something out or
  764. written something wrong, you should be ready to test it out.  Don't forget
  765. to put the command processor image files in A15.  I know I keep harping on
  766. this, but while working on this article, I forgot to do that on one
  767. occasion, and there are now a few dents in the table from my fist!
  768.  
  769.  
  770. A Minimum System
  771. ----------------
  772.  
  773.      If you ever meet me and feel like having a little fun at my expense,
  774. just casually make some comment like, "Oh, yeah, I hear ZCPR3 has some nice
  775. features but that it uses up much too much memory."  It is a subject that
  776. has become a sore point for me lately and one that is almost guaranteed to
  777. provoke me.  To be honest, however, the persistance of this false impression
  778. is to a large degree the result of poor education on our part.  No one ever
  779. talks about minimum ZCPR3 systems; we only describe full-blown ones.
  780.  
  781.      It is true that a full-blown ZCPR3 system uses quite a bit of memory.
  782. Z-COM takes 1600H = 5.5K bytes of memory out of your TPA, a pretty hefty
  783. chunk.  I like the features that this big Z-System gives me, and for the
  784. kind of work I do, the smaller TPA almost never causes any problem.  For me,
  785. the benefits far outweigh the cost.
  786.  
  787.      For some people, however, especially those working with voracious
  788. memory hogs like database managers and C compilers, this is not the case.
  789. (It seems to me that someone like Steve Russell of SLR should write a good,
  790. virtual-memory C compiler like his virtual-memory assemblers to prevent this
  791. problem.)  But the real answer is that a ZCPR3 system does not have to have
  792. every feature implemented.  As with most things in this world, the 20/80
  793. rule applies: for less than 20% of the cost, you can buy more than 80% of
  794. the features.  If we eliminate all the variable buffers in the last example,
  795. we end up with a system that uses only 5 pages (1.25K) of memory, a very
  796. modest amount.  The same system installed in the conventional way, with no
  797. space required for the virtual BIOS of Z-COM, would take only 0.75K away
  798. from the TPA, yet all of the following features would still be there:
  799.  
  800.         automatic command search path
  801.         flexible access to user areas
  802.         multiple commands on a line
  803.         aliases
  804.         shells (including history shell and filer shells)
  805.         extended command processing (including ARUNZ command generator)
  806.         powerful error handlers (with command editing)
  807.         terminal-independent operation (TCAP)
  808.         flexible program loading (type-3 environment)
  809.         interprogram communication
  810.  
  811. The only things missing are named directories and flow control.  Some simple
  812. flow-control-like features could be implemented even without the FCP.  With
  813. all the security features and named-directory support removed from the
  814. command processor, there is room for many more CPR-resident commands, and
  815. the ones that won't fit can be implemented as virtual residents using the
  816. new type-3 environment.  In summary, a very powerful system can be built
  817. with a very small cost in TPA.
  818.  
  819.      To prove this point (and because it will be useful on those rare
  820. occasions when I run my database manager), I decided to develop a version of
  821. Z-COM that would have only the three pages of core modules.  The memory map
  822. is shown in Fig. 9.  It differs in two fundamental ways from all the other
  823. maps we have seen: (1) it is shorter and (2) the real VBIOS and ZRDOS run at
  824. different addresses than usual.  These differences will require some new
  825. techniques, and we will cover them shortly.
  826.  
  827. -----------------------------------------------------------------------------
  828.  
  829. System Component                ZC.COM Address          System Address
  830. ----------------                --------------          --------------
  831.  
  832.   CPR                             0200 - 09FF             CB00 - D1FF
  833.   ZRDOS                           0A00 - 17FF             D300 - E0FF
  834.   Virtual BIOS                    1800 - 19FF             E100 - E2FF
  835.   Shell Stack                     1A00 - 1A7F             E300 - E47F
  836.   Z3 Message Buffer               1A80 - 1ACF             E380 - E4CF
  837.   External FCB                    1AD0 - 1AF3             E3D0 - E4F3
  838.   PATH                            1AF4 - 1AFE             E3F4 - E4FE
  839.   Wheel Byte                      1AFF - 1AFF             E3FF - E4FF
  840.   Environment Descriptor          1B00 - 1B7F             E400 - E47F
  841.   TCAP                            1B80 - 1BFF             E480 - E4FF
  842.   Multiple Command Line           1C00 - 1CCF             E500 - E5CF
  843.   External Stack                  1CD0 - 1CFF             E5D0 - E5FF
  844.  
  845. Fig. 9.  Addresses of system components in the ZC3.COM file and in the
  846. target system for a minimum configuration with no IOP, RCP, FCP, or NDR.
  847. The file is 2E00H - 1D00H = 1100H = 4.25K shorter than the other versions.
  848.  
  849. -----------------------------------------------------------------------------
  850.  
  851.      First we have to make Z3BASE.LIB, the equates for which are shown in
  852. Fig. 10.  The only subtle change is in the way the VBIOS address is defined.
  853. Make sure you do not define it in terms of any of the modules whose
  854. addresses have been set to zero to disable them or you will get extremely
  855. strange results.
  856.  
  857. -----------------------------------------------------------------------------
  858.  
  859.         ; Z3BASE.LIB
  860.  
  861.                 rbios   equ     0e600h
  862.  
  863.         ; First page under BIOS
  864.  
  865.                 z3cl    equ     rbios - 100h
  866.                 z3cls   equ     203
  867.                 extstk  equ     z3cl + 0d0h
  868.  
  869.         ; Second page under BIOS
  870.  
  871.                 z3env   equ     rbios - 200h
  872.                 z3envs  equ     2
  873.  
  874.         ; Third page under BIOS
  875.  
  876.                 shstk   equ     rbios - 300h
  877.                 shstks  equ     4
  878.                 shsize  equ     32
  879.                 z3msg   equ     shstk + 080h
  880.                 extfcb  equ     shstk + 0d0h
  881.                 expath  equ     shstk + 0f4h
  882.                 expaths equ     5
  883.                 z3whl   equ     shstk + 0ffh
  884.  
  885.         ; Variable modules -- all disabled
  886.  
  887.                 z3ndirs equ     0
  888.                 z3ndir  equ     0
  889.                 fcps    equ     0
  890.                 fcp     equ     0
  891.                 rcps    equ     0
  892.                 rcp     equ     0
  893.                 iops    equ     0
  894.                 iop     equ     0
  895.  
  896.         ; Operating system components
  897.  
  898.                 vbios   equ     shstk - 0200h
  899.                 dos     equ     vbios - 0e00h
  900.                 ccp     equ     dos - 0800h
  901.  
  902. Fig. 10.  The Z3BASE.LIB equates for a minimum system that takes only 0.75K
  903. for the ZCPR3 buffers and 0.5K for the virtual BIOS required for automatic
  904. installation.
  905.  
  906. -----------------------------------------------------------------------------
  907.  
  908.      The basic procedure for creating this system is very much like what we
  909. have done before.  We edit the Z3BASE.LIB file and assemble up the CPR and
  910. ENV modules (or make the latter by patching).  There are no FCP, NDR, or IOP
  911. modules to worry about.  We set up the path, the wheel, and the error
  912. handler; we change the VBIOS file control block to load ZC3.CP for the CPR
  913. image file and change the 'not found' message to match; and we put in the
  914. ENV and CPR modules.
  915.  
  916.      Now we have to face the new complications that arise because of the
  917. change in size of the file.  First we will take up the simpler problem --
  918. changing the loader code in the first page of the file.  It normally copies
  919. 2C00H bytes (from 200H to 2E00H) up to the run-time location in memory.  Now
  920. the image part of the file is only 1B00H bytes long.  If you follow through
  921. the loader code in a debugger, you should not have too much difficultly
  922. figuring out what is going on.  The hardest parts to trace through are the
  923. places where the code prints out in-line strings.  You will typically see a
  924. call instruction followed by very strange code.  That strange code is the
  925. text to be printed.  That coding technique is very convenient for the
  926. programmer (and I use it all the time), but it makes disassembly and single-stepping in a debugger much more difficult.  When you encounter code like
  927. this, you have to use the dump ('D') display to locate the null (binary 0)
  928. that marks the end of the string.  Then you can continue running using the
  929. command "G,addr", where 'addr' is the address just after the null.
  930.  
  931.      Anyway, at address 181H you will find the key instruction: LD
  932. B.C.,2C00H.  This must simply be changed to LD B.C.,1B00H.  That's all there
  933. is to it -- as far as the loader code is concerned.  You might wonder why we
  934. don't have to change the starting address for the load, since it is not the
  935. same as before.  The answer is that Z-COM derives it from the initial jump
  936. instruction in the CPR image.  My first versions of Z33 used a relative
  937. jump, and I had to put the absolute jump back after one of my beta-testers
  938. pointed out that it would not work with Z-COM.
  939.  
  940.      Now we have to face two much more difficult problems: both the VBIOS
  941. and the ZRDOS modules have to be relocated to a new address.  How can we
  942. possibly do this without source code?  Well, if you purchased a separate
  943. copy of ZRDOS, you have a file with a name like ZRDINS.COM with which you
  944. can create a binary image of ZRDOS that will run at any address and with any
  945. ENV address.  But what if you don't have it?  And what about the VBIOS part?
  946. The latter could conceivably be disassembled, since the code is not very
  947. long or very complex, but there is a better way, one that makes use of the
  948. built-in capabilities of the auto-install package.
  949.  
  950.      If you had two computers with different BIOS entry addresses, you could
  951. perform a standard installation of Z-COM on each system.  By taking the two
  952. ZC.COM files and subtracting them in a debugger, you could derive the
  953. relocation map.  Now the question is how we can make two ZC.COMs using a
  954. single computer.
  955.  
  956.      If you examine the beginning of the code in ZCLD.COM, you will see that
  957. ZCLD keys its system generation to the address of the BIOS warmboot vector
  958. at address 0001, and that is what we will base our strategy on.  We will
  959. fool ZCLD into making us two versions of ZC.COM one page apart that we can
  960. subtract.
  961.  
  962.      With my standard Z-COM system running on the Televideo 803H, the CPR is
  963. at BA00H and the virtual BIOS at D000H.  Thus the vector at address 0001
  964. points to D003H.  By entering the following commands, we can make the BIOS
  965. look as though it were at B900:
  966.  
  967.         POKE B903 C3 03 D0      ; Set up JP D003H at address B903H
  968.         POKE 2 B9               ; Change bios vector from D003 to B903
  969.  
  970. Of course, you must use addresses appropriate to your system.  Any address
  971. below the CPR but above the memory used by ZCLD should work.
  972.  
  973.      With this patch in place, everything will be fine so long as we do not
  974. try to run a program that does direct BIOS calls based on the address at
  975. 0001.  (If we do? -- the system will simply go up in flames!)  In case
  976. you're worried, the next warmboot will delete our patch and restore things
  977. to normal.
  978.  
  979.      Fortunately, ZCLD does not mind being fooled this way.  All in all, the
  980. following sequence of commands will result in two files, ZCB8.COM and
  981. ZCB9.COM.
  982.  
  983.         POKE B903 CE 03 D0;POKE 2 B9;ZCLD;REN ZCB9.COM=ZC.COM
  984.         POKE B803 CE 03 D0;POKE 2 B8;ZCLD;REN ZCB8.COM=ZC.COM
  985.  
  986. We can then load both files into a debugger using the commands
  987.  
  988.         IZCB8.COM               ; set file to ZCB8.COM
  989.         R                       ; read in at 100H (100H-2DFFH)
  990.         IZCB9.COM               ; set file to ZCB9.COM
  991.         R3000                   ; read in at 3100H (3100H-5DFFH)
  992.  
  993.      Now from right in the debugger we can assemble a little program at
  994. 3000H to subtract the ZRDOS and VBIOS images in memory block 0A00H-19FFH
  995. from the images in memory block 3A00H-49ffH to give us the relocation map we
  996. need.  Here is how the entry of the assembly code proceeds:
  997.  
  998.         -A3000
  999.         3000  LD DE,3A00        ; set up pointers to two files
  1000.         3003  LD HL,A00
  1001.         3006  LD B.C.,1000      ; number of bytes to subtract
  1002.         3009  LD A,(DE)         ; get byte from higher image
  1003.         300A  SUB (HL)          ; subtract byte from lower image
  1004.         300B  LD (DE),A         ; put result (0 or 1) back
  1005.         300C  INC HL            ; increment the pointers
  1006.         300D  INC DE
  1007.         300E  DEC B.C.          ; check count
  1008.         300F  LD A,B
  1009.         3010  OR C
  1010.         3011  JR NZ,3009        ; loop through 1000H bytes
  1011.         3013
  1012.  
  1013. Enter the command "G3000,3013" to run this routine with a breakpoint at
  1014. 3013.  If you look at memory from 3A00H TO 49FFH you will see a pattern of
  1015. 1s and 0s.  This is the relocation map.  It indicates which bytes must be
  1016. changed to shift the execution address of the code.
  1017.  
  1018.      Now we have to relocate the ZRDOS to run at D300H and the VBIOS to run
  1019. at E100H instead of the values 9400H and A200H as they are in the image in
  1020. ZCB8.COM (determined by inspection with a debugger).  Thus we have to add an
  1021. offset of 3FH (E1-A2) to all bytes where the relocation map has a one in it.
  1022. So we assemble up another little program at 3000H as follows:
  1023.  
  1024.         -A3000
  1025.         3000  LD HL,3A00        ; point to relocation byte
  1026.         3003  LD DE,1A00        ; point to ZRDOS/VBIOS we are creating
  1027.         3006  LD B.C.,1000      ; number of bytes to cover
  1028.         3009  LD A,(DE)         ; get current value of byte
  1029.         300A  BIT 0,(HL)        ; see if relocation map has a 1 in it
  1030.         300C  JR Z,3011         ; if not, skip the offset addition
  1031.         300E  ADD A,3F          ; add the offset
  1032.         3010  LD (DE),A         ; put back the corrected byte
  1033.         3011  INC HL            ; increment the pointers
  1034.         3012  INC DE
  1035.         3013  DEC B.C.          ; check the count
  1036.         3014  LD A,B
  1037.         3015  OR C
  1038.         3016  JR NZ,3009        ; loop through 1000h bytes
  1039.         3018
  1040.  
  1041. Run this program with "G3000,3018" and you will have a ZRDOS and VBIOS that
  1042. will run at the required address.  Put them in a safe place temporarily
  1043. while you load in ZC3.COM and then move them into the proper place in the
  1044. image.  This completes the generation of the minimum system except for one
  1045. step described a little later.
  1046.  
  1047.      Although all that work with the debugger took quite a lot of space to
  1048. describe, it is really not that difficult to do.  I particularly wanted to
  1049. show it to you because it is a technique that is useful in many other
  1050. circumstances as well (like using MOVCPM to relocate your system in one-page
  1051. rather than 1K increments).  Now, however, I will show you a much easier way
  1052. to accomplish the same thing in the case of Z-COM.
  1053.  
  1054.      If you load ZCLD.COM into the debugger and trace through the code with
  1055. the 'L' command, you will see how it works.  Before one gets to the main
  1056. code, there are two places where checks are made.  One is to see if the
  1057. command was invoked as "ZCLD //" to request the built-in help screen.  The
  1058. second test is to make sure that you are not trying to run ZCLD from inside
  1059. a running Z-COM system.  We could drop out of Z-COM after making the changes
  1060. I am about to describe, but why put up with that trouble.  The code is
  1061. testing for the presence of the letter 'Z' in the copyright notice inside
  1062. the VBIOS at offset 42H.  At address 249H there is a "JP NZ,29D" instruction
  1063. that takes one to the system-building code if no 'Z' is detected.  If we
  1064. change this to an unconditional jump, we will effectively disable the test.
  1065.  
  1066.      At 29DH, the code loads the address of the BIOS with the instruction
  1067. "LD HL,(1)".  We know that we want the system to be generated at an address
  1068. 1100H higher than it would be normally because of all the modules we
  1069. removed.  Since the normal BIOS address was E600H, we want ZCLD to see a
  1070. value of F700H.  To accomplish this, we assemble in the instruction "LD
  1071. HL,F700", a direct load instead of an indirect load to HL.  We can then save
  1072. away this modified version as ZCLD1.COM.  When we run it, it very nicely
  1073. produces a system with a ZRDOS and VBIOS at just the addresses we wanted.
  1074.  
  1075.      There is one other change I have forgotten to mention.  The jumps in
  1076. the VBIOS that go to the IOP have to be replaced by jumps to the real BIOS
  1077. at the very same offset as in the VBIOS.  Thus the jump at offset 06, which
  1078. was "JP IOP+0CH", would become "JP BIOS+06H".
  1079.  
  1080.  
  1081. Switching from One Version to Another
  1082. -------------------------------------
  1083.  
  1084.      What if we are running one of our versions of Z-COM and want to change
  1085. to another one.  We can always run the ZCX command to get back to CP/M and
  1086. then load the new Z-COM system.  This seems unnecessarily tedious.  Why
  1087. can't we just run ZC2.COM from the ZC1 system?  The answer is that Joe
  1088. Wright did not want us to do this.  Of course, he was thinking in terms of
  1089. only single configurations, and then there would be no reason to run ZC.COM
  1090. when Z-COM was already running.  So, he put in some code to protect us from
  1091. this mistake.
  1092.  
  1093.      Now we want to do that very thing!  How can we disable the safety code?
  1094. Very simply.  It is based on the same check we described with the ZCLD
  1095. program.  It looks for a 'Z' at byte 42H of the BIOS or VBIOS.  If it is a
  1096. VBIOS, the 'Z' will be there; if it is a real BIOS, it would be very
  1097. unlikely that a 'Z' would be there.  We could go into the code itself as I
  1098. described with ZCLD and disable the test.  Alternatively, we could do
  1099. something much simpler (and reversible): go into the VBIOS and remove the
  1100. 'Z' by changing it to something else.  A third possibility, one I
  1101. implemented for the fun of it, is to write a little utility program that
  1102. finds that byte of the BIOS.  If it is not a 'Z', it simply returns; if it
  1103. is a 'Z', it sets it to zero.  Then the next ZCx can load over it.  If the
  1104. utility is not run, then the system cannot be overlaid.
  1105.  
  1106.      I will suggest one last modification to Z-COM to enhance it even
  1107. further.  That is a change to allow alternative versions of Z-COM to be
  1108. loaded without interrupting the flow of commands.  Thus your memory-hungry C
  1109. compiler would be invoked with an alias the reads something like:
  1110.  
  1111.         RUNC zc3;c $*;zc2
  1112.  
  1113. This alias would load the minimum Z-COM system to give the C compiler the
  1114. most room to work, and then once the compilation was finished it would
  1115. reload the full Z-COM configuration.  I did this with my Z3-DOT-COM/Z-COM
  1116. combination.  The I/O Recorder IOP was invoked using an alias.  The alias
  1117. would first check to see which Z-System was running (that is what I put the
  1118. $M parameter into ARUNZ for).  If it was Z3-DOT-COM, then alias would load
  1119. Z-COM before proceeding to load the IOP.  I will not go through the method
  1120. for accomplishing this, but I will give you a hint.  You have to change the
  1121. loader code in the first page of ZCx.COM so that the multiple command line
  1122. buffer and some other system information is not overwritten by the load.
  1123.  
  1124.  
  1125. Plans for Next Time
  1126. -------------------
  1127.  
  1128.     Whew!  That was quite a session of heavy technical material.  I don't
  1129. know yet exactly what I will do next time, but I certainly I will find a
  1130. less technical subject.  You need a rest, and I need a rest.  If you have
  1131. any questions or suggestions, please write or call.  See the ad for Sage
  1132. Microsystems East for the address and phone numbers.
  1133.