Debugging the emulated program

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Debugging the emulated program
by on (#63317)
I've reached the point where the CPU and a basic PPU are ready and games can be run.
But they don't, so I have to debug them.
I'm thinking on developing a graphical debugger pretty much like the one in FCEUXD SP.
Those who made emulators, how did you do this? did you make a debugger? did you use an IDE's debug? did you use any other solution?

by on (#63318)
A graphical debugger is probably overkill unless it's one of the goals for your emulator.

I'd start with a tracelogger. Dump register contents, timing info, etc between every CPU instruction, and mark where NMIs/IRQs/etc occur.

Usually if a game fails to run, it's somewhat easy to spot where it's going wrong just by examinig the trace log.

Put undocumented opcodes and BRK inside special characters that can be easily searched. For my log I put them in {braces}, that way if a game fails to run, I can just search the log for a { character, and that gives me a starting point to find where things are going wrong.

by on (#63319)
Oh that's easier, I already have a log but I thought it may be very hard to debug with it, I used it to test the CPU instructions, but thought a step by step realtime debugger would be nicer. But also more difficult to build.

Actually I started testing a memory watch in QT that works fine, but I'm having trouble mixing QT and SDL.

But I may give the log debugging a try

I'm not sure about what to use for the GUI. Since I use MacOS, I could do it native, but I'd like the debugger to be portable, just in case I need to debug on windows, although the emulator should run exactly the same on both platforms. That's why I considered QT.
I ruled SDL out because current version can't handle more than one window, and it's not enough for the emulator output, nametables watch and CPU debugger, and the next version is still unstable and I can't get it to build.
Any other suggestions?

by on (#63320)
You could try dividing your SDL screen into panes. Open a 1024x600 pixel window (I chose this size so that it'd be full screen on a small laptop) and then, within your app, split it into two panes: the left 592x480* for the emulated console's screen, and the remaining 432 pixels for any debugger.


* Why not 512x480? Pixel aspect ratio. At the NES's dot clock rate, a 4:3 screen would be 280x240 pixels. If you enlarge a 259x240 pixel display (including 3 columns of side border in color 0) to 592x480 square pixels, it'll have the right PAR.

by on (#63322)
Petruza wrote:
Any other suggestions?


You could help me... :D

NESICIDE main site

A rather old OSX build, hyarion on #nesicide on freenode.net can build a newer one...I don't have a Mac.

Help, help! Join us on #nesicide on freenode.net if interested.

I'm currently embarked on an emulator accuracy quest, which is giving me plenty of excuses to add more flesh to my debugger inspectors. Currently there are 23 different dockable inspectors showing everything from graphical views of code/data accesses by the CPU or PPU to logging of execution cycles of the CPU/PPU/APU, to showing the internal state of the PPU, APU or cartridge mapper, etc. Breakpoints can be set on just about any event within the CPU, PPU, APU, or cartridge.

The end-goal isn't just for a debugger...but that is one of the areas that I'm currently finishing up.

by on (#63323)
tepples wrote:
You could try dividing your SDL screen into panes.

I thought about that, but as I'm planning to have the original NES screen, plus the 2 nametables, plus the two attribute tables, plus the two nametables with tile indexes instead of the tiles themselves, that's already 7 rectangles of 256x240 pixels on the window.
Plus the 64 sprites, plus a little table with RAM values, plus CPU registers, flags, etc. plus a list of dissasembled instructions...
I was thinking about an SDL window with all the graphic data and one GUI window with the RAM and CPU data.
Oh yes, and other point against mac native code (cocoa) is it has to be written in Objective-C. Brrrrrrrr I hate that language.

by on (#63324)
NESICIDE wrote:
Help, help! Join us on #nesicide on freenode.net if interested.

Sorry, is that IRC? it's been years since I don't use IRC

by on (#63325)
Petruza wrote:
NESICIDE wrote:
Help, help! Join us on #nesicide on freenode.net if interested.

Sorry, is that IRC? it's been years since I don't use IRC


Yes it's IRC but I use the qwebirc portal at webchat.freenode.net. Channel #nesicide, pick a nick, join.

NESICIDE uses OpenGL textures to render the NES screen, the 512x480 nametable view, a graphical view of the OAM (256x32 or x64), a graphical view of CHR memory (256x128), a graphical view (256x256) of the CPU and (256x64) the PPU executing memory access cycles, and a view of the PPU clock-cycle domain (341x262 NTSC or 341x312 PAL) showing up to 8 marked regions of CPU execution within the PPU frame (visual cycle-timing).

It uses various QTableView widgets with specialized models to display binary memory contents for all memory regions, and a combined set of QTableView widgets to display register content in both binary and bitfield human-readable form. Then there's the PPU/APU information dialogs. Also a specialized model displays the execution trace in a QTableView. Finally there is the assembly or source-code specialized models for displaying currently executing code.

NESICIDE only uses SDL for audio.

EDIT: wrong dimensions on CHR.

by on (#63333)
I'd recommend getting nestest.nes to pass first.

It will make sure your CPU is correct. Start with getting the PC/registers to match perfectly, and then get your cycle timings correct.

Load the ROM into your emulator's memory and set the 6502 PC to C000. Turn off interrupts.

Build a tracelogger to match this format (note those are PPU cycles, not CPU cycles). Run and then compare your log against this golden log: http://nickmass.com/images/nestest.log

by on (#63334)
I only ever did was Disch suggested which was to make a simple Tracer Logger of CPU execution. For games that crash at a specific point I changed it to toggle logging so I don't have to sift through tons of log before getting to a crash. It works pretty well.

by on (#63335)
So that's how you use nestest. Excellent, and helps you find out exactly where you went wrong. I knew that nestest was the better one to run before my CPU tests, but never had figured out how to use it effectively. I just updated the Wiki with links to this version, and the log, and why it's better to run first.