Page 1 of 3
How do you find bugs in your emulator?
Posted: Mon Jun 06, 2011 10:55 am
by oRBIT2002
I've got a few problematic ROMs that doesn't work in my emulator. The symtoms are just lockups or the game tries to run an illegal opcode which causes my emulator to halt.
The problem is that I am not sure how to find the bugs. I've done a log-feature that logs the previously executed code and where it came from, but it easily gets huge which makes it unusable.
The current one I'm trying to get to work is "Jackal" (mapper 2), which for some reason only gives me a blank screen.
So emulator-authors, do you have any genius-tips or how do you track down problems like this? How do you proceed when a game just refuses to run?
Thanks in advance
Posted: Mon Jun 06, 2011 11:05 am
by tepples
You could start with some
test cases from the wiki.
Posted: Mon Jun 06, 2011 1:15 pm
by oRBIT2002
I pass all CPU-tests using the NESstress ROM so I guess it has to be something else..
Re: How do you find bugs in your emulator?
Posted: Mon Jun 06, 2011 1:27 pm
by cpow
oRBIT2002 wrote:
So emulator-authors, do you have any genius-tips or how do you track down problems like this? How do you proceed when a game just refuses to run?
Thanks in advance
I just kept adding stuff to my debugger output windows to help me figure things out. For example, to figure out the sprite hit and overflow test ROMs I added a bunch of breakpoint events like:
Break when sprite N enters the multiplexer
Break when sprite N is selected by the multiplexer
Break when sprite N is drawn
Break when sprite 0 is hit
I did the same for debugging my APU, adding breakpoint events like:
Break on length counter clock
Break on DMC DMA
Most of the time a game refuses to run its because there's some condition about sprite 0 hit or sprite overflow that isn't quite right in your emulation. At least, that has been my experience...you'll stop the game and it'll be spinning on a BIT $2002 loop or something and you'll facepalm and exclaim "not ANOTHER one!"
Other cases of game-not-so-runnyness:
Mapper imperfections causing incorrect bank loading causing eventual KIL opcode execution...easy enough to trap and even put up a "DOH" dialog for. Mapper imperfections includes incorrect initialization of mapper state such that the game doesn't even start out with the correct PRG banks loaded where they need to be loaded. [I had a problem where I could get SMB3 *or* SMB2 to run but not both because of some error in the way I was initializing the PRG bank swapping modes].
The way I solved those issues was to add mapper inspectors that let me peer into the internal state of the mapper and trap on writes to the mapper and set breakpoints if the mapper state changes. It's pretty easy to see a bad mapper write when you step over it and all of a sudden you're in the middle of a bunch of .DB $00 crap.
I'm in a bit different situation though I'm not just writing an emulator I'm writing a tool that I think should by definition have the capability to scrutinize the minutia of the machine otherwise it's not very useful as a debug/integration platform.
Posted: Mon Jun 06, 2011 1:35 pm
by cpow
oRBIT2002 wrote:I pass all CPU-tests using the NESstress ROM so I guess it has to be something else..
I would disagree with that statement.
Do you pass:
blargg_nes_cpu_test5
branch_timing_tests
cpu_dummy_reads
cpu_timing_test6
instr_misc
instr_timing
Passing those, you probably have a nearly flawless CPU. I say nearly because there's some I didn't include in the list and we don't know everything (yet) about the 2A03.

Posted: Mon Jun 06, 2011 3:43 pm
by Zepper
The best thing you do is to create a log of the running ASM code. It should be a text file within all the executed instructions... and where it hangs/fails. Though, there's one problem: the size. It generates a huge file that isn't opened so quickly in wordpad, for example.
Anyway, yes, it's the best thing. Next, the PPU. There are tons of PPU tests that shoudl help you a lot. They're much more difficult to get a pass than CPU tests.
Posted: Mon Jun 06, 2011 6:14 pm
by Luke
blarrg's test were by far the most helpful thing for me, but there are a few things they do not catch. To snuff out some lingering issues, I would try to find games that did not work right from the get-go, i.e. games whose title screen wouldn't even come up, or would be glitchy, etc. Then I'd turn on super-detailed tracing like Zepper describes, and compare against the output of Nintendulator running that same game. This technique helped me iron out some bugs that manifested themselves in Galaxian, Joy Mecha Fight, and Slalom.
Posted: Mon Jun 06, 2011 8:36 pm
by Zelex
yup, that's a great technique comparing traces. I have yet to do full traces, but I've done limited ones to find bugs in the past. For example, mapper bugs that happen a long time after the game has started. Only outputting traces related to the mappers helped immensely.
Posted: Mon Jun 06, 2011 8:49 pm
by Zelex
blargg's tests are indeed awesome btw, but you don't need to pass them all to emulate most games very well.
Posted: Mon Jun 06, 2011 10:32 pm
by MottZilla
All I ever needed was a trace logger. Though it helps if you have a way of turning it on and off during execution so if you have a problem beyond the initial bootup you can avoid logging parts that work fine.
But it'd be even better to have a full fledged debugger complete with breakpoints and step by step execution options.
Posted: Mon Jun 06, 2011 11:07 pm
by oRBIT2002
Zelex wrote:blargg's tests are indeed awesome btw, but you don't need to pass them all to emulate most games very well.
Blargg's tests are pretty insane. Not many emulators pass all of them.
Some bugs are hard to find. If it's CPU related, the problem doesn't always appear where the bug is.
Another strange bug I've got is that "Balloon Fight (E)", plays a song during titlescreen (the (US) doesn't, neither the (E) version in any other emulator). How do you bughunt such a thing?

Posted: Tue Jun 07, 2011 5:06 am
by cpow
MottZilla wrote:But it'd be even better to have a full fledged debugger complete with breakpoints and step by step execution options.
I always wondered exactly what a "fledge" is, and how they become "full"?
But yeah, I know what you mean. For me, having access to the code for said somewhere-between-nil-and-full-fledged debugger in my app makes it that much easier to add specific breakpoint events or log events or features that I can think up to help me bughunt.
One story. I was having a heck of a time figuring out why I could pass all of blargg's sprite hit tests but one, specifically "07.screen_bottom". I had thought I had the timing correct since I passed 03.corners fine [aside: I had wrongly assumed that "corners" meant screen corners, but further debugging of this test ROM showed it meant corners of a sprite in the center of the screen! Duh!]. But, it wasn't until I created the "Execution Visualizer" that could show me where in the PPU time domain code was executing, overlaid on a 341x262 graphic representing the PPU time domain and showing the screen and VBLANK/HBLANK time. I was always executing the "check for hit" code about four and a half scanlines too soon [and it hadn't hit yet, so I failed]. Four and a half scanlines is ~513 CPU cycles...and there I was, not properly accounting for sprite DMA cycles missing from the CPU. Sometimes things don't pop out at me from a trace log...I need visuals!
Posted: Tue Jun 07, 2011 11:54 am
by Zelex
a fledgling is a young bird. to be fully fledged is to have large wings and able to fly.
Posted: Tue Jun 07, 2011 11:58 am
by cpow
Zelex wrote:a fledgling is a young bird. to be fully fledged is to have large wings and able to fly.
Now I know.

Posted: Tue Jun 07, 2011 12:41 pm
by tepples
cpow wrote:MottZilla wrote:But it'd be even better to have a full fledged debugger complete with breakpoints and step by step execution options.
I always wondered exactly what a "fledge" is
Wikipedia knows.
Fledge is the second stage of a bird's life cycle, after it has left the nest and before it can fly.
and how they become "full"?
Ability to do everything but fly, including (in some species) fend for oneself without help from parents.