************************* * * * T h e P E E P E R * * * ************************* Unique Interrupt-Based Program-Tracer For the Radio Shack Color Computer, 16K min., Extended Basic not required Copyable to disk, compatible with Disk Basic 1.0 and 1.1 (c) 1984, Arthur J. Flexser SpectroSystems, Miami, Florida The Peeper is a machine-language utility program designed to let you inspect any desired portion of the Color Computer's memory, even while Basic or machine language programs are running. With the Peeper, you can display any part of memory, using any of the CoCo's 26 documented display modes (text, graphics, or semigraphics). You can freeze the action at any time, or slow it down by practically any desired amount. Machine-language programmers are likely to find Peeper to be an invaluable debugging tool, in that it provides the capability of monitoring the slow-motion execution of a machine-language program. The Peeper is capable of providing a running trace of the 6809's registers and stack, and supports single-stepping, breakpoints, and other useful program-monitoring functions. Basic programmers will find Peeper very useful as a means of extending their knowledge beyond the level explained in the manuals. Peeper's ability to let you look "behind the scenes" at what Basic is doing will clarify the uses of many PEEK and POKE commands. The section entitled ^cA Guided Tour Through the CoCo's Memory^d is included to help you explore the functioning of Basic. You are invited to watch what happens in memory as various Basic commands are executed, and an explanation of what you are seeing is provided, at a level that does not presuppose knowledge of machine language. For the pure fun of it (ML experience not required), it is fascinating to use Peeper with arcade-style games. You can use the slow-motion feature to see the fine details of how the animation effects are achieved. See what is happening on "hidden screens" that never normally come into view. Or, see how the game looks and plays in a graphics mode other than the normal one--you will be dazzled at the variety of effects you can achieve with 26 display modes available. (This demonstration is a definite attention-grabber at any gathering of CoCo enthusiasts.) Also included with Peeper are two short companion programs. The first, Rompeep, supplements Peeper in that it allows you to inspect the contents of the Basic ROMs and of Rompack cartridges. The second program, Find, is a utility to aid in locating interrupt-disabling instructions that must be removed from some machine-language programs in order to achieve Peeper compatibility. Using the Peeper A command reference sheet is included with the program. It is suggested that you have this sheet in front of you for reference as the various commands are discussed. If you have not already done so, load in and execute the program. Peeper should now be asking you whether you have a printer connected; type Y or N as appropriate. Either response will produce Basic's "OK" message and flashing cursor, and your printer, if any, should type a carriage return. (Note: if you use a printer baud rate other than 600 baud, you must poke the appropriate constant into location 150 before executing Peeper, or with Peeper disengaged, or the poke will have no effect. You can also save a "customized" copy of Peeper with your required baud rate constant embedded, as explained later.) Display Window Commands Now, let's try out some of the commands, starting with those that affect which portion of memory is being displayed. Hexadecimal notation (indicated by a dollar sign) will be used principally in what follows. If you are unfamiliar with hexadecimal, it is recommended that you consult one of the many available sources that explains this notation. As you will see, it is not difficult to keep track of what portion of memory Peeper is displaying when hexadecimal counting is used, whereas this task would be much more involved using the corresponding decimal values. First, press shift-clear. You should now be looking at memory page zero, which contains addresses $0 to $1FF. Each display page contains 512 bytes, equivalent to hexadecimal $200, or 1/2 K. The Color Computer is capable of using addresses from $0 to $FFFF, or 64K of memory. Thus, there are 128 display pages of 1/2 K each, which will be designated as pages 0-127. (These pages are not the same thing as what Radio Shack refers to as a graphics page. A graphics page contains $600 bytes, or three display pages worth.) The section entitled "A Guided Tour Through the CoCo's Memory", presented later, will describe what it is you are looking at on the various pages of memory; for now, let us concentrate on getting you oriented so that you will be able to locate any desired page of memory or any particular individual byte. In order to keep track easily of where you are in memory, it is necessary to acquire the ability to count by twos in hex: $0,\2,\4,\6,\8,\A,\C,\E,\10,\ 12,\14,\16,\18,\1A,\1C,\1E,\20, etc. Why by twos? Because each screen row contains $20 bytes, and each display page contains $200 bytes; if you can count by twos, you can also count by $20s or $200s. Now, try out the up and down arrow keys. The former moves the display window up $200 (1 page) in memory, while the latter moves you down an equal amount. If you hold the shift key down while pressing up or down arrow, you will move up or down $1000 (8 pages, or 4K) at a time. Use shift-clear to go back to page zero and count 2,\4,\6,\8,\A,\C,\E,\ one thousand,\2,\4,\6,\8,\A,\C,\E,\two thousand, pressing the up-arrow key with each count. You should now be looking at the display page containing addresses $2000-$21FF. Of course, we could have gotten to $2000 faster by pressing shift-up arrow twice. As a check, type two shifted down arrows, which should bring you back to page zero. Suppose we want to locate a particular byte of memory, say $2D56. This address will be on the page containing $2C00-$2DFF. From page zero, type two shifted up arrows, to get to $2000. Now count 2,\4,\6,\8,\A,\C\as you press unshifted up arrow with each count. You should now have the correct page, starting with $2C00, on your screen. Each screen row contains $20 bytes; the row that contains $2D56 will include addresses $2D40-$2D5F, and will be located somewhere in the bottom half of the screen. As you point to the start of each successive row, starting at the top, count 0,\2,\4,\6,\8,\A,\C,\E,\one hundred (=$2D00), 2,\4. This is the row we want, the one starting with $2D40. Starting at the left, count 40, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 50, 1, 2, 3, 4, 5, 6. You should now be pointing at $2D56. (With some practice, you may find it easier to locate $2D5F at the right edge of the screen and count leftwards back to $2D56.) To check that you are really looking at $2D56, try poking something into this location. Press the enter key to start a new line, and then type (blindly) POKE &H2D56,\&H41. If all is well, the letter A should appear at the location you identified as $2D56. ($41 is the screen code for the uppercase form of the letter A; refer to the table of screen codes on page 4 for determining the code corresponding to any desired letter or symbol.) If an A did not appear where expected, you either were looking at the wrong memory location, or you mistyped the command. To find out what went wrong in this case, type shift-right arrow to display Basic's text screen (locations $400-$5FF). Your POKE command should be visible, so that you can verify it. If it is correct and was acknowledged by Basic, try again to locate $2D56; there should be an A displayed there. Otherwise, type the command again and check $2D56. With a little practice, you should be able to find any location reliably. (While practicing, avoid poking locations on page zero, which could cause a crash. Also steer clear of memory locations that contain Peeper itself, for similar reasons. Incidentally, the active copy of Peeper is the one at the top of your available memory; Peeper relocates itself when executed to maximize the memory available to Basic.) In using the commands that move the display window, you should be aware that memory is treated as circular: the page below page zero is page 127, and the page above page 127 is page zero. The final display window command is shift-L (L stands for look), which causes a display of Peeper's "status page". This page contains information concerning the current status of various selectable options, as well as displays used in conjunction with the memory examine, breakpoint, and trace features to be discussed later. A second shift-L command will in most cases restore the display page and display mode that were in effect previously. In some cases, however, it will be necessary to use additional Peeper commands to restore the correct page and mode, since Peeper cannot be aware of changes in page and mode that have been induced by other programs. If the program you are monitoring induces a change in display mode while you are inspecting the status page, rendering the status display unreadable, two successive shift-L commands will have the effect of returning you to the status page in text-display mode. Note Concerning the Effect of Memory Size If you have a 16K machine, containing RAM addresses $0-$3FFF, you will find that the display for pages 32-63, corresponding to addresses $4000-$7FFF, is unstable. This instability is of no consequence, since these addresses are beyond the end of your 16K of RAM in any case. If you have a nonstandard 32K upgraded machine containing two banks of piggybacked 16K chips, the display may also be unstable in this memory range, depending on the exact upgrade method used. This constitutes a much more serious problem, since Peeper will be unable to display half of your available RAM, and since the status page (discussed later) will usually be located in this upper part of RAM. Some minor hardware modifications can correct this difficulty, however; SpectroSystems will supply instructions if the request is accompanied by a stamped, self-addressed envelope. In either the 16K CoCo or the 32K piggyback version, pages 64-127 will be a repeat of pages 0-63. If your CoCo is a standard 32K model, containing 64K chips, your 32K of RAM (addresses $0 to $7FFF) will be displayed on pages 0-63. However, pages 64-127 will ^cnot^d be a repeat of pages 0-63 as would be true in a machine with 16K chips. A Color Computer memory map shows that locations $8000 and up contain the Basic ROMs, so one might reasonably expect the start of Extended Basic to come into view as one flips from page 63 to page 64. If so, one would be wrong. What is actually seen on pages 64-127 is the second 32K bank of RAM that is contained in the 64K chips. This will be true whether or not your CoCo has had the benefit of the 64K modification to enable use of this second bank of RAM. (Newer CoCos have this modification already built in, whether sold as 32K or 64K.) Thus, many of you will be able to see into 32K of RAM that your CoCo is unable to use without modification. Fortunately, the hardware remedy for this somewhat frustrating situation is simple, inexpensive, and has been widely published. Screen Codes A. Non-graphics characters The following table shows the hex bytes corresponding to the inverse (lowercase) and regular (uppercase) forms of the various characters. Inv Char Reg Inv Char Reg Inv Char Reg Inv Char Reg $00 @ $40 $10 P $50 $20 space $60 $30 0 $70 01 A 41 11 Q 51 21 ! 61 31 1 71 02 B 42 12 R 52 22 " 62 32 2 72 03 C 43 13 S 53 23 # 63 33 3 73 04 D 44 14 T 54 24 $ 64 34 4 74 05 E 45 15 U 55 25 % 65 35 5 75 06 F 46 16 V 56 26 & 66 36 6 76 07 G 47 17 W 57 27 ' 67 37 7 77 08 H 48 18 X 58 28 ( 68 38 8 78 09 I 49 19 Y 59 29 ) 69 39 9 79 0A J 4A 1A Z 5A 2A * 6A 3A : 7A 0B K 4B 1B [ 5B 2B + 6B 3B ; 7B 0C L 4C 1C \ 5C 2C , 6C 3C < 7C 0D M 4D 1D ] 5D 2D - 6D 3D = 7D 0E N 4E 1E ^f 5E 2E . 6E 3E > 7E 0F O 4F 1F ^g 5F 2F / 6F 3F ? 7F B. Graphics characters The graphics screen codes ($80-$FF) consist of a color code, represented by the first hex digit, and a pattern code, represented by the second digit. The color codes are as follows: $8 green 9 yellow A blue B red C buff D green-blue ("cyan") E blue-purple ("magenta") F orange (Adding 7 to the numbers used by Basic to represent the colors will produce these values.) ^kN The pattern codes ($0-F) that correspond to the second digit of the graphics characters' screen codes are found using the following diagram: (diagram missing) To obtain the pattern code for a desired configuration, simply add up the values of the quadrants that are "lit up", that is, non-black. Thus, the screen code value of a graphics character that is red in the upper left and lower left quadrants would be $BA, since $B = red and $A = 8 + 2. Note that a character's screen code is not the same as its Ascii value; the two are equivalent for uppercase letters, but are not equivalent in general. Display Mode Commands The shift-D command allows you to change the display mode in which you are viewing a section of memory. If you type shift-D 13 times in a row, you will view all of the available modes in Color Set 0, one of the two color sets that is available for each display mode. If you now type shift-Q, which causes a change to the alternate color set, Color Set 1 will be in effect and you can again cycle through the 13 modes by repeatedly pressing shift-D. These 26 display options (13 modes ^i 2 color sets) represent the entire set of the CoCo's documented display possibilities, although undocumented modes also exist. Pressing shift-right arrow at any time will return you to text mode and Color Set 0, and will reset the display mode counter to the beginning of its cycle of 13 modes. (Recall that this command also moves the display window to page 2, Basic's text page.) The 13 display modes, in order, are as follows: 1. Text mode (Alphanumeric Internal; Semigraphics-4) (Set-Reset graphics, 64 * 32) 2. Graphics-6R (PMODE 4; 256 * 192) 3. Graphics-6C (PMODE 3; 128 * 192) 4. Graphics-3R (PMODE 2; 128 * 192) 5. Graphics-3C (PMODE 1; 128 * 96) 6. Graphics-2R (PMODE 0; 128 * 96) 7. Graphics-2C (128 * 64) 8. Graphics-1R (128 * 64) 9. Graphics-1C (64 * 64) 10. Semigraphics-24 (64 * 192) 11. Semigraphics-12 (64 * 96) 12. Semigraphics-8 (64 * 64) 13. Semigraphics-6 (64 * 48) Since most of these modes display considerably more than $200 bytes on the screen at a time, pressing the up or down arrow keys will not cause a complete replacement of the screen's contents as it does in text mode. Rather, most of the screen's contents will remain the same but will be shifted up or downward by the equivalent of $200 bytes as the up or down arrow keys are pressed. The memory address corresponding to the upper left corner of the screen may be determined by counting by $1000s or $200s as discussed previously. Peeper disables a feature of Extended Basic that automatically induces a change to text-display mode whenever any printing is sent to the screen. This disabling allows you to stay in your selected display mode regardless of whether screen printing is taking place. This aspect of Peeper creates an exception to the general rule that Basic programs run normally under Peeper if no Peeper commands are given. The command SCREEN\0 may be inserted at appropriate places in an Extended Basic program if you wish to be snapped back to text mode whenever screen printing occurs. In any case, shift-right arrow will always display the contents of Basic's text screen. Speed Commands To enter or leave Peeper's "slow motion" mode, type shift-S. There are a number of possible degrees of slowing available, which are controlled by the seven keys on the lower left of the keyboard: Z,\X,\C,\V,\B,\N, and M. Pressing one of these with the shift key down will select the degree of slowing that is in effect while in slow-motion mode, with shift-Z producing the slowest and shift-M the fastest motion. These speed modes allow degrees of slowing ranging from about half normal speed in the shift-M mode to several thousand times slower than normal in the shift-Z mode. Shift-Z mode is the default that remains in effect until some other speed is selected. Peeper will respond to a speed-select command whether or not it is currently in slow-motion mode, although the command will affect only slow-motion operation. While slow motion is in effect, if the space bar is held down, the speed will increase to that of the next faster speed mode, and will revert to the former speed when the space bar is released. This feature is useful as a "fast forward" mechanism for rapidly approaching a particular event that you wish to observe at the slower speed. A special command, shift-enter, has been provided for entering a Basic command or other input line and turning on slow motion almost simultaneously. Used instead of the Enter key alone to terminate a line of keyboard input, the shift-enter command causes slow-motion mode to be entered after a sixtieth of a second delay, with this pause being provided to allow Basic time to process the Enter key. (This is necessary because, in the slower speed modes, keyboard input, except for Peeper commands, is effectively disabled.) Occasionally, the sixtieth of a second provided will be insufficient for Basic to recognize the Enter key, and the cursor will remain at the end of the line. In such cases, use shift-S to release the slow motion and try shift-enter again. (Note: the sixtieth of a second will always be insufficient if the register trace feature, described later, is engaged.) The ultimate in slow motion is a complete freeze, which Peeper also permits. Shift-F turns the "Freeze" mode on or off. If slow-motion was in effect when shift-F was pressed, it will resume when freezing is turned off by a second shift-F command. If you use the shift-L command to go to Peeper's status page, you will see that the display includes the words FREEZE and SLOW. A plus or minus indicates the On or Off status of these options; the letter after the plus or minus in the SLOW field indicates the selected slow motion speed. A Note About How Peeper Operates Before proceeding to the remaining commands, it may be useful to have some understanding of the mechanisms by which Peeper operates. Peeper's ability to function while another program is running depends on the 6809 processor's ability to handle signals known as interrupts. Whenever an interrupt occurs, the processor stops whatever it is doing, records the current contents of all of its registers (so that it can restore them later), and jumps to an instruction representing the start of an "interrupt service routine". This service routine performs whatever functions have been specified until a "return from interrupt" instruction is encountered, which causes the contents of the registers to be restored to their entry values, and causes execution to resume at the point where it left off when the interrupt occurred. The type of interrupt used by Peeper is the "field sync IRQ", which occurs once every sixtieth of a second. This interrupt is generated by the VDG (video display generator) chip and is synchronized with the end of each "frame" on the TV screen, when the scanning beam has reached the bottom of the screen. When this type of interrupt occurs, provided that interrupts are enabled both in the 6809 processor and in the PIA (peripheral interface adapter) chip that detects the signal, processing jumps to whatever address is contained in locations $10D-$10E. (These locations are defined in ROM as containing a pointer to the IRQ service routine.) Normally, these locations contain the address of Basic's interrupt service routine, which differs according to what version of Basic (Color, Extended, or Disk) you have. In Basic, interrupt servicing times the duration of the SOUND and PLAY commands, updates the value returned by the Extended Basic TIMER function, and times the interval during which the disk motor remains on following a disk operation. Peeper changes the contents of locations $10D-E to substitute its own service routine for Basic's. Peeper's routine checks the keyboard for the commands that Peeper recognizes and performs the functions appropriate to each. It then exits to Basic's service routine so that Basic's servicing functions, as well as Peeper's, are performed. To achieve slow motion, Peeper inserts a delay loop into the service routine. For the slowest speed (the shift-Z mode), the duration of the delay loop has been selected to make the service routine last barely under a thirtieth of a second. This ensures that a new interrupt will occur practically immediately after the servicing of the previous interrupt is completed, so that only a single machine-language instruction has a chance to be executed between interrupts. Less severe degrees of slowing are achieved by reducing the duration of the delay loop to permit more processing between interrupts. Printer Output The commands discussed in the following three sections, which are concerned with various machine-language monitoring functions, all produce output both on Peeper's status page (reached by the shift-L command) and on the printer, if printing is currently enabled. Printer output may be toggled off or on by using the shift-P command; a plus or minus in the PRINT field on the status page indicates whether or not printing is currently enabled. Printing is initially on if a Yes answer was given to the "Printer Connected" question. If a No answer was given, printing is permanently disabled and future shift-P commands will have no effect. Breakpoints The shift-H command enables the setting of up to three breakpoints, and removes any previously set breakpoints (H stands for halt). This command moves the display window to the status page, where a blinking cursor will be seen in the BREAKPOINTS field. Breakpoint addresses are entered in hexadecimal notation, separated by spaces; type Enter after the final address. Shift-H followed immediately by Enter may be used to remove previous breakpoints without setting new ones. While the cursor is blinking in the BREAKPOINTS field, normal processing is suspended. After breakpoints have been entered, the shift-L command may be used to return to the previous display page and display mode if desired. When a breakpoint that you have set is encountered during program execution, the display window moves to the status page, where a blinking blue indicator will be seen in the BREAKPOINTS field immediately preceding the address where execution has been halted. Peeper goes into Freeze mode to accomplish this halt; thus, shift-F is used to resume execution by turning off the freeze. Breakpoints remain set until cleared by a shift-H command. Since the functioning of the breakpoint feature requires that Peeper be able to insert an SWI instruction at the specified address, breakpoints will not be recognized if ROM addresses have been specified. It is possible to breakpoint addresses within the Basic interpreter, but only if you have 64K and have transferred Basic to RAM. One use of the breakpoint feature is to provide an opportunity to turn on slow motion and/or program tracing (described below) at a desired point. Thus, you may find it useful to set a breakpoint at the execution address of a machine language program prior to typing EXEC, if you wish to trace execution starting at the beginning. (The execution address of a machine language program may be found by examining locations $9D-$9E after loading in the program. The "examine" feature described later provides a convenient way to do this, or you can type PRINT HEX$(256*PEEK(&H9D) + PEEK(&H9E)) from Basic.) Note that you could also, as an alternative to setting a breakpoint at the execution address, type EXEC followed by shift-enter to achieve a much more imprecise synchronization of the onset of slow motion with the start of a machine-language program. Program Tracing Features Peeper has the ability to provide a continuous trace readout on the status page. Trace output is also sent to the printer, if printing is enabled. Tracing is toggled on or off by the shift-T command; a plus or minus in the TRACE field on the status page shows whether or not tracing is currently enabled. The shift-T command does not move the display window; if you wish to observe the status page, you will need to use a shift-L command in addition. Two different trace modes, referred to as address tracing and register tracing, are provided. In address trace mode, the address of the current machine-language instruction is displayed on the status page. Previous values remain in view until the display capacity of 18 addresses is filled, after which new addresses overwrite the oldest displayed addresses. A blue cursor precedes the most recent addition to the display. If the trace is engaged while Basic is idling, the output will contain a high proportion of instances of addresses $A7D3 and $A7D5. These addresses correspond to a delay loop that Basic uses for various purposes such as deciding when to change the color of the cursor. In register trace mode, the contents of all registers and of the hardware stack are displayed. The stack contents, displayed to a depth of 9 bytes, provide valuable information for determining where a subroutine was called from, since the first few bytes of the stack will generally contain the address to which control will revert when a return from the subroutine occurs. Knowledge of the stack contents can be particularly helpful when several subroutines are called in nested fashion. Unfortunately, there is no foolproof method for distinguishing stack bytes that represent subroutine return addresses from bytes that represent registers whose contents have been pushed onto the stack. In the shift-Z slow motion mode, the trace display is updated with each machine-language instruction, providing continuous single-stepping. If you turn the Freeze option on, while remaining in shift-Z slow motion mode, one machine-language instruction will be executed with each press of the space bar (discontinuous single-stepping). Faster slow-motion modes will cause a coarser trace; that is, the faster the slow motion, the more instructions will be executed between successive updates of the trace display. The shift-A command switches to the alternate trace mode (address trace/register trace). The currently selected trace mode is indicated by an A or R following the plus or minus in the TRACE field. If occasional single instances of either type of trace output are desired, rather than continuous updating, the shift-space and shift-R commands (used with trace off) will provide respectively an individual update of the address trace or of the register trace. The trace facility, needless to say, is highly useful for debugging machine-language programs. An advantageous technique is to use the speed functions to slow down more and more as you approach a critical point you wish to observe, engaging printing just before this point. Frequently, watching the register display on the status page will be helpful in deciding when to turn on printing. For example, if you know that the X-register must count down to zero before something interesting happens, you can increase speed to "fast forward" until X is close to zero before engaging printing and going into shift-Z speed mode. Peeper's trace facility is particularly useful in developing modifications to commercial machine-language software for which no source listing is available. The trace enables you to find out which routines are active as particular things happen on your screen. This enables many modifications to be accomplished without disassembling more than a small fraction of the program. There is an unfortunate flaw in the design of the 6809 processor that interferes with the proper functioning of the single-step feature in some situations. In normal operation, without Peeper, servicing of an interrupt may occasionally be erroneously omitted. This omission occurs whenever an interrupt happens to coincide with an instruction that reads from location $FF02. Normally, this represents a relatively unlikely coincidence and there are no noticeable consequences. But while in Peeper's single-step mode, where an interrupt occurs on ^cevery^d instruction, any read from $FF02 will coincide with an interrupt, and the result will be a sixtieth of a second of normal-speed processing. In such a situation, a block of instructions will be omitted from the trace output. In most cases, instructions that read from $FF02 will be encountered only in connection with Basic's keyboard scan routine (POLCAT), where instances occur at locations $A1D6, $A1EB, and $A23D (for Color Basic 1.1 or 1.2). The effects of this problem can be minimized by placing breakpoints at instructions that follow calls to the POLCAT routine. Such a breakpoint can be placed even after POLCAT has been entered, if the critical instruction at $A1D6 has not yet been reached. In such cases, the appropriate breakpoint address can often be identified by inspection of the stack contents. Examine Mode Examine mode, which is accessed by the shift-E command, provides the capability of inspecting and changing the contents of an address that is entered from the keyboard in hexadecimal. When shift-E is typed, the display window is moved to the status page and a blinking cursor appears in the MEM EXAMINE field. Normal processing is suspended until examine mode is exited by pressing the break key. To inspect the contents of an address, enter the address followed by a slash. The contents will be displayed after the slash, with the blinking cursor appearing to the right of them. At this point, the contents may be changed if desired by typing the new contents followed either by Enter (to remain in examine mode) or by the break key (to exit examine mode). If you do not wish to change the contents, possible commands at this point are up or down arrow (to inspect the next higher or lower address), Enter (to clear the MEM EXAMINE field and prepare for entry of a new address), or Break (to exit). Peeper remembers which address was last examined, and will allow this address and its contents to be re-displayed later simply by typing a slash in a blank MEM EXAMINE field. Examine mode may also be used for changing the contents of the registers. More precisely, what can be changed is the stored set of values that will be re-inserted in the registers when interrupt servicing is complete. If you enter Freeze mode and issue a shift-R command, these register values will be displayed on the status page. After doing this, issue a shift-E command and examine the contents of the location that corresponds to the value given for S in the register display. The contents of this location should agree with the first stack byte shown at the bottom of the status display. Repeated up-arrow commands should display the subsequent stack bytes. (This provides a method for inspecting the stack contents to a depth greater than 9, incidentally.) Go back to the first stack byte (using down arrow), and press the down arrow key once more. The byte now displayed corresponds to the second two hex digits (least significant byte) of the PC register value, as you can verify from the register display. Another down arrow will give the first two digits (most significant byte) of PC. If you repeatedly press the down-arrow key, you will see that the successive bytes displayed correspond to the contents of the various registers, which are stored in memory in the same order in which they appear on your screen. Thus, to change the contents of a register (except S), just use the examine mode to change the contents of the memory address where that register's contents are stored. After exiting examine mode, the change may be verified by issuing a second shift-R command. It is strongly recommended that such changes be done only with Freeze on, and that they be verified with shift-R before unfreezing. It is sometimes useful to change the contents of the PC register, although caution should be observed here, as an ill-advised change may cause a crash. Changing the value of PC to a particular address is equivalent to executing a machine-language jump to that address. Such a jump to $AC73, the address of Basic's idle loop, will usually enable a return to Basic from a machine-language program, assuming that no critical Basic addresses have been overwritten and that the DP register is set to zero. A jump to the execution address of a machine-language program provides a way of tracing execution flow from the start of the program that may be used as an alternative to the breakpoint method discussed earlier, except that no return to Basic on RTS is provided for. Disengagement The shift-break command is used to disengage Peeper. EXEC will re-engage the program, provided that the default EXEC address has not been redefined by loading in a machine-language program since disengagement. Adding a Command to Peeper Provision has been made in Peeper to allow for the addition of a user-provided machine-language subroutine to be invoked whenever the shift-U command is given. At address $16EC are three NOP instructions that may be replaced with an LBSR or JSR to a user-supplied subroutine. Various utilities, such as a disassembler or a graphics screen print program, could be interfaced with Peeper by this method. A strategy that was employed in the design of Peeper, to maximize compatibility with other programs, was to have Peeper preserve the contents of all memory locations except for the contiguous block of locations taken up by Peeper itself. You may or may not wish to require the same criteria for a user-supplied routine, depending on the compatibility requirements of the programs to be monitored. The subroutine SWAPAL, located at address $165E, may be useful in this regard: if called at the beginning and end of a user routine, it will record and later restore the contents of all RAM addresses affected by the ROM keyboard scan and printer output routines. User-Modifiable Locations Several locations at the beginning of Peeper have been assigned values that you may wish to change in order to "customize" the program for certain applications, as outlined below. Using the start, end, and exec addresses given on the tape label (cassette version), you can save one or more custom versions, embodying any changes you wish to make. Please note that the program is distributed in unprotected (copyable) form for your convenience in making backup or customized copies for your personal use only. Location Function $1000 A zero poked here disables Peeper's relocation feature $1001-2 Substitute IRQ address; $FF in $1001 suppresses Basic's IRQ servicing $1003-4 Slow motion adjustment constant if substitute IRQ is used $1005 A zero poked here will bypass the "Printer Connected" question; Peeper will assume no printer is in use. Any value other than 0 or 255 will be used as a printer baud rate constant. $1006 Contains the number of addresses put on one print line by the address trace (normally 15) $1007 Contains the number of stack bytes (0-9) to be printed out in register trace mode (normally 9) A. Relocation Feature and 64K Operation When Peeper is executed, it copies itself to the top of available memory (excluding unneeded initialization routines) and does the machine language equivalent of Basic's command "CLEAR 200, xxxx", where "xxxx" represents the start address of the relocated Peeper. This procedure protects Peeper from being overwritten by Basic and maximizes the amount of memory available to Basic, regardless of the RAM size of your machine. If you wish to reserve memory above a certain address for machine-language use, enter a CLEAR statement to protect this area of memory prior to executing Peeper. When Peeper is then executed, it will relocate itself immediately below the protected area. For some applications, it may be desirable to disable the relocation feature and have Peeper execute directly in the address range into which it has been loaded. Peeper is relocatable, and may be loaded into whatever address range you wish to place it by using an appropriate offset with the LOADM or CLOADM command. (The supplied copy loads at a start address of $1000, which was chosen to make it easy to calculate offsets.) One application in which it is desirable to offset-load Peeper and disable relocation is if you wish Peeper to execute in high memory in a 64K machine. Locating Peeper above Basic enables the monitoring of programs that take up a full 32K, which otherwise would be impossible since there would be no place to put Peeper. In order to disable relocation, poke a zero into the first byte of the program. This address is listed as $1000 in the preceding address table, to which must be added any offset that is used in loading the program. Thus, to have Peeper load in at $E000 in a 64K machine, enter (C)LOADM "PEEPER", &HD000, then POKE &HE000,0 to disable relocation, and then type EXEC. (This assumes that you have first run a program to enable the 64K mode of operation. One such routine is given in lines 10-40 of the Basic program shown below.) Prior to executing Peeper, you may wish to save a copy that loads in directly at $E000 for future use with 64K. Alternately, if you have a disk system, the following Basic program may be used to put you into 64K mode, load in Peeper at $E000, and disable relocation. Line 60 may be replaced with EXEC if desired. 10 FOR X=&HE00 TO &HE16 20 READ H$:POKE X,VAL("&H"+H$):NEXT 30 EXEC &HE00 '64K MODE NOW ENABLED 40 DATA 1A,50,8E,80,0,B7,FF,DE,EC,84,B7,FF,DF,ED,81,8C,DF,FF,25,F1,1C,AF,39 50 LOADM"PEEPER",&HD000:POKE&HE000,0 60 CLS:PRINTTAB(4);"64K PEEPER READY TO EXEC" One caution should be observed when running Peeper in high memory when in 64K mode: do not press reset. If you do, you will no longer be in 64K mode; Basic will try to jump to an IRQ service routine that is no longer in memory that it knows about, and a crash will result. (In non-64K operation, Peeper will normally survive a reset, although interrupts will need to be re-enabled by typing EXEC if you do not have Extended Basic.) B. Other Modifiable Locations Discussion of the "substitute IRQ" feature that employs addresses $1001-2 and $1003-4 will be deferred until the sections on Peeper's compatibility requirements and use with arcade-style games. For now, it is merely noted that this advanced feature allows Peeper to be used with programs that employ their own interrupt-service routines. Poking an appropriate constant into location $1005 allows you to save a copy of Peeper that omits the printer inquiry (convenient if you have no printer), or a copy that embodies any desired baud rate constant. Rompeep Peeper does not allow you to display the contents of the Basic ROMs or of Rompack cartridges. For this purpose, a short companion program, Rompeep, has been included with Peeper. Rompeep, unlike Peeper, does not employ interrupts, and consequently cannot run along with another program as Peeper can. The commands that Rompeep recognizes are a subset of those used by Peeper: the up and down arrows (shifted and unshifted) and shift-clear perform the same functions as in Peeper, while the shift-right arrow command exits the program and returns to Basic. Rompeep's method of displaying a memory page is somewhat different than Peeper's. Rather than moving the display window around in memory as Peeper does, (which is accomplished by changing the setting of the display offset register in the SAM, or synchronous address multiplexer), Rompeep copies the desired page of memory to Basic's text page. This copying is done many times per second, so that the view of memory is a dynamic one, similar to what Peeper displays. The advantage of this method over the one used by Peeper is that ROM may be displayed. To look at the memory contained in a Rompack, it is necessary to defeat the Rompack autostart feature. This may be done by taping over two of the pins that protrude from the cartridge. If you look carefully at the pins, you will see that one pin on the upper surface is shorter than the others. The pins to tape are the ones immediately to the left of this pin, one on the upper and one on the lower surface (viewed with the pins pointing towards you). If there are any pins to the left of these, it probably will not interfere with operation to tape over them as well; in fact, leaving these latter pins taped over would be a wise precaution since the voltages to these pins can cause extensive (and expensive) damage to the computer if a Rompack is accidentally inserted with power on. Rompacks should be inserted only with power off; although the autostart can be disabled with a poke as well as with tape, the former method provides no protection from blowing out chips if the Rompack is slightly misaligned when inserted. When the taped-up Rompack has been inserted, power may be turned on and Rompeep may be loaded and executed. Compatibility Requirements for Using Peeper with Machine-Language Programs While Peeper was written to maximize compatibility with other programs, various types of incompatibilities may nevertheless be encountered. The most common type of incompatibility results when a program disables the interrupts, which Peeper requires in order to function. Most programs that disable interrupts will also be capable of running with interrupts enabled, so establishing compatibility will involve finding and removing (replacing with NOPs) the instructions that do the disabling. Interrupts can be disabled either in the processor (usually with an ORCC #$50 or ORCC #$10 instruction), or in the PIA (by storing an even number, usually $34, into location $FF03). Removing an interrupt-disabling instruction can occasionally have undesirable side effects, since there are a few locations in low memory used in Basic's interrupt servicing that the program being monitored may use for conflicting purposes. In such cases, an $FF poked into location $1001 (or $E001 if Peeper starts at $E000 in 64K mode) can be used to cause Basic's interrupt servicing to be bypassed. You will need to use POKE &HFF40,0 (or its examine mode equivalent) to shut off the disk drive motor if you have disabled Basic's interrupt servicing. The program to be monitored, which will be referred to as the target program, must also not write to the IRQ vector locations $10C-$10E; these addresses must contain a JMP instruction to Peeper's IRQ service routine. If Peeper's breakpoint function is to be used, locations $106-$108 (the SWI vector) must be preserved as well. In most cases in which a program overwrites locations $10C-$10E, it does so in order to insert its own IRQ service routine. In such cases, a special provision has been made in Peeper to make it possible to patch in Peeper's IRQ routine ahead of the target program's routine. Doing so involves finding and removing the instruction that stores the address of the target program's routine into locations $10D-$10E, usually a STX $10D or STD $10D instruction. Then, the address of the target program's IRQ routine is inserted at locations $1001-2 at the beginning of Peeper (or $E001-2 in 64K mode). This procedure will cause Peeper's service routine to be patched in as required when Peeper is executed. In addition, if it is desired that the slow motion speeds be properly calibrated and that single-stepping function properly, an adjustment must be made to the slow-motion delay constants, using Peeper addresses $1003-4 (or $E003-4). These procedures will be described in additional detail in the following section, which discusses using Peeper with arcade-style game programs. Addendum--Using the Find program Now included with Peeper is a machine-language utility program called Find that can be used to facilitate the removal of interrupt-disabling instructions from ML programs in order to achieve compatibility with Peeper. Find will locate all instances of a specified sequence of bytes within a given range of memory. It is relocatable, and requires Extended Basic. After executing Find and answering the printer inquiry with a Y or N response, you will be prompted for the start and end addresses of the region of memory to be searched. Input should be in hexadecimal. When you receive the "Bytes:" prompt, enter the sequence you wish to search for, in hex, one byte per line. After entering the last byte and receiving the subsequent ">" prompt, press the break key to perform the search. After the addresses where the sequence occurs, if any, are printed out, the program will again give a "Bytes:" prompt and you may search the same range of memory for other byte sequences without having to reenter the start and end addresses. If you wish to change the search range, pressing break without entering any byte values will cause the program to prompt for new start and end addresses. To exit Find, use the reset button. Interrupt-Disabling Byte Sequences ^k; Instruction Equivalent Byte Sequence (hex) ORCC #$50 1A, 50 (replace with 12, 12) ORCC #$10 1A, 10 (replace with 12, 12) LDA #$34,...,STA $FF03 86, 34,...,B7, FF, 03 (replace 34 with 35) LDB #$34,...,STB $FF03 C6, 34,...,F7, FF, 03 (replace 34 with 35) LDX #$mmnn,...,STX $10D 8E, mm, nn,...,BF, 01, 0D LDD #$mmnn,...,STD $10D CC, mm, nn,...,FD, 01, 0D LDU #$mmnn,...,STU $10D CE, mm, nn,...,FF, 01, 0D LDY #$mmnn,...,STY $10D 10, 8E, mm, nn,...,10, BF, 01, 0D (In all 4 cases, replace the bytes after the dots with NOPs ($12) and poke $mmnn, the address of the program's IRQ routine, into the second and third bytes of Peeper ($1001-2, or offset-adjusted equivalent). The dots that appear between some byte values indicate that the bytes need not be consecutive (although they usually are), but may be separated by an instruction or two. If you are using Peeper in 64K mode, also beware of CLR $FFDE instructions (7F, FF, DE), which disable 64K operation. These should be replaced by 3 NOPs ($12). Peeper and the Color Computer 3 Peeper requires some minor adjustments to its timing constants in order to be able to single-step properly on the CoCo 3 (i.e., without skipping any instructions). A copy of Peeper that has been modified in this fashion has been placed on the Peeper disk under the name PEEPER3.BIN.