How do you find bugs in your emulator?

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

User avatar
oRBIT2002
Posts: 623
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

How do you find bugs in your emulator?

Post by oRBIT2002 » Mon Jun 06, 2011 10:55 am

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

tepples
Posts: 22050
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Mon Jun 06, 2011 11:05 am

You could start with some test cases from the wiki.

User avatar
oRBIT2002
Posts: 623
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Post by oRBIT2002 » Mon Jun 06, 2011 1:15 pm

I pass all CPU-tests using the NESstress ROM so I guess it has to be something else..

User avatar
cpow
NESICIDE developer
Posts: 1097
Joined: Mon Oct 13, 2008 7:55 pm
Location: Minneapolis, MN
Contact:

Re: How do you find bugs in your emulator?

Post by cpow » Mon Jun 06, 2011 1:27 pm

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.

User avatar
cpow
NESICIDE developer
Posts: 1097
Joined: Mon Oct 13, 2008 7:55 pm
Location: Minneapolis, MN
Contact:

Post by cpow » Mon Jun 06, 2011 1:35 pm

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. :shock:

User avatar
Zepper
Formerly Fx3
Posts: 3217
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper » Mon Jun 06, 2011 3:43 pm

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.

Luke
Posts: 40
Joined: Mon Oct 06, 2008 6:03 pm

Post by Luke » Mon Jun 06, 2011 6:14 pm

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.

Zelex
Posts: 268
Joined: Fri Apr 29, 2011 9:44 pm

Post by Zelex » Mon Jun 06, 2011 8:36 pm

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.

Zelex
Posts: 268
Joined: Fri Apr 29, 2011 9:44 pm

Post by Zelex » Mon Jun 06, 2011 8:49 pm

blargg's tests are indeed awesome btw, but you don't need to pass them all to emulate most games very well.

User avatar
MottZilla
Posts: 2832
Joined: Wed Dec 06, 2006 8:18 pm

Post by MottZilla » Mon Jun 06, 2011 10:32 pm

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.

User avatar
oRBIT2002
Posts: 623
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Post by oRBIT2002 » Mon Jun 06, 2011 11:07 pm

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? :)

User avatar
cpow
NESICIDE developer
Posts: 1097
Joined: Mon Oct 13, 2008 7:55 pm
Location: Minneapolis, MN
Contact:

Post by cpow » Tue Jun 07, 2011 5:06 am

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"? :D

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!

Zelex
Posts: 268
Joined: Fri Apr 29, 2011 9:44 pm

Post by Zelex » Tue Jun 07, 2011 11:54 am

a fledgling is a young bird. to be fully fledged is to have large wings and able to fly.

User avatar
cpow
NESICIDE developer
Posts: 1097
Joined: Mon Oct 13, 2008 7:55 pm
Location: Minneapolis, MN
Contact:

Post by cpow » Tue Jun 07, 2011 11:58 am

Zelex wrote:a fledgling is a young bird. to be fully fledged is to have large wings and able to fly.
Now I know. :D

tepples
Posts: 22050
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Tue Jun 07, 2011 12:41 pm

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.

Post Reply