Power20 features a built in Monitor/Debugger that works on the Macintosh side of the the emulation. Thus it possible to examine and modify the contents of the VIC-20 state without using any VIC-20 RAM. The monitor is completely invisible for the running VIC-20 program.
To start the monitor/debugger choose the menu item File/Monitor/Debugger (Cmd-G). A text window will pop up where you can enter commands (see the list of supported commands below) and view results.
By default the monitor/debuggers commands will work on the VIC-20, but you use the 'z' command (see below) to examine one of the disk drives.
To execute a command type it in one line and press <Return>. Note that you can 'recycle' old commands by moving the cursor back over an old command and pressing <Return> again or by using Cut & Paste. There is also a command history, that can be accessed using Ctrl-Up/Down.
To modify the contents of the RAM it is best to first use a command that displays the old contents in a convenient form (usually the 'm' command) and then edit the output. By pressing <Return> while the cursor is on the edited line, the memory can be modified.
Most commands expect one or two numeric parameter that can be given as C-like expressions. Values can be given in either hexadecimal (without prefix or with prefix '$' or '0x'), decimal (prefix '#') or binary (prefix '%') constants or using the CPU registers ('rA', 'rX', 'rY', 'PC', 'SP' (including the $0100 offset)) or the contents of the RAM ('RAM[xxxx]' or 'RAMb[xxxx]' for 8 bit access or 'RAMw[xxxx]' for 16 bit). MEM[xxxx] works like RAM[xxxx] but does take the current memory configuration into account. Thus MEM[xxxx] will sometimes access RAM, sometimes ROM sometime I/O Chips. The arithmetic register names ('rA', 'rX', 'rY') and RAM references can be suffixed with 's' or 'u' (e.g. 'rAs','rXu', RAMsb[xxxx]) to denote a signed or unsigned value (default: unsigned).These values can be combined with the operators '+', '-', '*', '/', '<<', '>>', '&', '^', '|', '~', '-'. All operations are performed using signed 32 bit integers. Note that (different from C) the shift operators have higher precedence than '+', '-', '*' and '/' (I believe that the C semantic is unfortunate in this point). Of course you can use parenthesis to enforce a specific order of evaluation.
The monitor supports the following commands (parameters in parenthesis are optional):
a StartAddr - Assemble
Assemble Code starting at StartAddr. All constants and addresses in the code must be given in hexadecimal. It is possible to use the common illegal opcodes. An empty line ends the assembly.
b StartAddr (EndAddr) - Binary Memory Dump
Displays the memory contents from StartAddr to EndAddr in binary notation. Set bits are denoted by '*', clear bits by '.'. This makes it easy to look at the bitmap for a character set. Change the contents of the memory by overwriting the data and pressing <Return>.
c StartAddr EndAddr CompareAddr - Compare Memory
Compare the memory contents from StartAddr to EndAddr with the memory contents of the range starting at CompareAddr. Equal and non-equal ranges of memory are reported. Note that equal ranges of less than 3 bytes that are surrounded by non-equal ranges are considered artifacts, and are suppressed in order to avoid clutter.
d StartAddr (EndAddr) - Disassemble
Disassembles the memory contents from StartAddr to EndAddr. Changes to a program are possible by overwriting the output and pressing <Return>.
f StartAddr EndAddr Bytes- Find
Find a series of bytes in a range of memory. The bytes must be given in hexadecimal notation. It is possible to use '?' as a wild card for a hex-digit. Furthermore it is possible to search for character strings. When searching for strings there is no distinction of upper/lowercase, ASCII/screen code or normal/reverse text.
Examples:f c000 c080 43 42 ?d f c000 ffff "Basic"
fa StartAddr EndAddr SearchAddr - Find Address
Find all references to the absolute address SearchAddr in the program within the memory range StartAddr to EndAddr. Again it is possible to use '?' as a wild card for a hex-digit.
Example: fa e000 ffff 900? - find all accesses to the VIC in the Kernal ROM.
fp StartAddr EndAddr Value - Find Poke
Find all locations in a range of memory, that contain a specific value. Using + instead of StartAddr EndAddr causes fp to search only in the results of the previous search.
Example: Assume you want to know where Serpentine stores the number of lives left. After starting the game you have 5 lifes. Thus fp 0800 2A00 5 will find all locations, that contain the value 5. There is quite a lot of locations (too many to sort through by hand). Now play until you loose a life (now there are 4 lives left) and use fp + 4 to find all those locations that now contain 4 and used to contain 5. There are none - Too bad ;(. Second try: If we start with 5 lives, then we have one life that is currently going on and 4 lives left. So we restart the game, and use fp 0800 2a00 4 to find all locations that contain 4. After loosing one life, we use fp + 3 to search again. Behold: There is just one match ($0924)! Sometime there might be several matches, but usually there are so few, that they can easily be sifted through by hand. We now know where Serpentine stores the number of remaining lives. We can just use m 0924 to view and update this value or use fa 0800 2a00 0924 to search for all locations where Serpentine accesses or updates this value (and then apply appropriate patches there).
Note that fp is an advanced command for skilled users. There are many ways that a game might store a value. The 'Off-by-One' problem was shown above.
It is also possible that the game does not count the number of lifes left, but the number of lifes already used (or in use). Other quantities like scores sometimes stored with an factor (e.g. if all scores are a multiple of 100 points, then there is no point in storing the two zeros, so a game may or may not divide the score by 100 before storing it). The fp command searches for the given value in binary format (little- and big-endian), in BCD format (little- and big-endian), in ASCII format and in Float format. Patience, repeated trial and guesswork are the key to success when using the fp command.
g (RegPC) - Go
Resume the execution of the VIC-20 program at address RegPC (default: at the current PC). This does not destroy the monitor window.
h - Help
Display a short summary of the monitor commands.
l (LoadAddr) - Load Data
Loads data from the Mac hard disk (*.C64, *.CBM, *.PRG or *.P00 files) into the VIC-20 RAM. Usually you will load the data to the address stored in the file, but it is possible to override this by providing a new LoadAddr. The file is selected using a Mac file selector.
lr LoadAddr - Load Raw Data
Loads data from the Mac hard disk into the VIC-20 RAM. This loads the entire(!) contents of the file into RAM, including the header data of a *.P00 file and the two leading bytes load address. Thus it is necessary to provide a new load address as a parameter to lr. The file is selected using a Mac file selector.
k StartAddr (EndAddr) - PETASCII Memory Dump
Displays the memory contents from StartAddr to EndAddr as PETASCII-characters. Change the contents of the memory by overwriting the data and pressing <Return>.
m StartAddr (EndAddr) - HEX/PETASCII Memory Dump
Displays the memory contents from StartAddr to EndAddr as hex-values and as PETASCII-characters. Change the contents of the memory by overwriting the hex-values and pressing <Return>.
n StartAddr (EndAddr) - Screen Code Dump
Displays the memory contents from StartAddr to EndAddr as VIC-20 screen codes. Change the contents of the memory by overwriting the output and pressing <Return>.
o StartAddr EndAddr Data - Fill (Occupy) Memory
Fills the memory range from StartAddr to EndAddr with the value Data.
p ("FileName") - Reset Log File
Closes the current log file, and opens a new with the given file name (default: "VIC-20 Monitor - dd.mm.yyyy" in the print file folder). Output of any command can be sent to the log file by capitalizing the command name.
r - Show CPU Registers
Displays the contents of the CPU registers. Changes are possible by overwriting the output and pressing <Return>.
s StartAddr EndAddr - Save Data
Saves the memory range StartAddr to EndAddr to the Mac hard disk. The file is selected using a Mac file selector. Depending on the files extension it will be written in either *.C64, or *.P00 file format. If you want to save the same range that was previously loaded it is not necessary to specify the StartAddr and EndAddr.
sr StartAddr EndAddr - Save Raw Data
Saves the memory range StartAddr to EndAddr to the Mac hard disk. Only the data from memory is saved, no load address or other header information is stored in the file. The file is selected using a Mac file selector.
t (RegPC) - Trace Program
The VIC-20 program at address RegPC (default: at the current PC) is executed one statement at a time. After each command the state of the CPU is displayed and Power20 waits for a key. Press Space to execute another VIC-20 instruction. Press Return to trace quickly - All information is displayed, but Power20 does not wait for a key. Press 'J' to quickly execute the remainder of the current subroutine. Press 'S' to execute the current line (a plain statement or a complete subroutine call). Press 'G' to abort trace mode and switch back to the VIC-20 window, executing code at full speed.
tb (Addr (Cnt)) (!) - Set/Clear/Show Breakpoints
Without parameters tb displays a list of all currently set breakpoints. When given just an Addr,tb sets a breakpoint at the specified address. Every time the VIC-20 reaches reaches this address, program execution will be shifted into Trace mode. If, in addition to Addr,tb also receives a Cnt it will only enter Trace mode when it program execution reaches Addr for the Cnt'th time. At that time the Breakpoint will be automatically deleted. To manually delete a single breakpoint use tb Addr!. Use tb ! to remove all breakpoints at once.
The special keywords IRQ, NMI and RESET can be used instead of Addr to create a breakpoint whenever an exception occurs.
Note: Breakpoints may fail if the VIC-20 program uses self modifying code.
tl (Scanline (RegPC)) - Trace to Scanline
Run the VIC-20 program at address RegPC (default: at the current PC)until the VIC has reached a specific Scanline (default: same as last tl command). Then change into Trace mode and execute the statements step by step. This is very useful when debugging pseudo-Raster-IRQ code.
tq (Cnt (RegPC)) - Trace Quick
Execute Cnt statements of the VIC-20 program at address RegPC (default: at the current PC) quickly. Then change to Trace mode. This helps finish long loops quickly without looking at every single iteration.
v vic - Show the state of the Video and Sound IC
Displays the state of the Video/Sound IC in an easy-to-read fashion.
v via1 | via2 - Show the state of the VIA 1 or VIA2
Displays the state of the VIA1 or VIA2 an easy-to-read fashion (including internal data from shadow registers).
w StartAddr EndAddr DestAddr - Write (Copy) Memory
Copies the contents of the memory range StartAddr to EndAddr into the memory range starting at DestAddr. This works correctly even if the source and destination ranges overlap.
x - Exit/Quit Monitor
Closes the monitor window.
z DeviceNumber - Select Device to Debug
Selects the device that is to be examined by the monitor. Selecting DeviceNumber 8-11 chooses the corresponding disk drive. All other numbers select the Commodore VIC-20.
$ HexExpr - Evaluate Hexadecimal Expression
# DecimalExpr - Evaluate Decimal Expression
% BinaryExpr - Evaluate Binary Expression
? Expression - Calculate Expression
Evaluate an expression and print its value in hexadecimal and decimal.
The output of all these commands can be sent to a log file (in addition to the screen display) by capitalizing the command name. The log file is situated in the print file folder (see 5.15 Printer for more on the print file folder) and is called "VIC-20 Monitor - dd.mm.yyyy" by default. See the 'p' command above on ways to rename the log file.