From 8aed4f81a953463350923025cd7b1d2e86b01772 Mon Sep 17 00:00:00 2001
From: stephena
Date: Tue, 13 Sep 2005 18:27:42 +0000
Subject: [PATCH] Tweaked ContextMenu so that an item is selected/committed
only when the left mouse button is pressed and released on the item (should
fix problems with accidentally selecting an item). Also added 'Escape' key
to mean "cancel/remove context menu".
Updated '-help' commandline argument to recent additions.
Huge amount of work on the documentation. It's probably not complete,
but it's turning into a project in itself.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@776 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
---
stella/Debugger.txt | 753 -----------------------
stella/docs/debugger.html | 760 ++++++++++++++++++++++++
stella/docs/stella.html | 160 +++--
stella/src/common/FrameBufferGL.cxx | 6 +-
stella/src/debugger/DebuggerParser.cxx | 4 +-
stella/src/debugger/gui/ContextMenu.cxx | 14 +-
stella/src/debugger/gui/RomWidget.cxx | 24 +-
stella/src/debugger/gui/RomWidget.hxx | 8 +-
stella/src/emucore/Settings.cxx | 22 +-
stella/src/gui/ListWidget.cxx | 10 +-
stella/src/gui/ListWidget.hxx | 5 +-
stella/src/win32/SettingsWin32.cxx | 7 +-
12 files changed, 923 insertions(+), 850 deletions(-)
delete mode 100644 stella/Debugger.txt
create mode 100644 stella/docs/debugger.html
diff --git a/stella/Debugger.txt b/stella/Debugger.txt
deleted file mode 100644
index a39769c19..000000000
--- a/stella/Debugger.txt
+++ /dev/null
@@ -1,753 +0,0 @@
-
-20050717 bkw
-
-This alpha build of Stella contains an incomplete version of the debugger.
-
-What the debugger can do:
-- Display registers and memory
-- Dump state of TIA and RIOT, with things like joystick directions and
- NUSIZx decoded into English (more-or-less).
-- Change registers/memory, including toggles for flags in P register
-- Single step/trace
-- Breakpoints - break running program and enter debugger when the
- Program Counter hits a predefined address. You can set as many
- breakpoints as you want.
-- Conditional breakpoints - Break running program when some arbitrary
- condition is true (e.g. "breakif {a == $7f && c}" will break when the
- Accumulator value is $7f and the Carry flag is true, no matter where
- in the program this happens). Unlike the cond breaks in PCAE, Stella's
- are *fast*: the emulation will run at full speed unless you use lots
- of breakif's at the same time, or have a slow CPU
-- Watches - View contents of a location/register before every
- debugger prompt.
-- Traps - Like breakpoints, but break on read/write/any access to
- *any* memory location.
-- Frame advance (automatic breakpoint at beginning of next frame)
- You can advance multiple frames with one command.
-- Disassembly
-- Support for DASM symbol files (created with DASM's -s option),
- including automatically loading symbol files if they're named
- romname.sym
-- Built-in VCS.H symbols, if no symbol file is loaded
-- Symbolic names in disassembly
-- Symbolic names accepted as input
-- Tab completion for commands and symbol names
-- Graphical editor for RIOT RAM. Acts a lot like a spreadsheet.
- Input in hex, with displays for label/decimal/binary for
- currently-selected location.
-- GUI CPU state window
-- Cheat system (similar to MAME) (still needs a way to save/load cheats)
-- Reset the 6502
-- Input and output in hex, decimal, or binary
-- Start emulator in debugger (via command-line option "-debug")
-- Save CLI session to a text file.
-- Supports hex, decimal, and binary input and output almost everywhere.
- (disassembly is still hex)
-- Support for bank switching. You can see how many banks a cart has,
- and switch banks. There's still more to be done here though.
-- Patching ROM in-place. Currently there's no way to save the patched
- ROM though.
-- Registers/memory that get changed by the CPU during debugging are
- highlighted when they're displayed
-- Scanline advance (like frame advance, break at beginning
- of next scanline).
-- TIA display is updated during step/trace, so we can see our
- scanlines being drawn as it happens. This isn't 100% perfect: unlike
- a real TIA, the one in Stella only updates when it's written to.
-- Script (batch) file support, including auto-running a script file
- named after the ROM image.
-- Saving the current debugger state to a script file (including
- breakpoints, traps, etc).
-- Built-in functions for use with "breakif", to support common conditions
- (such as breaking when the user presses Game Select...)
-- Save patched ROM ("saverom filename.bin").
-
-Planned features for Stella 2.0 release:
-- Graphical TIA tab, with register names and GUI buttons for
- various bits (e.g. click ENAM0 to turn it on). This has been started
- on already.
-- GUI Disassembly window, scrollable, with checkboxes for breakpoints
- (also perhaps 2 panes in this window so you can see 2 parts of the
- code at once)
-- Bankswitch support in the debugger for the few remaining cart types
- that aren't supported.
-- Patch ROM support for a few cart types doesn't work. Must fix.
-- Some way to control joystick/etc. input from within the debugger.
-- Source-level debugging: if a DASM .lst file is available, we'll show
- the listing in the ROM tab instead of a disassembly. This is already
- availabe in a very crude form ("loadlist" and "list" commands).
-- More "special variables" for the expression parser. Currently, you can
- use all the CPU registers and flags in expressions (e.g. "print a+1" does
- what you expect), and the pseudo-variables "_scan" and "_bank" (which
- evaluate the the current scanline and bank number). Need to add more TIA,
- RIOT registers too. Also, more functions for the builtin function lib.
-
-Future plans (post 2.0):
-- Possibly a mini-assembler
-- Support for extra RAM in Supercharger and other cart types.
-- Possibly support for recording and playing back input files, like
- MAME. This isn't a debugger feature per se, but it'll make it easier
- to reliably trigger a bug so you can debug it
-- Graphics ROM view, so you can see your sprite data (it might still
- be upside-down though :)
-- Various new GUI enhancements
-
-How to use the debugger
------------------------
-
-Pressing ` (aka backtick, backquote, grave accent) toggles the debugger on
-& off. When you exit the debugger, the emulation resumes at the current
-program counter, and continues until either a breakpoint/trap is hit,
-or the ` key is pressed again. Pressing Ctrl-Tab cycles between tabs
-from left to right, and Shift-Ctrl-Tab cycles from right to left.
-Pressing Tab cycles between widgets in the current tab.
-
-You can also enter the debugger by giving a breakpoint on the command line:
-
- ; will enter the debugger the first time the instruction at "kernel" runs
- stella -break kernel mygame.bin
-
- ; $fffc is the 6502/6507 init vector. This command will break and enter the
- ; debugger before the first 6507 instruction runs, so you can debug the
- ; startup code:
- stella -break "*($fffc)" mygame.bin
-
-
-
-Tabs:
-
-The top-level user interface uses tabs to select the current debugger
-mode. Not all the tabs are implemented yet: those that aren't will just
-show up as a blank tab.
-
-The tabs that are implemented so far:
-
-- Prompt tab
-
- This is a command-line interface, similar to the DOS DEBUG command
- or Supermon for the C=64. It shows you the current CPU state, including
- the disassembly of the instruction pointed to by the Program Counter.
- This instruction is the NEXT one that will execute, NOT the one that
- just executed!
-
- Editing keys work about like you'd expect them to: Home, End, Delete,
- arrows, etc. To scroll with the keyboard, use Shift-PageUp and
- Shift-PageDown or Shift-Up and Shift-Down arrow keys. You can also
- scroll with the mouse. Copy and paste is not (yet?) supported.
-
- To see the available commands, enter "help" or "?". Most commands can
- be abbreviated: instead of "clearbreaks", you can type "clear" or
- even just "cl". However, "c" by itself is the Toggle Carry command.
-
- Bash-style tab completion is supported for commands and labels (see below)
-
- For now, there are some functions that only exist in the prompt. We
- intend to add GUI equivalents for all (or almost all?) of the prompt
- commands by the time we release Stella 2.0. People who like command
- prompts will be able to use the prompt, but people who hate them will
- have a fully functional debugger without typing (or without typing
- much, anyway).
-
- - Status
-
- Before each prompt, you'll see a dump of the current processor
- status, plus any watches you've set (see section on watches
- below), plus a disassembly of the instruction at the current
- Program Counter. This is the next instruction that will execute;
- it hasn't been executed yet.
-
- PC=f000 A=01 X=02 Y=03 S=ff P=21/nv-bdizC Cycle 12345
- $f000 a2 ff LDX #ff ; 2
- >
-
- This is telling us a lot of information:
-
- - PC=f000 A=01 X=02 Y=03 S=ff
- The Program Counter, Accumulator, X, Y, and Stack Pointer registers.
-
- - P=21/nv-bdizC
- The Processor Status register. The "21" is the hex value of the
- register, and the "nv-bdizC" shows us the individual flags. Flags
- with capital letters are set, and lowercase means clear. In this
- example, only the Carry bit is set.
-
- - Cycle 12345
- This counter gets reset at the beginning of each frame, when
- VSYNC is strobed. In this example, we're 12345 (decimal) cycles
- past the beginning of the frame.
-
- - $f000 a2 ff LDX #ff ; 2
- Disassembly of the instruction the PC points to. This is the next
- instruction that will execute (when we exit the debugger, or via the
- "step" or "trace" commands). The "a2 ff" is the raw machine code
- for this instruction. The "; 2" is a cycle count: this instruction
- will take 2 cycles to execute.
-
- WARNING: the cycle count in the disassembly does NOT include extra
- cycles caused by crossing page boundaries. Also, Branch instructions
- are shown as 2 cycles, as though they're not going to be taken. A
- branch that's taken adds a cycle, of course.
-
- The ">" is where your commands will appear as you type them.
-
-
- - Tab completion
-
- While entering a command or label, you can type a partial name and
- press the Tab key to attempt to auto-complete it. If you've ever used
- "bash", this will be immediately familiar. If not, try it: load up
- a ROM, go to the debugger, type "print w" (but don't press Enter),
- then hit Tab. The "w" will change to "WSYNC" (since this is the only
- built-in label starting with a "w"). If there are multiple possible
- completions (try with "v" instead of "w"), you'll see a list of them,
- and your partial name will be completed as far as possible.
-
- Tab completion works on all labels: built-in, loaded from a symbol file,
- or set during debugging with the "define" command. However, it does not
- yet work on functions defined with the "function" command, nor does it
- work on filenames.
-
- - Expressions
-
- Almost every command takes a value: the "a" command takes a
- byte to stuff into the accumulator, the "break" command
- takes an address to set/clear a breakpoint at. These values
- can be as a hex constant ($ff, $1234), or as complex as
- "the low byte of the 16-bit value located at the address
- pointed to by the binary number 1010010110100101" (which
- would be "@<\1010010110100101"). You can also use registers
- and labels in expressions.
-
- You can use arithmetic and boolean operators in expressions. The
- syntax is very C-like. The operators supported are:
-
- + - * / (add, subtract, multiply, divide: 2+2 is 4)
- % (modulus/remainder: 3%2 is 1)
- & | ^ ~ (bitwise AND, OR, XOR, NOT: 2&3 is 2)
- && || ! (logical AND, OR, NOT: 2&&3 is 1, 2||0 is 0)
- ( ) (parentheses for grouping: (2+2)*3 is 12)
- * @ (byte and word pointer dereference: *$80 is the byte stored
- at location $80)
- [ ] (array-style byte pointer dereference: $80[1] is the byte
- stored at location ($80+1) or $81)
- < > (prefix versions: low and high byte. <$abcd is $cd)
- == < > <= >= !=
- (comparison: equality, less-than, greater-than, less-or-equals,
- greater-or-equals, not-equals)
- << >> (bit shifts, left and right: 1<<1 is 2, 2>>1 is 1)
-
- Division by zero is not an error: it results in zero instead.
-
- None of the operators change the values of their operands. There
- are no variable-assignment or increment/decrement operators. This
- may change in the future, which is why we used "==" for equality
- instead of just "=".
-
- The bitwise and logical boolean operators are different in that the
- bitwise operators operate on all the bits of the operand (just like
- AND, ORA, EOR in 6502 asm), while the logical operators treat their
- operands as 0 for false, non-zero for true, and return either 0 or 1.
- So $1234&$5678 results in $1230, whereas $1234&&$5678 results in 1.
- This is just like C or C++...
-
- Like some programming languages, the debugger uses prefixed characters
- to change the meaning of an expression. The prefixes are:
-
- - Dereference prefixes:
-
- - "*"
- Dereference a byte pointer. "*a" means "the byte at the address that
- the A register points to". If A is 255 (hex $ff), the result will be
- the value currently stored in memory location 255. This operator
- will be very familiar to you if you're a C or C++ programmer. It's
- equivalent to the PEEK() function in most 8-bit BASICs. Also, the
- debugger supports array-like byte dereferences: *address can be
- written as address[0]. *(address+1) can be written as address[1],
- etc.
-
- - "@"
- Dereference a pointer to a word. This is just like the "*" byte deref,
- except it refers to a 16-bit value, occupying 2 locations, in
- low-byte-first format (standard for the 6507).
-
- The following are equivalent:
-
- @address
- *address+$100**(address+1)
- address[0]+#256*address[1]
-
- (TODO: add (indirect),y and (indirect,x) syntax)
-
- - Hi/Lo Byte Prefixes
-
- - "<"
- Take the low byte of a 16-bit value. This has no effect on an 8-bit
- value: "a" is equal to ""
- Take the high byte of a 16-bit value. For 8-bit values such as
- the Accumulator, this will always result in zero. For 16-bit values,
- "<$1234" = "$12".
-
- - Number Base Prefixes
-
- - "#"
- Treat the input as a decimal number.
-
- - "$"
- Treat the input as a hex number.
-
- - "\"
- Treat the input as a binary number.
-
- These only have meaning when they come before a number, not a
- label or a register. "\1010" means 10 decimal. So do "$0a" and
- "#10". "a" by itself is always the Accumulator, no matter what
- the default base is set to.
-
- If you don't specify any number base prefix, the number is
- assumed to be in the default base. When you first start Stella,
- the default base is 16 (hexadecimal). You can change it with the
- "base" command.
-
- Remember, you can use arbitrarily complex expressions with any
- command that takes arguments (except the ones that take filenames,
- like "loadsym").
-
-
- - Breakpoints, watches and traps, oh my!
-
- - Breakpoints
-
- A breakpoint is a "hotspot" in your program that causes the emulator
- to stop emulating and jump into the debugger. You can set as many
- breakpoints as you like. The command is "break xx" where xx is any
- expression. If you've created a symbol file, you can use labels.
-
- Example: you've got a label called "kernel". To break there,
- the command is "break kernel". After you've set the breakpoint,
- exit the debugger ("quit" or click the Exit button). The emulator
- will run until it gets to the breakpoint, then it will enter the
- debugger with the Program Counter pointing to the instruction
- at the breakpoint.
-
- Breakpoints happen *before* an instruction is executed: the
- instruction at the breakpoint location will be the "next"
- instruction.
-
- To remove a breakpoint, you just run the same command you used to
- set it. In the example, "break kernel" will remove the breakpoint.
- The "break" command can be thought of as a *toggle*: it turns the
- breakpoint on & off, like a light switch.
-
- You could also use "clearbreaks" to remove all the breakpoints. Also,
- there is a "listbreaks" command that will list them all.
-
- - Conditional Breaks
-
- A conditional breakpoint causes the emulator to enter the debugger when
- some arbitrary condition becomes true. "True" means "not zero" here:
- "2+2" is considered true because it's not zero. "2-2" is false, because
- it evaluates to zero. This is exactly how things work in C and lots
- of other languages, but it might take some getting used to if you've
- never used such a language.
-
- Suppose you want to enter the debugger when the Game Reset switch is
- pressed. Looking at the Stella Programmers' Guide, we see that this
- switch is read at bit 0 of SWCHB. This bit will be 0 if the switch is
- pressed, or 1 otherwise.
-
- To have an expression read the contents of an address, we use the
- dereference operator "*". Since we're looking at SWCHB, we need
- "*SWCHB".
-
- We're only wanting to look at bit 0, so let's mask off all the other
- bits: "*SWCHB&1". The expression now evaluates to bit 0 of SWCHB. We're
- almost there: this will be 1 (true) if the switch is NOT pressed. We
- want to break if it IS pressed...
-
- So we invert the sense of the test with a logical NOT operator (which
- is the "!" operator): !(*SWCHB&1). The parentheses are necessary as
- we want to apply the ! to the result of the &, not just the first term
- (the "*SWCHB").
-
- "breakif !(*SWCHB&1)" will do the job for us. However, it's an ugly mess
- of letters, numbers, and punctuation. We can do a little better:
-
- "breakif { !(*SWCHB & 1 ) }" is a lot more readable, isn't it? If
- you're going to use readable expressions with spaces in them,
- enclose the entire expression in curly braces {}.
-
- There is one annoyance about this complex expression: once we
- remove the conditional break with "delbreakif" or "clearbreaks",
- we'd have to retype it (or search backwards with the up-arrow key)
- if we wanted to use it again.
-
- We can avoid this by defining the expression as a function, then using
- "breakif function_name":
-
- function gameReset { !(*SWCHB & 1 ) }
- breakif gameReset
-
- Now we have a meaningful name for the condition, so we can use it again.
- Not only that: we can use the function as part of a bigger expression.
- Suppose we've also defined a gameSelect function that evaluates to true
- if the Game Select switch is pressed. We want to break when the user
- presses both Select and Reset:
-
- breakif { gameReset && gameSelect }
-
- If you've defined a lot of complex functions, you probably will
- want to re-use them in future runs of the debugger. You can save
- all your functions, breakpoints, conditional breaks, and watches
- with the "save" command. If you name your saved file the same
- as the ROM filename, it'll be auto-loaded next time you load the
- same ROM in Stella. The save file is just a plain text file called
- "filename.stella", so you can edit it and add new functions, etc.
-
- Conditional breaks appear in "listbreaks", numbered starting from
- zero. You can remove a cond. break with "delbreakif number", where
- the number comes from "listbreaks".
-
- - Watches
-
- A watch is an expression that gets evaluated and printed before
- every prompt. This is useful for e.g. tracking the contents of a
- memory location while stepping through code that modifies it.
-
- You can set up to 10 watches (in future the number will be unlimited).
- Since the expression isn't evaluated until it's used, you can include
- registers: "watch *y" will show you the contents of the location
- pointed to by the Y register, even if the Y register changes.
-
- The watches are numbered. The numbers are printed along with the
- watches, so you can tell which is which. To delete a watch use the
- "delwatch" command with the watch number (1 to whatever). You can
- also delete them all with the "clearwatches" command.
-
- Note that there's no real point in watching a label or CPU register
- without dereferencing it: Labels are constants, and CPU registers
- are already visible in the prompt status.
-
- - Traps
-
- A trap is similar to a breakpoint, except that it catches
- accesses to a memory address, rather than specific location in the
- program. They're useful for finding code that modifies TIA registers
- or memory.
-
- An example: you are debugging a game, and you want to stop the
- emulation and enter the debugger whenever RESP0 is strobed. You'd use
- the command "trap RESP0" to set the trap, then exit the debugger. The
- emulator will run until the next time RESP0 is accessed (either read
- or write). Once the trap is hit, you can examine the TIA state to
- see what the actual player 0 position is, in color clocks (or you
- can in the future when we implement that feature in the TIA dump!)
-
- Unlike breakpoints, traps stop the emulation *after* the instruction
- that triggered the trap. The reason for this is simple: until the
- instruction is executed, the emulator can't know it's going to hit
- a trap. After the trap is hit, the instruction is done executing,
- and whatever effects it may have had on e.g. the TIA state have
- already happened... so we don't have a way to run the emulated CPU
- in reverse.
-
- Traps come in two varieties: read access traps and write access traps.
- It is possible to set both types of trap on the same address (that's
- what the plain "trap" command does). To set a read or write only trap,
- use "trapread" or "trapwrite". To remove a trap, you just attempt
- to set it again: the commands actually toggle the trap on & off. You
- can also get rid of all traps at once with the "cleartraps" command.
-
- Use "listtraps" to see all enabled traps.
-
- - Prompt commands:
-
- a - Set Accumulator to value xx
- bank - Show # of banks (with no args), Switch to bank (with
- 1 arg)
- base - Set default base (hex, dec, or bin)
- break - Set/clear breakpoint at address (default=pc)
- c - Carry Flag: set (to 0 or 1), or toggle (no arg)
- clearbreaks - Clear all breakpoints
- cleartraps - Clear all traps
- clearwatches - Clear all watches
- colortest - Color Test
- d - Decimal Flag: set (to 0 or 1), or toggle (no arg)
- define - Define label
- delwatch - Delete watch
- disasm - Disassemble from address (default=pc)
- dump - Dump 128 bytes of memory at address
- frame - Advance emulation by xx frames (default=1)
- help - This cruft
- listbreaks - List breakpoints
- listtraps - List traps
- listwatches - List watches
- loadstate - Load emulator state (0-9)
- loadsym - Load symbol file
- n - Negative Flag: set (to 0 or 1), or toggle (no arg)
- pc - Set Program Counter to address
- print - Evaluate and print expression in hex/dec/binary
- ram - Show RAM contents (no args), or set RAM address xx to
- value yy
- reload - Reload ROM and symbol file
- reset - Reset 6507 to init vector (does not reset TIA, RIOT)
- riot - Show RIOT timer/input status
- rom - Change ROM contents
- run - Exit debugger, return to emulator
- s - Set Stack Pointer to value xx
- saveses - Save console session to file
- savestate - Save emulator state (valid args 0-9)
- savesym - Save symbols to file
- step - Single step CPU (optionally, with count)
- tia - Show TIA state
- trace - Single step CPU (optionally, with count), subroutines
- count as one instruction
- trap - Trap read and write accesses to address
- trapread - Trap read accesses to address
- trapwrite - Trap write accesses to address
- undef - Undefine label (if defined)
- v - Overflow Flag: set (to 0 or 1), or toggle (no arg)
- watch - Print contents of address before every prompt
- x - Set X Register to value xx
- y - Set Y Register to value xx
- z - Zero Flag: set (to 0 or 1), or toggle (no arg)
-
- This list may be outdated: see the output of the "help" command
- for the current list. Commands marked with a * are unimplemented.
- Commands marked with a + are partially implemented. Most commands can
- be abbreviated just by typing a partial command: "st" for "step", or
- "f" for "frame". Where there are conflicts, generally the shortest
- name is chosen (so "tra" is "trap", not "trapread").
-
-
-- CPU tab
-
-(TODO: document this, when it's close enough to finished)
-
-
-- RAM tab
-
- This is a spreadsheet-like GUI for inspecting and changing the contents
- of the 2600's RAM. All 128 bytes of RAM are visible on the screen at
- once. You can navigate with either the mouse or the keyboard arrow keys.
- To change a RAM location, either double-click on it or press Enter while
- it's highlighted. Enter the new value (hex only for now, sorry), then
- press Enter to make the change. If you change your mind, press Escape
- and the original value will be restored.
-
- On the right there are also some buttons to do various things to the
- currently-selected memory location. The buttons are:
-
- 0 - Set the current location to zero.
- Inv - Invert the current location (toggle all its bits).
- Neg - Negate the current location (twos' complement negative).
- ++ - Increment the current location
- -- - Decrement the current location
- << - Shift the current location left. Any bits shifted off the left
- are lost (they will NOT end up in the Carry flag).
- >> - Shift the current location right, like << above.
-
-- Cheat tab
-
- This tab lets you search memory for values such as lives or remaining
- energy, but it's also very useful when debugging to determine which
- memory location holds which quantity.
-
- Currently, input must be in decimal format, and search results will be
- shown in decimal (with hex addresses).
-
- Enter a byte value into the search editbox (0-255) and click 'Search'.
- All matching address/value pairs will be shown in the listbox to the
- right. The values in the listbox may be changed using the normal
- editing operations, and the RAM will be immediately updated. If
- 'Search' is clicked and the inputbox is empty, all RAM locations
- are returned.
-
- The 'Compare' button is used to compare the given value using all
- addresses in the listbox. This may be an absolute number (such as 2),
- or a comparitive number (such as -1). Using a '+' or '-' operator
- means 'search addresses for values that have changed by that amount'.
-
- The following is an example of inspecting all addresses that have
- decreased by 1:
-
- Click 'Search' with an empty inputbox. All 128 address/values are
- returned
-
- Exit debugger mode and lose a life, let your energy decrease, or
- do whatever it is you're trying to debug
-
- Enter debugger mode again, and enter a '-1' in the inputbox
-
- Click the 'Compare' button, which compares all addresses in the
- listbox with RAM, and finds all values that have decreased by 1
- (as compared to their value in the listbox).
-
- Repeatedly following these steps may help to narrow number of
- addresses under consideration, and eventually you'll find the
- memory address you're looking for
-
- The 'Restart' button restarts the whole procedure (ie, clear the
- input and listboxes, and allows another search.
-
- (TODO: need a way to name and save/load the cheats)
-
-- TIA tab (TODO)
-
-- ROM tab (TODO)
-
-Global Buttons:
-
-There are also buttons on the right that always show up no matter which
-tab you're looking at. These are always active. They are: Step, Trace,
-Frame+1, and Exit.
-
-When you use these buttons, the prompt doesn't change. This means the
-status lines with the registers and disassembly will be "stale". You
-can update them just by pressing Enter in the prompt.
-
-You can also use the Step, Trace and Frame+1 buttons from anywhere in
-the GUI via the keyboard, with Alt-S, Alt-T and Alt-F.
-
-
-Tutorial: How to hack a ROM
----------------------------
-
-Here is a step-by-step guide that shows you how to use the debugger to
-actually do something useful. No experience with debuggers is necessary,
-but it helps to know at least a little about 6502 programming.
-
-Step 1: get the Atari Battlezone ROM image. Make sure you've got the
-regular NTSC version. Load it up in Stella and press TAB to get to
-the main menu. From there, click on "Game Information". For "Name", it
-should say "Battlezone (1983) (Atari) [!]" and for MD5Sum it should say
-"41f252a66c6301f1e8ab3612c19bc5d4". The rest of this tutorial assumes
-you're using this version of the ROM; it may or may not work with the
-PAL version, or with any of the various "hacked" versions floating around
-on the 'net.
-
-Step 2: Start the game. You begin the game with 5 lives (count the tank
-symbols at the bottom of the screen).
-
-Step 3: Enter the debugger by pressing the ` (backquote) key. Don't get
-killed before you do this, though. You should still have all 5 lives.
-
-Step 4: Go to the Cheat tab (click on Cheat). The Cheat tab will allow you
-to search RAM for values such as the number of remaining lives.
-
-Step 5: In the Cheat tab, enter "5" in the "Enter a value" box and click
-on Search. This searches RAM for your value and displays the results in
-the Address/Value list to the right. You should see two results: "00a5:
-05" and "00ba: 05". These are the only two addresses that currently have
-the value 5, so they're the most likely candidates for "number of lives"
-counter. (However, some games might actually store one less than the real
-number of lives, or one more, so you might have to experiment a bit.
-Since this is a "rigged demo", I already know Battlezone stores the
-actual number of lives. Most games do, actually).
-
-Step 6: Exit the debugger by pressing ` (backquote) again. The game will
-pick up where you left off.
-
-Step 7: Get killed! Ram an enemy tank, or let him shoot you. Wait for
-the explosion to finish. You will now have 4 lives.
-
-Step 8: Enter the debugger again. The Cheat tab will still be showing.
-In the "Enter a value" box, delete the 5 you entered earlier, and replace
-it with a 4. Click "Compare". Now the Address/Value list should only
-show one result: "00ba: 04". What we did was search within our previous
-results (the ones that were 5 before) for the new value 4. Address $00ba
-used to have the value 5, but now it has 4. This means that Battlezone
-(almost certainly) stores the current number of lives at address $00ba.
-
-Step 9: Test your theory. Go to the RAM tab and change address $ba to
-some high number like $ff (you could use the Prompt instead: enter "ram
-$ba $ff"). Exit the debugger again. You should now see lots of lives
-at the bottom of the screen (of course, there isn't room to display $ff
-(255) of them!)... play the game, get killed a few times, notice that
-you have lots of lives.
-
-Step 10: Now it's time to decide what sort of "ROM hack" we want to
-accomplish. We've found the "lives" counter for the game, so we can
-either have the game start with lots of lives, or change the game
-code so we can't get killed (AKA immortality), or change the code
-so we always have the same number of lives (so we never run out, AKA
-infinite lives). Let's go for infinite lives: it's a little harder than
-just starting with lots of lives, but not as difficult as immortality
-(for that, we have to disable the collision checking code, which means
-we have to find and understand it first!)
-
-Step 11: Set a Write Trap on the lives counter address: "trapwrite $ba"
-in the Prompt. Exit the debugger and play until you get killed. When
-you die, the trap will cause the emulator to enter the debugger with the
-Program Counter pointing to the instruction *after* the one that wrote
-to location $ba.
-
-Step 12: Once in the debugger, press Enter to refresh your prompt. The PC
-should be at address $f238, instruction "LDA $e1". You want to disassemble
-the ROM starting a few addresses before this to find the instruction
-that actually caused the write trap, so enter the command "disasm pc-5"
-(you may need to press Shift-PageUp afterwards to see the beginning of
-the disassembly). Take a look at the first few instructions. Do you see
-the one that affects the lives counter? That's right, it's the "DEC $ba"
-at location $f236.
-
-Step 13: Let's stop the DEC $ba from happening. We can't just delete the
-instruction (it would mess up the addressing of everything afterwards,
-if it were even possible), but we can replace it with some other
-instruction(s).
-
-Since we just want to get rid of the instruction, we can replace it with
-NOP (no operation). From looking at the disassembly, you can see that
-"DEC $ba" is a 2-byte long instruction, so we will need two one-byte
-NOP instructions to replace it. From reading the prompt help (the "help"
-command), you can see that the "rom" command is what we use to patch ROM.
-
-Unfortunately, Stella doesn't contain an assembler, so we can't just
-type NOP to put a NOP instruction in the code. We'll have to use the
-hex opcode instead.
-
-Now crack open your 6502 reference manual and look up the NOP
-instruction's opcode... OK, OK, I'll just tell you what it is: it's $EA
-(234 decimal). We need two of them, starting at address $f236, so our
-prompt command looks like:
-
- rom $f236 $ea $ea
-
-The debugger should respond with "changed 02 locations". If you run
-"disasm pc-5" again, you should see the two NOPs at $f236 and $f237.
-
-Step 14: Test your patch. First, set location $ba to some number of
-lives that can be displayed on the screen ("poke $ba 3" will do). Now
-exit the debugger and play the game. You should see 3 lives on the screen.
-
-Step 15: The crucial test: get killed again! After the explosion, you
-will *still* see 3 lives: Success! We've hacked Battlezone to give us
-infinite lives.
-
-Step 16: Save your work. In the prompt: "saverom bzhack.bin". You now
-have your very own infinite-lives version of Battlezone. The file will
-be saved in the current directory (NOT your ROM directory), so you might
-want to move it to your ROM directory if it isn't the current directory.
-
-Step 17: Test the new ROM: exit Stella, and re-run it. Open your ROM
-(or give its name on the command line) and play the game. You can play
-forever! It worked.
-
-Now, try the same techniques on some other ROM image (try Pac-Man). Some
-games store (lives+1) or (lives-1) instead of the actual number,
-so try searching for those if you can't seem to make it work. Also,
-some cartridge types include their own RAM. The debugger doesn't (yet)
-know how to access on-cartridge RAM, so you'll have to use the "bank" and
-"ram" commands to manually search the address space for the value you're
-looking for (future versions of the debugger will be smarter about this).
-
-If you successfully patch a ROM in the debugger, but the saved version
-won't work, or looks funny, you might need to add an entry to the
-stella.pro file, to tell Stella what bankswitch and/or TV type to use.
-That's outside the scope of this tutorial :)
-
-Of course, the debugger is useful for a lot more than cheating and
-hacking ROMs. Remember, with great power comes great responsibility,
-so you have no excuse to avoid writing that game you've been thinking
-about for so long now :)
diff --git a/stella/docs/debugger.html b/stella/docs/debugger.html
new file mode 100644
index 000000000..070d6f98a
--- /dev/null
+++ b/stella/docs/debugger.html
@@ -0,0 +1,760 @@
+
+
+ Stella Debugger
+
+
+
+Stella Integrated Debugger (a work in progress)
+
+The debugger in Stella may never be complete, as we're constantly
+adding new features requested by homebrew developers. However, even in its
+current form it's still quite powerful, and is able to boast at least one
+feature that no other 2600 debugger has; it's completely cross-platform.
+
+Here's a list of what the debugger can do so far:
+
+ - Display registers and memory
+ - Dump state of TIA and RIOT, with things like joystick directions and
+ NUSIZx decoded into English (more-or-less).
+ - Change registers/memory, including toggles for flags in P register
+ - Single step/trace
+ - Breakpoints - break running program and enter debugger when the
+ Program Counter hits a predefined address. You can set as many
+ breakpoints as you want.
+ - Conditional breakpoints - Break running program when some arbitrary
+ condition is true (e.g. "breakif {a == $7f && c}" will break when the
+ Accumulator value is $7f and the Carry flag is true, no matter where
+ in the program this happens). Unlike the cond breaks in PCAE, Stella's
+ are *fast*: the emulation will run at full speed unless you use lots
+ of breakif's at the same time, or have a slow CPU.
+ - Watches - View contents of a location/register before every
+ debugger prompt.
+ - Traps - Like breakpoints, but break on read/write/any access to
+ *any* memory location.
+ - Frame advance (automatic breakpoint at beginning of next frame)
+ You can advance multiple frames with one command.
+ - Disassembly
+ - Support for DASM symbol files (created with DASM's -s option),
+ including automatically loading symbol files if they're named
+ romname.sym
+ - Built-in VCS.H symbols, if no symbol file is loaded
+ - Symbolic names in disassembly
+ - Symbolic names accepted as input
+ - Tab completion for commands and symbol names
+ - Graphical editor for RIOT RAM. Acts a lot like a spreadsheet.
+ Input in hex, with displays for label/decimal/binary for
+ currently-selected location.
+ - GUI CPU state window
+
+ - Reset the 6502
+ - Start emulator in debugger (via command-line option "-debug")
+ - Save CLI session to a text file.
+ - Supports hex, decimal, and binary input and output almost everywhere.
+ (disassembly is still hex)
+ - Support for bank switching. You can see how many banks a cart has,
+ and switch banks. There's still more to be done here though.
+ - Registers/memory that get changed by the CPU during debugging are
+ highlighted when they're displayed.
-
+
- Scanline advance (like frame advance, break at beginning
+ of next scanline).
+ - TIA display is updated during step/trace, so we can see our
+ scanlines being drawn as it happens. This isn't 100% perfect: unlike
+ a real TIA, the one in Stella only updates when it's written to.
+ - Graphical TIA tab, with register names and GUI buttons for
+ various bits (e.g. click ENAM0 to turn it on).
+ - GUI Disassembly window, scrollable, with checkboxes for breakpoints.
+ - Script (batch) file support, including auto-running a script file
+ named after the ROM image.
+ - Saving the current debugger state to a script file (including
+ breakpoints, traps, etc).
+ - Built-in functions for use with "breakif", to support common conditions
+ (such as breaking when the user presses Game Select...)
+ - Patching ROM in-place.
+ - Save patched ROM ("saverom filename.bin").
+
+
+Future planned features (post 2.0):
+
+
+ - GUI for cheat codes (Cheetah and normal codes).
+ - Perhaps 2 panes in the disassembly window (so you can see 2 parts of the
+ code at once).
+ - Add bookmark support to disassembly window.
+ - Bankswitch support in the debugger for the few remaining cart types
+ that aren't supported.
+ - Patch ROM support for a few cart types doesn't work. Must fix.
+ - Some way to control joystick/etc. input from within the debugger.
+ - Source-level debugging: if a DASM .lst file is available, we'll show
+ the listing in the ROM tab instead of a disassembly. This is already
+ available in a very crude form ("loadlist" and "list" commands).
+ - More "special variables" for the expression parser. Currently, you can
+ use all the CPU registers and flags in expressions (e.g. "print a+1" does
+ what you expect), and the pseudo-variables "_scan" and "_bank" (which
+ evaluate the the current scanline and bank number). Need to add more TIA,
+ RIOT registers too. Also, more functions for the builtin function lib.
+ - Possibly a mini-assembler
+ - Support for extra RAM in Supercharger and other cart types.
+ - Possibly support for recording and playing back input files, like
+ MAME. This isn't a debugger feature per se, but it'll make it easier
+ to reliably trigger a bug so you can debug it.
+ - Graphics ROM view, so you can see your sprite data (it might still
+ be upside-down though :)
+ - Various new GUI enhancements
+
+
+How to use the debugger
+
+Pressing ` (aka backtick, backquote, grave accent) toggles the debugger on
+& off. When you exit the debugger, the emulation resumes at the current
+program counter, and continues until either a breakpoint/trap is hit,
+or the ` key is pressed again. Pressing Ctrl-Tab cycles between tabs
+from left to right, and Shift-Ctrl-Tab cycles from right to left.
+Pressing Tab cycles between widgets in the current tab.
+
+You can also enter the debugger by giving a breakpoint on the command line:
+
+ ; will enter the debugger the first time the instruction at "kernel" runs
+ stella -break kernel mygame.bin
+
+ ; $fffc is the 6502/6507 init vector. This command will break and enter the
+ ; debugger before the first 6507 instruction runs, so you can debug the
+ ; startup code:
+ stella -break "*($fffc)" mygame.bin
+
+
+
+Prompt tab
+
+This is a command-line interface, similar to the DOS DEBUG command
+or Supermon for the C=64. It shows you the current CPU state, including
+the disassembly of the instruction pointed to by the Program Counter.
+This instruction is the NEXT one that will execute, NOT the one that
+just executed!
+
+Editing keys work about like you'd expect them to: Home, End, Delete,
+arrows, etc. To scroll with the keyboard, use Shift-PageUp and
+Shift-PageDown or Shift-Up and Shift-Down arrow keys. You can also
+scroll with the mouse. Copy and paste is not (yet?) supported.
+
+To see the available commands, enter "help" or "?". Most commands can
+be abbreviated: instead of "clearbreaks", you can type "clear" or
+even just "cl". However, "c" by itself is the Toggle Carry command.
+
+Bash-style tab completion is supported for commands and labels (see below)
+
+For now, there are some functions that only exist in the prompt. We
+intend to add GUI equivalents for all (or almost all?) of the prompt
+commands by the time we release Stella 2.0. People who like command
+prompts will be able to use the prompt, but people who hate them will
+have a fully functional debugger without typing (or without typing
+much, anyway).
+
+Status
+
+Before each prompt, you'll see a dump of the current processor
+status, plus any watches you've set (see section on watches
+below), plus a disassembly of the instruction at the current
+Program Counter. This is the next instruction that will execute;
+it hasn't been executed yet.
+
+
+ PC=f000 A=01 X=02 Y=03 S=ff P=21/nv-bdizC Cycle 12345
+ $f000 a2 ff LDX #ff ; 2
+ >
+
+
+This is telling us a lot of information:
+
+ - PC=f000 A=01 X=02 Y=03 S=ff
+ The Program Counter, Accumulator, X, Y, and Stack Pointer registers.
+
+ - P=21/nv-bdizC
+ The Processor Status register. The "21" is the hex value of the
+ register, and the "nv-bdizC" shows us the individual flags. Flags
+ with capital letters are set, and lowercase means clear. In this
+ example, only the Carry bit is set.
+
+ - Cycle 12345
+ This counter gets reset at the beginning of each frame, when
+ VSYNC is strobed. In this example, we're 12345 (decimal) cycles
+ past the beginning of the frame.
+
+ - $f000 a2 ff LDX #ff ; 2
+ Disassembly of the instruction the PC points to. This is the next
+ instruction that will execute (when we exit the debugger, or via the
+ "step" or "trace" commands). The "a2 ff" is the raw machine code
+ for this instruction. The "; 2" is a cycle count: this instruction
+ will take 2 cycles to execute.
+
+ WARNING: the cycle count in the disassembly does NOT include extra
+ cycles caused by crossing page boundaries. Also, Branch instructions
+ are shown as 2 cycles, as though they're not going to be taken. A
+ branch that's taken adds a cycle, of course.
+
+ The ">" is where your commands will appear as you type them.
+
+
+Tab completion
+
+While entering a command or label, you can type a partial name and
+press the Tab key to attempt to auto-complete it. If you've ever used
+"bash", this will be immediately familiar. If not, try it: load up
+a ROM, go to the debugger, type "print w" (but don't press Enter),
+then hit Tab. The "w" will change to "WSYNC" (since this is the only
+built-in label starting with a "w"). If there are multiple possible
+completions (try with "v" instead of "w"), you'll see a list of them,
+and your partial name will be completed as far as possible.
+
+Tab completion works on all labels: built-in, loaded from a symbol file,
+or set during debugging with the "define" command. However, it does not
+yet work on functions defined with the "function" command, nor does it
+work on filenames.
+
+Expressions
+
+Almost every command takes a value: the "a" command takes a
+byte to stuff into the accumulator, the "break" command
+takes an address to set/clear a breakpoint at. These values
+can be as a hex constant ($ff, $1234), or as complex as
+"the low byte of the 16-bit value located at the address
+pointed to by the binary number 1010010110100101" (which
+would be "@<\1010010110100101"). You can also use registers
+and labels in expressions.
+
+You can use arithmetic and boolean operators in expressions. The
+syntax is very C-like. The operators supported are:
+
+
+ + - * / (add, subtract, multiply, divide: 2+2 is 4)
+ % (modulus/remainder: 3%2 is 1)
+ & | ^ ~ (bitwise AND, OR, XOR, NOT: 2&3 is 2)
+ && || ! (logical AND, OR, NOT: 2&&3 is 1, 2||0 is 0)
+ ( ) (parentheses for grouping: (2+2)*3 is 12)
+ * @ (byte and word pointer dereference: *$80 is the byte stored
+ at location $80)
+ [ ] (array-style byte pointer dereference: $80[1] is the byte
+ stored at location ($80+1) or $81)
+ < > (prefix versions: low and high byte. <$abcd is $cd)
+ == < > <= >= !=
+ (comparison: equality, less-than, greater-than, less-or-equals,
+ greater-or-equals, not-equals)
+ << >> (bit shifts, left and right: 1<<1 is 2, 2>>1 is 1)
+
+
+Division by zero is not an error: it results in zero instead.
+
+None of the operators change the values of their operands. There
+are no variable-assignment or increment/decrement operators. This
+may change in the future, which is why we used "==" for equality
+instead of just "=".
+
+The bitwise and logical boolean operators are different in that the
+bitwise operators operate on all the bits of the operand (just like
+AND, ORA, EOR in 6502 asm), while the logical operators treat their
+operands as 0 for false, non-zero for true, and return either 0 or 1.
+So $1234&$5678 results in $1230, whereas $1234&&$5678 results in 1.
+This is just like C or C++...
+
+Prefixes
+
+Like some programming languages, the debugger uses prefixed characters
+to change the meaning of an expression. The prefixes are:
+
+
+ - Dereference prefixes:
+
+ "*"
+ Dereference a byte pointer. "*a" means "the byte at the address that
+ the A register points to". If A is 255 (hex $ff), the result will be
+ the value currently stored in memory location 255. This operator
+ will be very familiar to you if you're a C or C++ programmer. It's
+ equivalent to the PEEK() function in most 8-bit BASICs. Also, the
+ debugger supports array-like byte dereferences: *address can be
+ written as address[0]. *(address+1) can be written as address[1],
+ etc.
+
+ "@"
+ Dereference a pointer to a word. This is just like the "*" byte deref,
+ except it refers to a 16-bit value, occupying 2 locations, in
+ low-byte-first format (standard for the 6507).
+
+ The following are equivalent:
+
+ @address
+ *address+$100**(address+1)
+ address[0]+#256*address[1]
+
+
+ (TODO: add (indirect),y and (indirect,x) syntax)
+
+
+ - Hi/Lo Byte Prefixes:
+ "<"
+ Take the low byte of a 16-bit value. This has no effect on an 8-bit
+ value: "a" is equal to "<a". However, "<$1234" equals "$34".
+
+ ">"
+ Take the high byte of a 16-bit value. For 8-bit values such as
+ the Accumulator, this will always result in zero. For 16-bit values,
+ "<$1234" = "$12".
+
+
+ - Number Base Prefixes:
+ "#"
+ Treat the input as a decimal number.
+
+ "$"
+ Treat the input as a hex number.
+
+ "\"
+ Treat the input as a binary number.
+
+ These only have meaning when they come before a number, not a
+ label or a register. "\1010" means 10 decimal. So do "$0a" and
+ "#10". "a" by itself is always the Accumulator, no matter what
+ the default base is set to.
+
+ If you don't specify any number base prefix, the number is
+ assumed to be in the default base. When you first start Stella,
+ the default base is 16 (hexadecimal). You can change it with the
+ "base" command.
+
+ Remember, you can use arbitrarily complex expressions with any
+ command that takes arguments (except the ones that take filenames,
+ like "loadsym").
+
+
+
+
+Breakpoints, watches and traps, oh my!
+
+Breakpoints
+
+A breakpoint is a "hotspot" in your program that causes the emulator
+to stop emulating and jump into the debugger. You can set as many
+breakpoints as you like. The command is "break xx" where xx is any
+expression. If you've created a symbol file, you can use labels.
+
+Example: you've got a label called "kernel". To break there,
+the command is "break kernel". After you've set the breakpoint,
+exit the debugger ("quit" or click the Exit button). The emulator
+will run until it gets to the breakpoint, then it will enter the
+debugger with the Program Counter pointing to the instruction
+at the breakpoint.
+
+Breakpoints happen *before* an instruction is executed: the
+instruction at the breakpoint location will be the "next"
+instruction.
+
+To remove a breakpoint, you just run the same command you used to
+set it. In the example, "break kernel" will remove the breakpoint.
+The "break" command can be thought of as a *toggle*: it turns the
+breakpoint on & off, like a light switch.
+
+You could also use "clearbreaks" to remove all the breakpoints. Also,
+there is a "listbreaks" command that will list them all.
+
+Conditional Breaks
+
+A conditional breakpoint causes the emulator to enter the debugger when
+some arbitrary condition becomes true. "True" means "not zero" here:
+"2+2" is considered true because it's not zero. "2-2" is false, because
+it evaluates to zero. This is exactly how things work in C and lots
+of other languages, but it might take some getting used to if you've
+never used such a language.
+
+Suppose you want to enter the debugger when the Game Reset switch is
+pressed. Looking at the Stella Programmers' Guide, we see that this
+switch is read at bit 0 of SWCHB. This bit will be 0 if the switch is
+pressed, or 1 otherwise.
+
+To have an expression read the contents of an address, we use the
+dereference operator "*". Since we're looking at SWCHB, we need
+"*SWCHB".
+
+We're only wanting to look at bit 0, so let's mask off all the other
+bits: "*SWCHB&1". The expression now evaluates to bit 0 of SWCHB. We're
+almost there: this will be 1 (true) if the switch is NOT pressed. We
+want to break if it IS pressed...
+
+So we invert the sense of the test with a logical NOT operator (which
+is the "!" operator): !(*SWCHB&1). The parentheses are necessary as
+we want to apply the ! to the result of the &, not just the first term
+(the "*SWCHB").
+
+"breakif !(*SWCHB&1)" will do the job for us. However, it's an ugly mess
+of letters, numbers, and punctuation. We can do a little better:
+
+"breakif { !(*SWCHB & 1 ) }" is a lot more readable, isn't it? If
+you're going to use readable expressions with spaces in them,
+enclose the entire expression in curly braces {}.
+
+There is one annoyance about this complex expression: once we
+remove the conditional break with "delbreakif" or "clearbreaks",
+we'd have to retype it (or search backwards with the up-arrow key)
+if we wanted to use it again.
+
+We can avoid this by defining the expression as a function, then using
+"breakif function_name":
+
+
+ function gameReset { !(*SWCHB & 1 ) }
+ breakif gameReset
+
+
+Now we have a meaningful name for the condition, so we can use it again.
+Not only that: we can use the function as part of a bigger expression.
+Suppose we've also defined a gameSelect function that evaluates to true
+if the Game Select switch is pressed. We want to break when the user
+presses both Select and Reset:
+
+
+ breakif { gameReset && gameSelect }
+
+
+If you've defined a lot of complex functions, you probably will
+want to re-use them in future runs of the debugger. You can save
+all your functions, breakpoints, conditional breaks, and watches
+with the "save" command. If you name your saved file the same
+as the ROM filename, it'll be auto-loaded next time you load the
+same ROM in Stella. The save file is just a plain text file called
+"filename.stella", so you can edit it and add new functions, etc.
+
+Conditional breaks appear in "listbreaks", numbered starting from
+zero. You can remove a cond. break with "delbreakif number", where
+the number comes from "listbreaks".
+
+Watches
+
+A watch is an expression that gets evaluated and printed before
+every prompt. This is useful for e.g. tracking the contents of a
+memory location while stepping through code that modifies it.
+
+You can set up to 10 watches (in future the number will be unlimited).
+Since the expression isn't evaluated until it's used, you can include
+registers: "watch *y" will show you the contents of the location
+pointed to by the Y register, even if the Y register changes.
+
+The watches are numbered. The numbers are printed along with the
+watches, so you can tell which is which. To delete a watch use the
+"delwatch" command with the watch number (1 to whatever). You can
+also delete them all with the "clearwatches" command.
+
+Note that there's no real point in watching a label or CPU register
+without dereferencing it: Labels are constants, and CPU registers
+are already visible in the prompt status.
+
+Traps
+
+A trap is similar to a breakpoint, except that it catches
+accesses to a memory address, rather than specific location in the
+program. They're useful for finding code that modifies TIA registers
+or memory.
+
+An example: you are debugging a game, and you want to stop the
+emulation and enter the debugger whenever RESP0 is strobed. You'd use
+the command "trap RESP0" to set the trap, then exit the debugger. The
+emulator will run until the next time RESP0 is accessed (either read
+or write). Once the trap is hit, you can examine the TIA state to
+see what the actual player 0 position is, in color clocks (or you
+can in the future when we implement that feature in the TIA dump!)
+
+Unlike breakpoints, traps stop the emulation *after* the instruction
+that triggered the trap. The reason for this is simple: until the
+instruction is executed, the emulator can't know it's going to hit
+a trap. After the trap is hit, the instruction is done executing,
+and whatever effects it may have had on e.g. the TIA state have
+already happened... so we don't have a way to run the emulated CPU
+in reverse.
+
+Traps come in two varieties: read access traps and write access traps.
+It is possible to set both types of trap on the same address (that's
+what the plain "trap" command does). To set a read or write only trap,
+use "trapread" or "trapwrite". To remove a trap, you just attempt
+to set it again: the commands actually toggle the trap on & off. You
+can also get rid of all traps at once with the "cleartraps" command.
+
+Use "listtraps" to see all enabled traps.
+
+Prompt commands:
+
+
+ a - Set Accumulator to value xx
+ bank - Show # of banks (with no args), Switch to bank (with
+ 1 arg)
+ base - Set default base (hex, dec, or bin)
+ break - Set/clear breakpoint at address (default=pc)
+ c - Carry Flag: set (to 0 or 1), or toggle (no arg)
+ clearbreaks - Clear all breakpoints
+ cleartraps - Clear all traps
+ clearwatches - Clear all watches
+ colortest - Color Test
+ d - Decimal Flag: set (to 0 or 1), or toggle (no arg)
+ define - Define label
+ delwatch - Delete watch
+ disasm - Disassemble from address (default=pc)
+ dump - Dump 128 bytes of memory at address
+ frame - Advance emulation by xx frames (default=1)
+ help - This cruft
+ listbreaks - List breakpoints
+ listtraps - List traps
+ listwatches - List watches
+ loadstate - Load emulator state (0-9)
+ loadsym - Load symbol file
+ n - Negative Flag: set (to 0 or 1), or toggle (no arg)
+ pc - Set Program Counter to address
+ print - Evaluate and print expression in hex/dec/binary
+ ram - Show RAM contents (no args), or set RAM address xx to
+ value yy
+ reload - Reload ROM and symbol file
+ reset - Reset 6507 to init vector (does not reset TIA, RIOT)
+ riot - Show RIOT timer/input status
+ rom - Change ROM contents
+ run - Exit debugger, return to emulator
+ s - Set Stack Pointer to value xx
+ saveses - Save console session to file
+ savestate - Save emulator state (valid args 0-9)
+ savesym - Save symbols to file
+ step - Single step CPU (optionally, with count)
+ tia - Show TIA state
+ trace - Single step CPU (optionally, with count), subroutines
+ count as one instruction
+ trap - Trap read and write accesses to address
+ trapread - Trap read accesses to address
+ trapwrite - Trap write accesses to address
+ undef - Undefine label (if defined)
+ v - Overflow Flag: set (to 0 or 1), or toggle (no arg)
+ watch - Print contents of address before every prompt
+ x - Set X Register to value xx
+ y - Set Y Register to value xx
+ z - Zero Flag: set (to 0 or 1), or toggle (no arg)
+
+
+This list may be outdated: see the output of the "help" command
+for the current list. Commands marked with a * are unimplemented.
+Commands marked with a + are partially implemented. Most commands can
+be abbreviated just by typing a partial command: "st" for "step", or
+"f" for "frame". Where there are conflicts, generally the shortest
+name is chosen (so "tra" is "trap", not "trapread").
+
+
+CPU Widget
+
+FIXME: document this
+
+
+RAM Widget
+
+This is a spreadsheet-like GUI for inspecting and changing the contents
+of the 2600's RAM. All 128 bytes of RAM are visible on the screen at
+once. You can navigate with either the mouse or the keyboard arrow keys.
+To change a RAM location, either double-click on it or press Enter while
+it's highlighted. Enter the new value (hex only for now, sorry), then
+press Enter to make the change. If you change your mind, press Escape
+and the original value will be restored.
+
+Nearby there are also some buttons to do various things to the
+currently-selected memory location. The buttons are:
+
+
+ 0 - Set the current location to zero.
+ Inv - Invert the current location (toggle all its bits).
+ Neg - Negate the current location (twos' complement negative).
+ ++ - Increment the current location
+ -- - Decrement the current location
+ << - Shift the current location left. Any bits shifted off the left
+ are lost (they will NOT end up in the Carry flag).
+ >> - Shift the current location right, like << above.
+
+
+This widget also lets you search memory for values such as lives or remaining
+energy, but it's also very useful when debugging to determine which
+memory location holds which quantity.
+
+To search RAM, click 'Search' and enter a byte value into the search editbox (0-255).
+All matching values will be highlighted in the RAM widget. If 'Search' is clicked
+and input is empty, all RAM locations are searched.
+
+The 'Compare' button is used to compare the given value using all
+addresses currently highlighted. This may be an absolute number (such as 2),
+or a comparitive number (such as -1). Using a '+' or '-' operator
+means 'search addresses for values that have changed by that amount'.
+
+The following is an example of inspecting all addresses that have
+decreased by 1:
+
+
+ - Click 'Search' with empty input. All 128 address/values are highlighted
+ - Exit debugger mode and lose a life, let your energy decrease, or
+ do whatever it is you're trying to debug
+ - Enter debugger mode again, click 'Compare' and and enter a '-1' for input.
+ This finds all values that have decreased by 1 (as compared to their current
+ values)
+ - Repeatedly following these steps may help to narrow number of
+ addresses under consideration, and eventually you'll find the
+ memory address you're looking for
+ - The 'Reset' button restarts the whole procedure (ie, clear the highlighted
+ addresses and allow another search
+
+
+TIA Tab
+
+FIXME
+
+ROM Widget
+
+FIXME
+
+Global Buttons
+
+There are also buttons on the right that always show up no matter which
+tab you're looking at. These are always active. They are: Step, Trace,
+Frame+1, Scan+1 and Exit.
+
+When you use these buttons, the prompt doesn't change. This means the
+status lines with the registers and disassembly will be "stale". You
+can update them just by pressing Enter in the prompt.
+
+You can also use the Step, Trace, Frame+1 and Scan+1 buttons from anywhere in
+the GUI via the keyboard, with Alt-S, Alt-T, Alt-F and Alt-L.
+
+
+Tutorial: How to hack a ROM
+
+Here is a step-by-step guide that shows you how to use the debugger to
+actually do something useful. No experience with debuggers is necessary,
+but it helps to know at least a little about 6502 programming.
+
+
+ - get the Atari Battlezone ROM image. Make sure you've got the
+ regular NTSC version. Load it up in Stella and press TAB to get to
+ the main menu. From there, click on "Game Information". For "Name", it
+ should say "Battlezone (1983) (Atari) [!]" and for MD5Sum it should say
+ "41f252a66c6301f1e8ab3612c19bc5d4". The rest of this tutorial assumes
+ you're using this version of the ROM; it may or may not work with the
+ PAL version, or with any of the various "hacked" versions floating around
+ on the 'net.
+
+ - Start the game. You begin the game with 5 lives (count the tank
+ symbols at the bottom of the screen).
+
+ - Enter the debugger by pressing the ` (backquote) key. Don't get
+ killed before you do this, though. You should still have all 5 lives.
+
+ - In the RAM Widget, click the "Search" button and enter "5" for input.
+ This searches RAM for your value and highlights all addresses that match
+ the input. You should see two addresses highlighted: "00a5" and "00ba".
+ These are the only two addresses that currently have the value 5, so they're
+ the most likely candidates for "number of lives" counter. (However, some
+ games might actually store one less than the real number of lives, or
+ one more, so you might have to experiment a bit. Since this is a "rigged
+ demo", I already know Battlezone stores the actual number of lives.
+ Most games do, actually).
+
+ - Exit the debugger by pressing ` (backquote) again. The game will
+ pick up where you left off.
+
+ - Get killed! Ram an enemy tank, or let him shoot you. Wait for
+ the explosion to finish. You will now have 4 lives.
+
+ - Enter the debugger again. Click the "Compare" button in RAM widget and enter
+ a value of 4. Now the RAM widget should only show one highlighted address:
+ "00ba". What we did was search within our previous results (the ones that
+ were 5 before) for the new value 4. Address $00ba used to have the value 5,
+ but now it has 4. This means that Battlezone (almost certainly) stores the
+ current number of lives at address $00ba.
+
+ - Test your theory. Go to the RAM widget and change address $ba to
+ some high number like $ff (you could use the Prompt instead: enter "ram
+ $ba $ff"). Exit the debugger again. You should now see lots of lives
+ at the bottom of the screen (of course, there isn't room to display $ff
+ (255) of them!)... play the game, get killed a few times, notice that
+ you have lots of lives.
+
+ - Now it's time to decide what sort of "ROM hack" we want to
+ accomplish. We've found the "lives" counter for the game, so we can
+ either have the game start with lots of lives, or change the game
+ code so we can't get killed (AKA immortality), or change the code
+ so we always have the same number of lives (so we never run out, AKA
+ infinite lives). Let's go for infinite lives: it's a little harder than
+ just starting with lots of lives, but not as difficult as immortality
+ (for that, we have to disable the collision checking code, which means
+ we have to find and understand it first!)
+
+ - Set a Write Trap on the lives counter address: "trapwrite $ba"
+ in the Prompt. Exit the debugger and play until you get killed. When
+ you die, the trap will cause the emulator to enter the debugger with the
+ Program Counter pointing to the instruction *after* the one that wrote
+ to location $ba.
+
+ - Once in the debugger, look at the ROM widget. The PC should be at address
+ $f238, instruction "LDA $e1". You want to examine a few instructions before
+ the PC, so scroll up using the mouse or arrow keys. Do you see
+ the one that affects the lives counter? That's right, it's the "DEC $ba"
+ at location $f236.
+
+ - Let's stop the DEC $ba from happening. We can't just delete the
+ instruction (it would mess up the addressing of everything afterwards,
+ if it were even possible), but we can replace it with some other
+ instruction(s).
+
+
Since we just want to get rid of the instruction, we can replace it with
+ NOP (no operation). From looking at the disassembly, you can see that
+ "DEC $ba" is a 2-byte long instruction, so we will need two one-byte
+ NOP instructions to replace it. From reading the prompt help (the "help"
+ command), you can see that the "rom" command is what we use to patch ROM.
+
+
Unfortunately, Stella doesn't contain an assembler, so we can't just
+ type NOP to put a NOP instruction in the code. We'll have to use the
+ hex opcode instead.
+
+
Now crack open your 6502 reference manual and look up the NOP
+ instruction's opcode... OK, OK, I'll just tell you what it is: it's $EA
+ (234 decimal). We need two of them, so the bytes to insert will look like:
+
+
$ea $ea
+
+ Select the line at address $f236 and enter 'ROM patch' mode. This is done
+ by either double-clicking the line, or pressing enter. Then delete the bytes
+ with backspace key and enter "ea ea". Another way to do this would have been
+ to enter "rom $f236 $ea $ea" in the Prompt widget.
+
+
+ - Test your patch. First, set location $ba to some number of
+ lives that can be displayed on the screen ("poke $ba 3" or enter directly into
+ the RAM widget). Now exit the debugger and play the game. You should see 3
+ lives on the screen.
+
+ - The crucial test: get killed again! After the explosion, you
+ will *still* see 3 lives: Success! We've hacked Battlezone to give us
+ infinite lives.
+
+ - Save your work. In the prompt: "saverom bzhack.bin". You now
+ have your very own infinite-lives version of Battlezone. The file will
+ be saved in the current directory (NOT your ROM directory), so you might
+ want to move it to your ROM directory if it isn't the current directory.
+ This can also be accomplished by right-clicking on the ROM widget and
+ selected 'Save ROM'.
+
+ - Test the new ROM: exit Stella, and re-run it. Open your ROM
+ (or give its name on the command line) and play the game. You can play
+ forever! It worked.
+
+
+Now, try the same techniques on some other ROM image (try Pac-Man). Some
+games store (lives+1) or (lives-1) instead of the actual number,
+so try searching for those if you can't seem to make it work. Also,
+some cartridge types include their own RAM. The debugger doesn't (yet)
+know how to access on-cartridge RAM, so you'll have to use the "bank" and
+"ram" commands to manually search the address space for the value you're
+looking for (future versions of the debugger will be smarter about this).
+
+If you successfully patch a ROM in the debugger, but the saved version
+won't work, or looks funny, you might need to add an entry to the
+stella.pro file, to tell Stella what bankswitch and/or TV type to use.
+That's outside the scope of this tutorial :)
+
+Of course, the debugger is useful for a lot more than cheating and
+hacking ROMs. Remember, with great power comes great responsibility,
+so you have no excuse to avoid writing that game you've been thinking
+about for so long now :)
diff --git a/stella/docs/stella.html b/stella/docs/stella.html
index d2fe75eed..104e3a737 100644
--- a/stella/docs/stella.html
+++ b/stella/docs/stella.html
@@ -35,7 +35,7 @@
- February 1999 - (FIXME)February 2005
+ February 1999 - September 2005
The Stella Team
Stella Homepage
@@ -230,14 +230,22 @@
(the Windows and Linux frontends) have been discontinued. The OSX
port now uses the launcher as well.
- FIXME - add info about integrated debugger
+ Added an integrated debugger for game developers. This is currently
+ the first version of a debugger in Stella, but it's already quite
+ usable.
- Further consolidation and integration of SDL. This should lead to
- faster operation and a more consistent look for all ports.
+ Added new sound subsystem, which is much faster and more accurate. Related
+ to this, added stereo sound output (used by some homebrew games).
Added ZIP support. Stella can now open ROM's compressed in zip
format.
+ Reworked properties system to use both a system-wide 'stella.pro' and
+ a per-user 'user.pro' properties files. Changes made by the user
+ and stored in 'user.pro' are no longer erased when upgrading Stella.
+
+ Added support for cartridges with 3E bankswitching format.
+
Added Alt/Shift-Cmd z, x, c, v, b, n keys to enable/disable the
P0, P1, M0, M1, BL, PL bits in the TIA, respectively.
@@ -266,15 +274,22 @@
Removed mergeprops commandline argument, since there are now
dedicated keys to do either save or merge game properties.
- Removed grabmouse and hidecursor commandline arguments.
- Stella will now automatically decide when to use these settings.
- You can still use Ctrl/Cmd g to grab/ungrab the mouse.
+ Removed hidecursor commandline argument. Stella will now
+ automatically decide when to use this setting.
Fixed framerate when switching between NTSC and PAL modes. Stella
- now uses the correct framerate based on the format of the ROM.
+ now uses the correct framerate based on the format of the ROM,
+ in terms of both video and audio.
+
+ Added 'configure' support to the build process for both Linux and
+ Win32 (using MinGW). Developers can now use the familiar 'configure;
+ make; make install' commands to compile Stella.
+
+ Further consolidation and integration of SDL. This should lead to
+ faster operation and a more consistent look for all ports.
Fixed some 64-bit issues. Stella now compiles and runs correctly
- on AMD64 and PPC64 systems.
+ on AMD64 and PPC64 Linux systems.
Updated the Stella manual with pictures of the new integrated GUI.
@@ -284,8 +299,8 @@
- High speed emulation using optimized C++ code
- - Supports high quality sound emulation using Ron Fries' TIA Sound Emulation
- library
+ - Supports high quality sound emulation using code derived from Ron Fries'
+ TIA Sound Emulation library, including stereo sound support
- Emulates the Atari 2600 Joystick Controllers using your computer's keyboard
or joysticks
- Emulates the Atari 2600 Keyboard Controllers using your computer's keyboard
@@ -349,7 +364,7 @@
- Linux Kernel 2.4.x, Linux Kernel 2.6.x is highly recommended
- GNU C++ compiler version 2.95 and the make utility are required for compiling
- the Stella source code; GNU C++ compiler version 3.2.x or later is highly
+ the Stella source code; GNU C++ compiler version 3.2.x/4.x or later is highly
recommended
- Pentium class machine required (Stella may compile on other
architectures, but it hasn't been extensively tested)
@@ -364,6 +379,8 @@
- Mac OSX 10.1 or Above
- 500 MHz G4 PPC processor or above (Stella may work with a G3
processor, but this is still a work-in-progress)
+ - OpenGL capable video card. Software rendering mode is still available,
+ but as of OSX 10.4 is substandard compared to OpenGL.
@@ -402,15 +419,14 @@
- Extract files from the distribution:
tar zxvf stella-release-src.tar.gz
- - Change directories to the stella-release/src/build directory
- - Edit the makefile to meet your needs
+ - Change directories to the stella-release directory
+
+ - Configure the build with the following command:
+
./configure (--help for list of options)
- Build the executable with the following command:
-
make linux (or make linux-gl)
- - Copy the executable to a directory that's in your path:
-
cp stella /usr/local/bin
- - Copy the supplied stella.pro properties file to the system-wide location:
-
cp stella.pro /etc
or to your home directory:
- mkdir ~/.stella
cp stella.pro ~/.stella
+ make
+ - Install the executable with the following command:
+
make install
- Source RPM (stella-release-1.src.rpm)
@@ -442,19 +458,11 @@
- Extract files from the distribution using Winzip,
Total Commander, or some other archiving program that supports
gzipped tar files
- - If compiling the Stella executable using MinGW:
-
+ - If compiling the Stella executable using MinGW, use the same commands
+ as specified under Linux/UNIX - Compressed tarball
- If compiling using Visual C++ 7:
- - Open the stella-release/src/win32/Stella_Emulator.sln
+
- Open the stella-release/src/win32/Stella.sln
file using Visual C++ 7
- Build the 'Stella' solution
- Copy the Stella.exe and stella.pro files
@@ -562,8 +570,8 @@
Once a ROM directory has been selected, clicking 'Reload' will update the
- ROM listing. You can start emulation by selecting a ROM and pressing 'Enter',
- clicking 'Play' or double-clicking a ROM.
+ ROM listing. You can start emulation by selecting a ROM and pressing 'Enter'
+ or clicking 'Play', or double-clicking a ROM.
Command Line
@@ -589,12 +597,6 @@
Use SDL software or OpenGL rendering mode. |
-
- -video_driver <windib|directx> |
- Use the specified video driver. Windows works best with 'windib'.
- Currently, only Windows makes use of this argument. |
-
-
-gl_filter <nearest|linear> |
OpenGL mode only. Use GL_NEAREST or GL_LINEAR filtering.
@@ -627,6 +629,11 @@
| Play the game in fullscreen mode. |
+
+ -center <0|1> |
+ Centers game window (if possible). |
+
+
-grabmouse <0|1> |
Keeps the mouse in the game window. |
@@ -645,8 +652,13 @@
- -sound <0|1> |
- Disable or enable sound. |
+ -sound <1|0> |
+ Enable or disable sound generation. |
+
+
+
+ -channels <1|2> |
+ Enable mono or stereo sound. |
@@ -670,12 +682,6 @@
Shows some game info while Stella is running. |
-
- -mergeprops <0|1> |
- Save the current properties to a separate file in the users' home directory,
- or merge them into the users' stella.pro file. |
-
-
-accurate <0|1> |
Linux only, may be removed in future versions. Use this when
@@ -723,6 +729,31 @@
| Description |
+
+ -debugheight <number> |
+ Set height of debugger in lines of text (currently not 100% working) |
+
+
+
+ -debug |
+ Immediately jump to debugger mode when starting Stella. |
+
+
+
+ -holdreset |
+ Start the emulator with the Game Reset switch held down. |
+
+
+
+ -holdselect |
+ Start the emulator with the Game Select switch held down. |
+
+
+
+ -holdbutton0 |
+ Start the emulator with the left joystick button held down. |
+
+
-pro <props file> |
Use the given properties file instead of stella.pro. |
@@ -1483,7 +1514,7 @@
Toggle fullscreen/windowed mode |
Alt + Enter |
- Shift-Cmd + Enter(FIXME) |
+ Cmd + Enter |
@@ -1585,7 +1616,9 @@
-FIXME - add info and snapshots for debugger
+
+ Have a look at this page for integrated debugger
+ documentation.
@@ -1597,20 +1630,27 @@ FIXME - add info and snapshots for debugger
You must use the included stella.pro file. Otherwise, the emulator
will try to guess the best settings for the game.
+
As of Stella 2.0, the properties file handling has changed. Stella now uses
+ two properties files; a system-wide stella.pro and a per-user user.pro.
+ The system-wide file will not be modified by Stella, and is used as a default
+ database of properties. The per-user file will contain all properties 'merged' by
+ the user (by pressing Alt-s while a game is running). So this means that when
+ you upgrade Stella and stella.pro, your personal profile settings are preserved.
+
Linux/Unix
- The Linux and Unix versions of Stella looks for the property file
- in your $HOME/.stella directory. If this file is not found there,
- Stella will look in the /etc/ directory.
+
The Linux and Unix versions of Stella looks for the system properties file
+ in /etc/stella.pro and your personal properties file in
+ $HOME/.stella/user.pro.
Macintosh
- The Mac version of Stella looks for the property file in the
+
The Mac version of Stella looks for the properties file(s) in the
directory containing the application.
Windows
- The Windows version of Stella looks for the property file in the same directory
+
The Windows version of Stella looks for the properties file(s) in the directory
containing the application. Future versions of Stella for Windows may look in
user-specific locations (C:\Documents and Settings\...).
@@ -1698,6 +1738,14 @@ FIXME - add info and snapshots for debugger
Stella will probably allow the user to view this information.
+
+ Cartridge.Sound: |
+ This property determines if the game should use 1 or 2 channels for
+ sound output. All original Atari 2600 machines supported 1 channel only,
+ but some homebrew games have been written to take advantage of stereo
+ sound. The value of this property must be Mono or Stereo. |
+
+
Cartridge.Type: |
This property indicates the bank-switching type for the game.
@@ -2028,7 +2076,9 @@ FIXME - add info and snapshots for debugger
| Brian Watson |
Helped with getting the illegal CPU instruction support working with Stella.
Brian also submitted a number of other changes, such as debugger support, which
- will be integrated into the 1.5 release of Stella. |
+ have been finally integrated into the 2.0 release of Stella. Without
+ a doubt, there would be no debugger support in Stella if not for the
+ tireless work of Brian.
diff --git a/stella/src/common/FrameBufferGL.cxx b/stella/src/common/FrameBufferGL.cxx
index f1f629507..fd9bacdfc 100644
--- a/stella/src/common/FrameBufferGL.cxx
+++ b/stella/src/common/FrameBufferGL.cxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: FrameBufferGL.cxx,v 1.41 2005-09-06 19:42:35 stephena Exp $
+// $Id: FrameBufferGL.cxx,v 1.42 2005-09-13 18:27:42 stephena Exp $
//============================================================================
#ifdef DISPLAY_OPENGL
@@ -254,8 +254,6 @@ void FrameBufferGL::preFrameUpdate()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::postFrameUpdate()
{
- // Do the following twice, since OpenGL mode is double-buffered,
- // and we need the contents placed in both buffers
if(theRedrawTIAIndicator || myDirtyFlag)
{
// Texturemap complete texture to surface so we have free scaling
@@ -272,7 +270,7 @@ void FrameBufferGL::postFrameUpdate()
glTexCoord2f(myTexCoord[0], myTexCoord[3]); glVertex2i(0, h);
glEnd();
- // Now show all changes made to the textures
+ // Now show all changes made to the texture
SDL_GL_SwapBuffers();
myDirtyFlag = false;
diff --git a/stella/src/debugger/DebuggerParser.cxx b/stella/src/debugger/DebuggerParser.cxx
index 5941a2918..c6af882ce 100644
--- a/stella/src/debugger/DebuggerParser.cxx
+++ b/stella/src/debugger/DebuggerParser.cxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: DebuggerParser.cxx,v 1.76 2005-08-20 18:19:52 urchlay Exp $
+// $Id: DebuggerParser.cxx,v 1.77 2005-09-13 18:27:42 stephena Exp $
//============================================================================
#include "bspf.hxx"
@@ -1534,7 +1534,7 @@ void DebuggerParser::executeRom() {
// "run"
void DebuggerParser::executeRun() {
- debugger->saveOldState(); // FIXME - why is this here?
+ debugger->saveOldState();
debugger->quit();
commandResult = "exiting debugger";
}
diff --git a/stella/src/debugger/gui/ContextMenu.cxx b/stella/src/debugger/gui/ContextMenu.cxx
index d2ad8a638..8d5b171ca 100644
--- a/stella/src/debugger/gui/ContextMenu.cxx
+++ b/stella/src/debugger/gui/ContextMenu.cxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: ContextMenu.cxx,v 1.1 2005-08-31 19:15:10 stephena Exp $
+// $Id: ContextMenu.cxx,v 1.2 2005-09-13 18:27:42 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@@ -75,8 +75,15 @@ const string& ContextMenu::getSelectedString() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::handleMouseDown(int x, int y, int button, int clickCount)
{
+ // Only do a selection when the left button is in the dialog
if(button == 1)
- sendSelection();
+ {
+ x += getAbsX(); y += getAbsY();
+ if(x >= _x && x <= _x+_w && y >= _y && y <= _y+_h)
+ sendSelection();
+ else
+ parent()->removeDialog();
+ }
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -105,6 +112,9 @@ void ContextMenu::handleKeyDown(int ascii, int keycode, int modifiers)
{
switch(keycode)
{
+ case 27: // escape
+ parent()->removeDialog();
+ break;
case '\n': // enter/return
case '\r':
sendSelection();
diff --git a/stella/src/debugger/gui/RomWidget.cxx b/stella/src/debugger/gui/RomWidget.cxx
index aae9307bf..26cd2dbf2 100644
--- a/stella/src/debugger/gui/RomWidget.cxx
+++ b/stella/src/debugger/gui/RomWidget.cxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: RomWidget.cxx,v 1.3 2005-09-07 18:34:52 stephena Exp $
+// $Id: RomWidget.cxx,v 1.4 2005-09-13 18:27:42 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@@ -64,7 +64,7 @@ void RomWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
switch(cmd)
{
case kListScrolledCmd:
- incrementalUpdate();
+ incrementalUpdate(data, myRomList->rows());
break;
case kListItemChecked:
@@ -92,21 +92,25 @@ void RomWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomWidget::loadConfig()
{
+cerr << " ==> RomWidget::loadConfig()\n";
+
+ Debugger& dbg = instance()->debugger();
+
// Only reload full bank when necessary
-// if(myFirstLoad || myCurrentBank != instance()->debugger().getBank())
-// FIXME - always do a full reload for now, will optimize later
- if(true)
+ if(myFirstLoad || myCurrentBank != instance()->debugger().getBank())
{
initialUpdate();
myFirstLoad = false;
}
else // only reload what's in current view
{
- incrementalUpdate();
+ incrementalUpdate(myRomList->currentPos(), myRomList->rows());
}
+ myCurrentBank = dbg.getBank();
+
// Update romlist to point to current PC
- int pc = instance()->debugger().cpuDebug().pc();
+ int pc = dbg.cpuDebug().pc();
AddrToLine::iterator iter = myLineList.find(pc);
if(iter != myLineList.end())
myRomList->setHighlighted(iter->second);
@@ -117,8 +121,6 @@ void RomWidget::initialUpdate()
{
Debugger& dbg = instance()->debugger();
- myCurrentBank = dbg.getBank();
-
// Fill romlist the current bank of source or disassembly
if(mySourceAvailable)
; // FIXME
@@ -131,7 +133,7 @@ void RomWidget::initialUpdate()
StringList label, data, disasm;
BoolArray state;
- // Disassemble entire bank (up to 4096 lines)
+ // Disassemble entire bank (up to 4096 lines) and invalidate all lines
dbg.disassemble(myAddrList, label, data, disasm, 0xf000, 4096);
for(unsigned int i = 0; i < data.size(); ++i)
state.push_back(false);
@@ -146,7 +148,7 @@ void RomWidget::initialUpdate()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void RomWidget::incrementalUpdate()
+void RomWidget::incrementalUpdate(int line, int rows)
{
}
diff --git a/stella/src/debugger/gui/RomWidget.hxx b/stella/src/debugger/gui/RomWidget.hxx
index 58733baaa..dade7876d 100644
--- a/stella/src/debugger/gui/RomWidget.hxx
+++ b/stella/src/debugger/gui/RomWidget.hxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: RomWidget.hxx,v 1.2 2005-09-07 18:34:52 stephena Exp $
+// $Id: RomWidget.hxx,v 1.3 2005-09-13 18:27:42 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@@ -47,7 +47,7 @@ class RomWidget : public Widget, public CommandSender
private:
void initialUpdate();
- void incrementalUpdate();
+ void incrementalUpdate(int line, int rows);
void setBreak(int data);
void setPC(int data);
@@ -63,6 +63,10 @@ class RomWidget : public Widget, public CommandSender
/** List of line numbers indexed by address */
AddrToLine myLineList;
+ /** Indicates whether a given line is valid or not;
+ Invalid lines need to be disassembled again */
+ BoolArray myLineValid;
+
bool myFirstLoad;
bool mySourceAvailable;
int myCurrentBank;
diff --git a/stella/src/emucore/Settings.cxx b/stella/src/emucore/Settings.cxx
index 95e52c6d4..36dd46a09 100644
--- a/stella/src/emucore/Settings.cxx
+++ b/stella/src/emucore/Settings.cxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: Settings.cxx,v 1.59 2005-09-11 15:44:51 stephena Exp $
+// $Id: Settings.cxx,v 1.60 2005-09-13 18:27:42 stephena Exp $
//============================================================================
#include
@@ -39,7 +39,6 @@ Settings::Settings(OSystem* osystem)
// Now fill it with options that are common to all versions of Stella
set("video", "soft");
- set("video_driver", "");
set("gl_filter", "nearest");
set("gl_aspect", "2.0");
@@ -47,8 +46,8 @@ Settings::Settings(OSystem* osystem)
set("zoom", "2");
set("fullscreen", "false");
- set("grabmouse", "false");
set("center", "true");
+ set("grabmouse", "false");
set("palette", "standard");
set("debugheight", "0");
@@ -255,7 +254,6 @@ void Settings::usage()
<< " soft SDL software mode\n"
#ifdef DISPLAY_OPENGL
<< " gl SDL OpenGL mode\n"
- << " -video_driver SDL Video driver (see manual).\n"
<< endl
<< " -gl_filter Type is one of the following:\n"
<< " nearest Normal scaling (GL_NEAREST)\n"
@@ -266,22 +264,19 @@ void Settings::usage()
#endif
<< " -zoom Makes window be 'size' times normal\n"
<< " -fullscreen <1|0> Play the game in fullscreen mode\n"
- << " -grabmouse <1|0> Keeps the mouse in the game window\n"
<< " -center <1|0> Centers game window (if possible)\n"
+ << " -grabmouse <1|0> Keeps the mouse in the game window\n"
<< " -palette \n"
<< " -framerate Display the given number of frames per second\n"
- << " -debug <1|0> Start in the debugger\n"
- << " -debugheight Set height of debugger in lines of text (NOT pixels)\n"
- << " -holdreset Start the emulator with the Game Reset switch held down\n"
- << " -holdselect Start the emulator with the Game Select switch held down\n"
- << " -holdbutton0 Start the emulator with the left joystick button held down\n"
+ << endl
#ifdef SOUND_SUPPORT
<< " -sound <1|0> Enable sound generation\n"
<< " -channels <1|2> Enable mono or stereo sound\n"
<< " -fragsize The size of sound fragments (must be a power of two)\n"
<< " -volume Set the volume (0 - 100)\n"
+ << endl
#endif
<< " -paddle <0|1|2|3> Indicates which paddle the mouse should emulate\n"
<< " -showinfo <1|0> Shows some game info\n"
@@ -292,6 +287,7 @@ void Settings::usage()
<< " -ssdir The directory to save snapshot files to\n"
<< " -ssname How to name the snapshot (romname or md5sum)\n"
<< " -sssingle <1|0> Generate single snapshot instead of many\n"
+ << endl
#endif
<< " -listrominfo Display contents of stella.pro, one line per ROM entry\n"
<< " -help Show the text you're now reading\n"
@@ -299,6 +295,12 @@ void Settings::usage()
<< " The following options are meant for developers\n"
<< " Arguments are more fully explained in the manual\n"
<< endl
+ << " -debugheight Set height of debugger in lines of text (NOT pixels)\n"
+ << " -debug Start in debugger mode\n"
+ << " -holdreset Start the emulator with the Game Reset switch held down\n"
+ << " -holdselect Start the emulator with the Game Select switch held down\n"
+ << " -holdbutton0 Start the emulator with the left joystick button held down\n"
+ << endl
<< " -pro Use the given properties file instead of stella.pro\n"
<< " -type Sets the 'Cartridge.Type' property\n"
<< " -ld Sets the 'Console.LeftDifficulty' property\n"
diff --git a/stella/src/gui/ListWidget.cxx b/stella/src/gui/ListWidget.cxx
index e93a7ece4..458d5d96c 100644
--- a/stella/src/gui/ListWidget.cxx
+++ b/stella/src/gui/ListWidget.cxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: ListWidget.cxx,v 1.30 2005-09-07 18:34:52 stephena Exp $
+// $Id: ListWidget.cxx,v 1.31 2005-09-13 18:27:42 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@@ -147,6 +147,7 @@ void ListWidget::scrollBarRecalc()
_scrollBar->recalc();
setDirty(); draw();
+ sendCommand(kListScrolledCmd, _currentPos, _id);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -366,20 +367,16 @@ void ListWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ListWidget::scrollToCurrent(int item)
{
- bool scrolled = false;
-
// Only do something if the current item is not in our view port
if (item < _currentPos)
{
// it's above our view
_currentPos = item;
- scrolled = true;
}
else if (item >= _currentPos + _rows )
{
// it's below our view
_currentPos = item - _rows + 1;
- scrolled = true;
}
if (_currentPos < 0 || _rows > (int)_list.size())
@@ -387,12 +384,13 @@ void ListWidget::scrollToCurrent(int item)
else if (_currentPos + _rows > (int)_list.size())
_currentPos = _list.size() - _rows;
+ int oldScrollPos = _scrollBar->_currentPos;
_scrollBar->_currentPos = _currentPos;
_scrollBar->recalc();
setDirty(); draw();
- if(scrolled)
+ if(oldScrollPos != _currentPos)
sendCommand(kListScrolledCmd, _currentPos, _id);
}
diff --git a/stella/src/gui/ListWidget.hxx b/stella/src/gui/ListWidget.hxx
index 8c7a0066d..dd851ee8d 100644
--- a/stella/src/gui/ListWidget.hxx
+++ b/stella/src/gui/ListWidget.hxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: ListWidget.hxx,v 1.12 2005-08-26 16:44:17 stephena Exp $
+// $Id: ListWidget.hxx,v 1.13 2005-09-13 18:27:42 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@@ -48,6 +48,9 @@ class ListWidget : public EditableWidget
int x, int y, int w, int h);
virtual ~ListWidget();
+ int rows() const { return _rows; }
+ int currentPos() const { return _currentPos; }
+
int getSelected() const { return _selectedItem; }
void setSelected(int item);
diff --git a/stella/src/win32/SettingsWin32.cxx b/stella/src/win32/SettingsWin32.cxx
index ec958195b..55bf44970 100644
--- a/stella/src/win32/SettingsWin32.cxx
+++ b/stella/src/win32/SettingsWin32.cxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: SettingsWin32.cxx,v 1.17 2005-08-24 01:07:37 stephena Exp $
+// $Id: SettingsWin32.cxx,v 1.18 2005-09-13 18:27:42 stephena Exp $
//============================================================================
#include
@@ -28,9 +28,8 @@
SettingsWin32::SettingsWin32(OSystem* osystem)
: Settings(osystem)
{
- set("video_driver", "directx"); // This seems to be much faster than DirectX
- set("fragsize", "2048"); // Anything less than this usually causes sound skipping
- set("video", "hard"); // Use software mode with hardware surface
+ set("fragsize", "2048"); // Anything less than this usually causes sound skipping
+ set("video", "hard"); // Use software mode with hardware surface
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -