Thursday, June 23. 2005

I've decided to fork FCE Ultra eXtended-Debug 1.0a under the name FCEUXD SP with the hope to make significant contributions and improvements to the NES debugging experience. My main reason for this was the sorry state of NES debugging today. Even with the best NES emulator debuggers today barely anything is possible. If I had to guess where NES debugging today is I'd estimate it's somewhere between debug.com and Borland's Turbo Debugger. That's an unacceptable situation in my opinion.
Here's where I come into play. As the original FCE Ultra was thankfully released under GPL I was able to get the source code of one of it's former forks FCE Ultra eXtended-Debug 1.0a from Zophar's Domain. The code is very well written so I had absolutely no problems with adding new functionality. It was not even necessary to change the interface of one, single pre-existing function.

In this first release of FCEUXD SP 1.0 I've added two features which were at the very top of my list: A simple form of symbolic debugging and conditional breakpoints.

Symbolic Debugging: I've defined a simple debug information file format for FCEUXD SP which contains names for memory addresses and comments. Defining names has two functions: If the renamed line is shown in the disassembly window the name will appear right above the line of code. If the renamed line is referenced in an instruction (for example "JSR $8000") the offset is replaced by the name. Like names comments are also added before the line of code they were defined for.

The debugging information file format is a very simple text file format. Here's an example file (*all* lines must end with a new line; including the last one):

Edit: Well, HTML is beating me again. It doesn't look correctly formatted. Look at the end of this post for a good file.

There are three #-separated parts in every line. The memory address to rename, the new name of that memory address (optional) and the comment for that memory address (also optional).

Two of the bigger weaknesses so far are that only four-byte addresses are properly supported (the representation in the disassembly window matters though; $3C1 might not work but $03C1 does) and that all addresses are case-sensitive ($03c1 does not work; $03C1 does).

Because of the nature of the NES not all parts of the ROM file are in memory at the same time. Different parts (banks) are paged in and out at certain occasions. To account for this every bank in the ROM needs it's own debugging information file. The name of such a file is RomName.nes.X.nl where X is the hexadecimal representation of the bank ID the file is for. For the curious: The file extension nl stands for name list.

Here are example screenshots for a piece of Faxanadu debugged using FCE Ultra eXtended-Debug 1.0a and FCEUXD SP. It shows a function adding a number of health points to the player's current health points and another function decreasing the player's health points.

Conditional breakpoints: Another minor annoyance was the lack of conditional breakpoints. I've added this functionality to the breakpoint definitions. When adding or editing a breakpoint you now have the option to add a condition for this breakpoint. Right now conditions are relatively simple but enough for probably more than 90% of all debugging.

A condition is a simple C-style expression. Supported values are A (register), X (register), Y (register), N, V, U, B, D, I, Z, C (all flags), hex numbers of the form #1234 and values at (CPU) memory locations of the form $1234. These values can be compared using the operators ==, !=, >=, <=, > and

Examples for valid conditions:
A > #5 (Value of register A is greater than 5)
B == #4 || B == #12 (Value of register B is 4 or 12)
C == #0 && $8000 == A (Carry flag is not set and the value of byte $8000 equals the value of register A)

That should be sufficient for the initial release. Features planned for the future are: Mouse-over tool-tips for renamed addresses to see the original value, watches, better conditions, an option to auto-execute a command when a breakpoint is triggered and the ability to navigate through the disassembly by double-clicking names or addresses.

Excellent idea to get the sources out guys. Hopefully soon someone can port your hard work over to Linux/X11 so more work can be done. Some ideas for those would-be Linux/X11 porters: SDL, OpenGL, GTK 2.x, and USB Joystick support.