home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / jsage / znode3 / tcj / tcj37bmm.ws < prev    next >
Encoding:
Text File  |  1994-09-02  |  25.0 KB  |  599 lines

  1. Art:  This TOTALLY REPLACES the disk I mailed 2 days ago.  Bridger. 12/29/88
  2.  
  3. TCJ #37
  4. _words in italics_
  5. .h1  main headings
  6. .h2  secondary headings
  7.  
  8.                 Advanced CP/M
  9.  
  10.               Raw and Cooked Console I/O
  11.  
  12.  
  13.                Bridger Mitchell
  14.  
  15. {usual sidebar on Bridger}
  16.  
  17.  
  18. .h1 ZSDOS News
  19.  
  20. The brand-new CP/M disk operating system -- ZSDOS -- that I announced
  21. in this column last fall is meeting an enthusiastic reception.  At
  22. that time I wrote that the quality of the design and testing that have
  23. gone into this project means we are unlikely to see a long series of
  24. revision numbers to fix bugs.  But I didn't mean to imply that a major
  25. upgrade, ZSDOS 2.0, might never appear!  Indeed, I should have gone on
  26. to say that we may expect further contributions from the design team.
  27.  
  28. In the first of a multi-part article in this issue of TCJ, two of the
  29. ZSDOS authors -- Hal Bower and Cameron Cotrill -- take you behind the
  30. scenes of the many innovations in the new DOS.  And several of you
  31. have asked about porting ZSDOS to banked-memory (HD64180, Z80)
  32. systems.  Well, early discussions are afoot to set specifications for
  33. a banked-memory version with well-defined memory-management services.
  34.  
  35. Meanwhile Carson Wilson, the third member of the team, has been avidly
  36. turning out system utilities with nifty new features and is at work on
  37. a Z-System version of a popular public-domain memory-based editor.
  38.  
  39. If you haven't already ordered it, ZSDOS is available from Plu*Perfect
  40. Systems and Sage Microsystems East.
  41.  
  42. .h1 Feedback Loop
  43.  
  44. With the demise of yet another magazine (Profiles) that provided some
  45. coverage of CP/M topics, TCJ takes on greater prominence as a
  46. continuing source of high-quality CP/M information.  Art Carlson and
  47. we regular columnists need your feedback and suggestions to keep
  48. expanding and broadening TCJ's material.
  49.  
  50. I've appreciated the cards and BBS messages several of you have sent.
  51. They indicate that you find these columns worthwhile, although not
  52. always fully digestible in one sitting!  I will continue to focus on
  53. more advanced technical topics relating to the CP/M operating system,
  54. aiming to get the core concepts and details into print.  I fully
  55. expect readers to extend, expand, revise and critique these pieces --
  56. that's how our hobby progresses!
  57.  
  58. I'd especially like to receive suggestions for topics for future
  59. columns.  One early candidate is methods to make the Z-System external
  60. environment address available to applications that have not been coded
  61. as a Z-System tool, including compiler-generated .COM files.
  62.  
  63. I'd also welcome information about adding 3.5" and high-density 1.2MB
  64. 5.25" drives to CP/M systems.  I've recently customized
  65. DosDisk for an OEM to handle the AT-style 1.2MB floppy disk format.
  66. The DosDisk software could be similary extended to handle the 3.5"
  67. MS-DOS format, but in order for this to be usable the BIOS must talk
  68. to the drive.  Some of you have doubtless done this, or at least
  69. thought it through.  It would make a nice TCJ article!
  70.  
  71.  
  72. .h1 Unit-Record Input/Output
  73.  
  74. A processor is isolated and quite useless until it can talk to the
  75. "outside world".  Input and output are essential -- they supply the
  76. processor with data and enable it to report results.  Memory chips
  77. provide the fastest i/o.  After that come hard disks, floppy disks,
  78. magnetic tape, and serial channels at decreasing data rates. 
  79.  
  80. In TCJ #35 we covered file systems.  Input and output to files is done
  81. in blocks (physical sectors) of many bytes, and file storage devices
  82. (floppy disks, hard disks, tape drives, ram disks) are sometimes
  83. called block-devices.
  84.  
  85. Our interest in this column is input/output to/from _character_
  86. devices -- devices that normally supply or accept one byte at a
  87. time, such as a terminal, printer or modem.  Single-byte devices
  88. are sometimes called unit-record devices; they can be thought of
  89. as special block devices with a record length of one.
  90.  
  91. For many purposes it's useful to think of the computer's software
  92. environment as a series of rings.  At the outer ring are the
  93. application programs.  Just inside are the high-level languages,
  94. and inside that is the operating system.  Its outermost layer is
  95. the BDOS, providing a standardized, hardware-independent set of
  96. high-level services for access to the file structure and bundled
  97. input/output services to various devices. 
  98.  
  99. The next ring is the BIOS, providing all of the primitive
  100. input/output services needed by the BDOS.  It is the border land
  101. between a standard system and the specific computer.  At the BIOS
  102. jump table the interface is completely standardized, but within
  103. the BIOS the system designer must program down to bare metal,
  104. coding routines that know the precise conditions of the hardware
  105. -- disk drive, video display, printer handshaking conditions.
  106.  
  107. In general, applications will be more portable and easier to write if
  108. they confine their operating system access to the outer ring -- BDOS
  109. calls.  Yet there are good reasons for using BIOS calls in some
  110. applications, those that require highest performance or services
  111. unavailable from the BDOS.  And in a few cases, an application must
  112. forego portability and itself directly access the hardware, because no
  113. BIOS service is available; for example, to read a video terminal's
  114. screen or use a modem port.
  115.  
  116. The CP/M 2.2 BIOS provides character-device services for the
  117. basic device needed to command the system (the console),
  118. an auxiliary device, and a printer.  These services are:
  119.  
  120.     CONSTAT        Console Input Status
  121.     CONIN        Console Input
  122.     CONOUT        Console Output
  123.  
  124.     READER        Auxiliary Input
  125.     PUNCH        Auxiliary Output
  126.  
  127.     LISTSTAT    Printer Output Status
  128.     LIST        Printer Output
  129.  
  130. Each input or output service returns or sends a single byte.  For
  131. input, the routine waits until a byte is ready before it returns; for
  132. output, it waits until the device can accept the byte.
  133.  
  134. Strangely, only one BIOS input device and one output device has a
  135. status call function available to an application.   The BDOS or
  136. an application can determine, by calling CONSTAT, whether a
  137. character is waiting in the input (a key has been pressed). 
  138. Similarly, it can call LISTSTAT to see whether the printer is
  139. idle and can accept a character.
  140.  
  141. But there is no portable way, in CP/M 2.2, to determine whether the
  142. console device is ready to _accept_ a character.  All you can do
  143. is call CONOUT to send the character and wait, hoping that the
  144. device will eventually be ready.  This might seem all right (how
  145. would you run a CP/M system if you couldn't see its console
  146. output?).   But, consider an application that wants to keep the
  147. processor running at full efficiency (perhaps a video game, or just
  148. a smart display utility).   It would like to send a character to
  149. the console only when it knows that it will be processed immediately.
  150.  
  151. Internally, however, the BIOS must have a routine to determine
  152. the input and output status of every device.  In order to obtain
  153. a valid byte of input it must not access the physical device (a
  154. parallel port, an asynchronous receiver chip) until the device
  155. signals, by some type of status report, that a byte is ready.
  156. And similarly, the BIOS must not output a byte to a physical
  157. device (video ram, serial tranmsitter chip, parallel port) until
  158. the device signals that its buffer is empty and ready to recieve
  159. a byte. 
  160.  
  161.  
  162.  
  163. .h1 Cooked Input
  164.  
  165. The BDOS provides standardized services to applications, hiding
  166. some of the tedious details of communicating with the input and
  167. output devices.  For the console device the BDOS provides
  168. _cooked_ (processed) input and output services, sparing the
  169. programmer the overhead of including this code in almost
  170. every application.  For applications needing raw console input and
  171. output, the BDOS also provides a raw (uncooked) function #6.
  172.  
  173. In CP/M 2.2, console single-character input function (#1) provides:
  174.     
  175.     . echo to console output
  176.     . flow control
  177.     . abort control
  178.     . tab expansion
  179.  
  180. In addition, the console line-input function (#10) provides
  181. limited line-editing and printer controls:
  182.  
  183.     . delete last-character (backspace)
  184.     . cancel line (^X or ^U)
  185.     . retype line (^R)
  186.     . list device output control
  187.  
  188. (Other function #10 editing controls -- delete and echo, and end
  189. physical line -- existed to serve paper-output teletypes.  BDOS
  190. patches and replacements such as ZSDOS have eliminated them.)
  191.  
  192. Both the console single-character output function (#2) and the
  193. string output function (#9) provide:
  194.  
  195.     . flow control
  196.  
  197. .h2 Flow Control and Lookahead
  198.  
  199. Flow control is the process of starting and stopping the flow of
  200. bytes over an input/output channel.  Our concern here is the
  201. control of bytes to the console device.  
  202.  
  203. The BDOS is designed so that the user can "freeze" a screen of
  204. messages by typing a Control-S -- the standard XOFF character. 
  205. Output will resume by typing Control-Q -- the standard XON
  206. character.  Actually, output resumes when any other character
  207. (except Control-C -- the abort character) is typed, but it's a
  208. good habit to use Control-Q to keep your fingers conditioned for
  209. systems, such as unix, that use the standard control characters.
  210.  
  211. In order for flow control to work, the application must print its
  212. messages using BDOS functions #2 and #9.
  213.  
  214. Flow control requires something that many -- including compiler
  215. authors and BDOS hackers -- have found astonishing:  the BDOS
  216. console-output functions must call the BIOS console _input_
  217. functions in order to perform a _lookahead_ function.  After all,
  218. how else could the BDOS know that the user had typed a Control-S
  219. to suspend output?
  220.  
  221. It works like this.  Before the BDOS sends a character to the
  222. console, it checks the console input status.  If no key has been
  223. pressed, the character is sent.
  224.  
  225. But suppose a key has been typed.  In this case the BDOS calls
  226. the BIOS console input function to get the character.  From this
  227. moment on, the character is no longer in the BIOS.  The BDOS then tests
  228. whether the character is a Control-S.  If it is, the BDOS waits
  229. for the _next_ keypress and only then sends the output character. 
  230. If it is _not_ Control-S (or Control-C, discussed below) the BDOS
  231. saves the character (say 'A') in a one-character buffer and sends the
  232. output character.
  233.  
  234. If the next operation is to print another character on the console,
  235. the BDOS test for flow control will become ineffective.  The BDOS has
  236. only the one-character buffer, which is now full (it's holding the
  237. 'A'), so it cannot check the next keypress for Control-S; if it did,
  238. and the character were anything else, it would have to throw away one
  239. of the input characters.
  240.  
  241. The lookahead function might perhaps have been better implemented by
  242. providing a "peek" subfunction to the BIOS CONIN -- return but retain
  243. the pending next character.
  244.  
  245. The key result is that the next console input character is moved from
  246. the BIOS into the BDOS one-character buffer as a result of any BDOS
  247. function #2 or #9 output.  As a consequence, any application that uses
  248. the _BIOS_ to obtain console input will sometimes "lose" a typed
  249. character, only to have it emerge when the BDOS is next used for input
  250. (function #1 or #10)!
  251.  
  252.  
  253. .h2 Coping with missing characters
  254.  
  255. The simplest rule I can give you for coping with missing
  256. characters is to  keep all console input/output at _one_ level of
  257. the operating system -- all BDOS or all BIOS -- within a single
  258. application.  For example, don't mix BDOS line input (function
  259. #10) and BIOS CONIN.
  260.  
  261. It's fairly common for applications to use the BIOS functions for
  262. console i/o, in order to speed up output and to get every possible
  263. keyboard character.  The Z3LIB and VLIB routines used in many Z-System
  264. utilities do so.  At the start of such an application you may need to
  265. check the BDOS, using function #11, to see if a fast keypress has
  266. already been sucked into the BDOS one-character buffer.  If it returns
  267. non-zero, you can get the character with function #1 (but that will
  268. echo).  In order to use function #6 successfully to get the character
  269. without echo, you need to have installed the Plu*Perfect Systems patch
  270. (described later).
  271.  
  272. Jay Sage has used the following method of obtaining input (a
  273. named-directory password) from BDOS function #10 with echoing shut
  274. off.  First, save the first byte of the BIOS CONOUT jump vector (it
  275. should be the JP opcode) and replace it with a RET opcode.  Next, call
  276. BDOS function #10.  When the BDOS calls the BIOS CONOUT to echo the
  277. character, the BIOS will return at once.  Then, immediately following
  278. the BDOS call, restore the first byte of the BIOS CONOUT jump.  (Note
  279. that he follows the sound principle of saving and restoring the
  280. environment, by saving and restoring the byte in the BIOS "jump
  281. vector".  he doesn't simply assume it is a JP.  It's possible that
  282. other code -- perhaps in an RSX -- has already patched this location.)
  283.  
  284. This trick is handy, but should be used only where no other solution
  285. is available.  In Jay's case, there was insufficient room in the Z34
  286. command processor to collect a password with function #6.  The
  287. difficulty with this approach is that during the time that the BIOS
  288. CONOUT is patched out it is possible that other processes would be
  289. generating console output.  What other processes could there be in
  290. CP/M?  If BackGrounder ii is loaded, a press of the <SUSPEND> key
  291. would temporarily suspend the current task and prompt for user input,
  292. but the prompt would be invisible!  Or an interrupt-driven task could
  293. generate a screen message that would be lost.
  294.  
  295.  
  296.  
  297. .h2 Abort Control
  298.  
  299. A Control-C will cause the BDOS to abort the current application,
  300. jumping directly to 0000, when it is:
  301.  
  302.     . the _first_ character typed after a Control-S
  303.       has halted output from function #2 or #9.    
  304.  
  305.     . the _first_ character typed to line-input
  306.       (function #10)
  307.  
  308. The abort control feature of the CP/M 2.2 BDOS is a mixed
  309. blessing at best.  It gives the user a handy way to kill a job
  310. that is scrolling unwanted output to the screen.  But it limits
  311. the use of edited BDOS line input to applications that can
  312. tolerate abrupt termination if the user happens to hit Control-C.
  313. As a result, most well-written applications must incorporate
  314. their own line editor in order to retain control to avoid being
  315. cancelled with unclosed files, open modem connections, or whatever.
  316.  
  317.  
  318. .h1 Cooked Output
  319.  
  320. In addition to flow control, which is a feature of cooked console
  321. input that controls the flow of output, the BDOS alters the raw
  322. output to the console by special processing of tabs and by
  323. creating a parallel stream of output for the printer.
  324.  
  325. .h2 Tab expansion
  326.  
  327. The BDOS expands the horizontal tab character (09h) to the number
  328. of spaces required to reach the next logical tab stop (every
  329. eight characters).  To do this it keeps a current-column count
  330. for all output to functions #2 and #10, resetting it to 0 on each
  331. carriage return.
  332.  
  333. This is a handy cooked-output service.  But to work successfully,
  334. all output on the line must go through these BDOS functions. 
  335. Avoid mixing BDOS and BIOS console output on the same line.
  336.  
  337. .h2  Echoing to the Printer
  338.  
  339. The BDOS maintains a flag that, when set, causes function #2 and
  340. #9 output to be echoed to the BIOS list device as well as the
  341. console output.  The flag is toggled when a Control-P is typed
  342. to function #10 -- the line-input function.
  343.  
  344. Control-P is very handy for getting a quick, selective printed
  345. record of some console output.  It can also mysteriously freeze
  346. your system when the printer is not ready.  When your computer locks
  347. up, make a habit of checking the attached external devices (printer,
  348. modem) before you resign yourself to pressing the reset button!
  349.  
  350.  
  351.  
  352. .h1 The Case of the Missing Character
  353.  
  354. If you've used a number of CP/M systems, you've probably had the
  355. puzzling and quite annoying experience of occasionally "losing"
  356. one character you have typed when running a program, only to have
  357. it pop up unexpectedly much later, perhaps at the next command
  358. prompt.  It's a difficult bug to reproduce, and occurs only on
  359. some systems.  This spooky gremlin is so perplexing that a user
  360. can begin to believe his computer is truly haunted!
  361.  
  362. Has CP/M been visited by the supernatural?  Probably not.  We've
  363. already seen how mixing BDOS and BIOS console functions can cause
  364. an input character to become stuck in the BDOS one-character
  365. buffer when subsequent input is obtained by BIOS calls.
  366.  
  367. Several years ago, Derek McKay, my partner at Plu*Perfect
  368. Systems, spotted another cause of missing characters -- a bug in
  369. Digital Research's original design of the CP/M 2.2 BDOS that used
  370. faulty logic in the handling of "raw" console input with BDOS
  371. function #6.  Moreover, Derek developed a Z80 patch that corrects
  372. the problem and fits in the original BDOS space.  This is an important
  373. improvement, because without it there is no totally reliable way
  374. to mix cooked BDOS console i/o with any type of raw i/o, either
  375. BIOS or BDOS.
  376.  
  377. We included the patch in the CP/M Enhancements that Plu*Perfect
  378. originally published for Kaypro systems.  More recently, the
  379. authors of ZSDOS have incorporated the same logic into their
  380. excellent new DOS.  So, on these systems, the missing character
  381. doesn't manifest itself.
  382.  
  383. .h2 Raw Console Input
  384.  
  385. To understand how a character can disappear, and then reappear,
  386. we first need to examine the BDOS's raw console input function.
  387.  
  388. BDOS function #6 was intended to provide absolutely raw console
  389. input and output functions accessible by a BDOS call, with no
  390. input flow control and no output processing.  An application would
  391. use this function, for example, when it wanted to get a character
  392. without necessarily echoing it to the terminal. 
  393.  
  394. DRI attempted to squeeze input, input status, and output into a
  395. single BDOS function (probably to save 8080 code space) and in
  396. doing so somewhat limited the usefulness of this service.  To use
  397. function #6, set C=6 and
  398.  
  399.     E= 0FFh        to get a character, if ready
  400.     E= 0FEh        to get console input status
  401.     (E=0FDh        to wait for a character)
  402.     E= 0...0FCh    to output the value in E to the console
  403.  
  404. When used for input, function #6 returns a 1-byte value in A.  If
  405. A is 0, no character is waiting; a non-zero value is the input
  406. character.  Thus it is impossible to enter a nul character
  407. (Control-@ on most keyboards) when function #6 is used.  (This
  408. defect is significant for editors, which must therefore use
  409. BIOS functions for console i/o.)
  410.  
  411. When used for output, function #6 is limited to values 0h to 0FCh.
  412. Usually ok, this restriction makes some 8-bit coded graphics
  413. characters unprintable on a few terminals.  (The subfunction code 0FDh
  414. is used by CP/M Plus and ZSDOS to wait for the next character and
  415. return it.)
  416.  
  417. But the real bug in function #6 is its internal check for input
  418. status.  The original BDOS code (figure 1) calls the BIOS CONSTAT
  419. routine to determine if a character is waiting.  This is fine,
  420. except that another BDOS function may have called the lookahead
  421. routine to test for flow control and left the tested character in
  422. the lookahead buffer.  When that situation exists, function #6
  423. will return A=0 (no character waiting) until a key is typed, and
  424. then return the next typed character, not the one last typed and
  425. still in the buffer!
  426.  
  427. Meanwhile, the tested character continues to sit in the buffer. 
  428. Eventually, someone -- either the application program or the
  429. command processor -- will call a BDOS function that does check
  430. the lookahead buffer before returning a character.  It will find
  431. the character still there, and return the missing character!
  432.  
  433. .h2 Code
  434.  
  435. Figure 2 contains the replacement routine.  It calls a new
  436. "ckstat" routine to determine input status.  The new routine just
  437. fits into the space made available by rewriting the "lkahead"
  438. routine just above it in z80 code.
  439.  
  440. Note the exact logic of the ckstat routine.  By clever coding it
  441. returns two flag values -- nonzero and carry not set when the next
  442. character should be obtained from the BDOS and nonzero and carry
  443. set when the next character should be obtained from the BIOS.
  444.  
  445. With this new routine, the lkahead routine can determine from
  446. calling ckstat whether to call the BIOS CONIN.
  447.  
  448. .h2 Patching your BDOS
  449.  
  450. If you are running the original CP/M 2.2 BDOS you can upgrade it
  451. with the function #6 patch.  Using a debugger, first check that
  452. the original 8080 code is exactly as shown in the figures.  Then
  453. assemble just the patch code with the BDOS equate set to the base
  454. value for your system, and output a hex file.
  455.  
  456. The hardest part is getting the patch installed in your system.
  457. You can load it with a debugger, and then check memory to see that
  458. it is installed.  But if your system reloads the BDOS on a warm
  459. boot, the patch will be gone when the next program runs.  If
  460. that's the case, you will need get the patch into the SYSGEN.COM
  461. image of the BDOS.
  462.  
  463. Load SYSGEN.COM with a debugger.  On most systems, the BDOS image
  464. begins at 1200h.  Compare the bytes there and in the running BDOS
  465. in high memory and then compare the bytes at the patch locations
  466. in the image (by adding 1200h to the addresses in the figures
  467. here) and in high memory.  If all matches up, load the hex patch
  468. into the high BDOS, compare again, and then move just the patched
  469. bytes of the two upgraded routines to their corresponding
  470. location in the overlay:
  471.     
  472.     MBDOS+0123,BDOS+0141,1200+0123
  473.     MBDOS+02D4,BDOS+02EC,1200+02D4
  474.  
  475. Then save the appropriage number of pages of the modified XSYSGEN.COM.
  476. Run XSYSGEN and place the system on the boot tracks of a scratch
  477. disk.  Boot the disk, test the system for normal operation, and
  478. then with a debugger check the high BDOS to see that the patches
  479. are indeed in place.
  480.  
  481. Note that this patch will not work with ZRDOS or other replacement
  482. BDOSes.  It may be possible to write a functionally equivalent
  483. ZRDOS patch, if you can find enough free space in a BDOS that is
  484. already in Z80 code.
  485.  
  486.  
  487.  
  488.      Figure 1.  Corrected CP/M 2.2 BDOS Function #6 Routine
  489.      ------------------------------------------------------
  490.  
  491. Authors: Derek McKay, Bridger Mitchell (Plu*Perfect Systems)
  492.  
  493.   0000    bdos       equ    0000h        ; base of CP/M 2.2 BDOS
  494.   00B7      abort       equ    bdos+00B7h    ; "jp 0000"
  495.   00FB      getchar  equ    bdos+00FBh    ; get next console input char.
  496.   0301      setretval equ    bdos+0301h    ; set return value in A
  497.   030A      charbuf  equ    bdos+030Ah    ; 1-character input buffer
  498.   0D91      exit       equ    bdos+0D91h    ; BDOS exit routine
  499.  
  500.   0E00    bios       equ    bdos+0e00h    ; base of BIOS
  501.   0E06      constat  equ    bios+6        ; console status
  502.   0E09      conin       equ    bios+9        ; console input
  503.   0E0C      conout   equ    bios+0Ch    ; console output    
  504.  
  505. ; -- original (8080) Direct Console I/O Routine --
  506. ;    malfuncting code marked with "***"
  507.  
  508.   02D4        org    bdos  + 2D4h    
  509.  
  510.   02D4    79    fn6:    ld    a,c
  511.   02D5    3C        inc    a
  512.   02D6    CA 02E0        jp    z,fn6in
  513.   02D9    3C        inc    a
  514.   02DA    CA 0E06    fn6s:    jp    z,constat    ; ***
  515.   02DD    C3 0E0C        jp    conout
  516.   02E0    CD 0E06    fn6in:    call    constat        ; ***
  517.   02E3    B7        or    a,a
  518.   02E4    CA 0D91        jp    z,exit
  519.   02E7    CD 0E09        call    conin        ; ***
  520.   02EA    C3 0301        jp    setretval
  521.  
  522. ; -- corrected (z80) routine --
  523.  
  524.   02D4        org    bdos  + 2D4h    
  525.         ;
  526.   02D4    79    fn6:    ld    a,c        ; if c == FF
  527.   02D5    3C        inc    a
  528.   02D6    28 08        jr    z,fn6in        ; ..get character
  529.   02D8    3C        inc    a        ; if c == FE
  530.   02D9    CA 0137        jp    z,ckstat    ; ..get input status
  531.                         ;   of buffer & bios
  532.   02DC    C3 0E0C        jp    conout        ; ..else output char
  533.         fn6in:    call    ckstat        ; check both buffer
  534.                         ;   and bios
  535.   02DF    CA 0D91        jp    z,exit        ; ..no char waiting,
  536.                         ;   return 0 status
  537.   02E2    CD 00FB        call    getchar        ; get char from buffer
  538.                         ;   or bios
  539.   02E5    18 1A        jr    setretval    ; and return it
  540.         ;
  541.  
  542.  
  543.          Figure 2.  Console Look-Ahead Routines
  544.          --------------------------------------
  545.  
  546.  
  547. ; -- original (8080) console input look-ahead routine --
  548.  
  549.   0123        org    bdos + 0123h
  550.  
  551.   0123    3A 030A    lkahead:ld    a,(charbuf)
  552.   0126    B7        or    a,a
  553.   0127    C2 0145        jp    nz,return1
  554.   012A    CD 0E06        call    constat
  555.   012D    E6 01        and    1b
  556.   012F    C8        ret    z
  557.   0130    CD 0E09        call    conin
  558.   0133    FE 13        cp    'S'-'@'
  559.   0135    C2 0142        jp    nz,savechar
  560.   0138    CD 0E09        call    conin
  561.   013B    FE 03        cp    'C'-'@'
  562.   013D    CA 0000        jp    z,0000
  563.   0140    AF        xor    a,a
  564.   0141    C9        ret
  565.  
  566.   0142    32 030A    savechar:ld    (charbuf),a    ; save input char
  567.                         ; in buffer
  568.   0145    3E 01    return1:ld    a,1        ; return a non-zero
  569.   0147    C9        ret            ; character
  570.  
  571. ; -- shorter replacement (z80) routine --
  572.  
  573.   0123        org    bdos + 0123h
  574.  
  575.   0123    CD 0137    lkahead:call    ckstat        ; if no char waiting
  576.   0126    C8        ret    z        ; ..return
  577.   0127    DC 0E09        call    c,conin        ; if no char in buffer,
  578.                         ;   call bios
  579.   012A    FE 13        cp    'S'-'@'        ; if not ^S
  580.   012C    20 14        jr    nz,savechar    ; ..return the char
  581.   012E    CD 0E09        call    conin        ; ^S, so get next char
  582.   0131    FE 03        cp    'C'-'@'        ; if ^C
  583.   0133    28 82        jr    z,abort        ; ..abort
  584.   0135    AF        xor    a,a        ; else return false
  585.   0136    C9        ret            ;    status    
  586.  
  587. ; new check-console-status (z80) routine
  588.  
  589.   0137    3A 030A    ckstat:    ld    a,(charbuf)    ; if buffered char waiting
  590.   013A    B7        or    a,a        ; ..clear CY and return NZ
  591.   013B    C0        ret    nz
  592.   013C    CD 0E06        call    constat        ; else check bios for a char
  593.   013F    B7        or    a,a        ; if char waiting there
  594.   0140    0F        rrca            ; ..set CY and set NZ
  595.   0141    C9        ret
  596.  
  597. ; resume original (8080) code at 0142h
  598.  
  599.