My Emulator - Problems With a Few Games ('Toads, TMNT, MM6)

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

allthatremains
Posts: 7
Joined: Thu Apr 23, 2009 12:14 pm

My Emulator - Problems With a Few Games ('Toads, TMNT, MM6)

Post by allthatremains » Thu Apr 23, 2009 12:47 pm

So I've been developing an emulator (both as a learning experience and as a product for a certain platform... will get to that soon enough).

I have a good understanding of the NES architecture, and things are to the point where they're pretty solid. The EMU passes most of blargg's tests (including CPU/official, PPU, IRQ/NMI, MMC3). Most games (that I have mapper support for) run without a hiccup; this includes a lot of notoriously tough games like Megaman 3, Super Mario 3, Double Dragon 3, and Solar Jetman.

I've run into problems with the aforementioned trio of games.

First off, Battletoads. Everything looks great right off the bat; the title screen, game play, the entire first level... accuracy is right up there with Nestopia. But, not long into the second level (the chasm), everything just suddenly freezes. (Interestingly, it has the same problem on Nintendulator. Nestopia runs it perfectly.)

Image

Looking at my debug info, it seems to loop in the following code. (Looks like it's waiting for the Sprite Overflow flag to be set, but it never does... Would seem to point to a Sprite Overflow implementation bug, but the EMU passes all of blargg's Overflow/Sprite0 tests).

Code: Select all

863E  2C 02 20  BIT $2002 = 00                  A:40 X:10 Y:10 P:37 SP:FD CYC: 63 SL:87
8641  F0 FB     BEQ $863E                       A:40 X:10 Y:10 P:37 SP:FD CYC: 75 SL:87
Next, Megaman 6. The game looks and plays perfectly... except for ONE miniboss. The monkey/ape/wtfever in Plant Man's level. The (background?) tiles look like they're all one vertical index off. I couldn't find this bug in any other emulator. As soon as I defeat him, everything's normal again.

Image

Finally, TMNT. Basically, the overhead view looks fine, the pause/map screen looks perfect. But, once you actually enter a level... everything, again, seems like one vertical tile off. There's no status bar. Everything seems to run very slowly as well, whereas any other game is full-speed.

Image

My emulator has per-cycle accuracy, so everything is basically by-the-book. I tried holding off posting for this long, because I usually come up with answers on my own. Any help at all would be appreciated!

User avatar
tokumaru
Posts: 12003
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Thu Apr 23, 2009 12:56 pm

The second and third problems are obviously related, and I was thinking the first one might be too. Isn't it possible that the $2002 loop is waiting for a sprite 0 hit that doesn't happen because the background is offset, like in the other cases? Well, maybe not, since you said it happens in Nintendulator also.

User avatar
Dwedit
Posts: 4411
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Post by Dwedit » Thu Apr 23, 2009 12:58 pm

Battletoads doesn't use the sprite overflow bit. Sprite collision yes, overflow no.

Anyway, you obviously have missing sprite 0 hits. Double check for bugs there. Make sure you're calculating the sprite pixels correctly, background scrolling location, and background pixels correctly. Any bug that causes the wrong address to be used for any of these things will throw everything off.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

allthatremains
Posts: 7
Joined: Thu Apr 23, 2009 12:14 pm

Post by allthatremains » Thu Apr 23, 2009 1:07 pm

Am I setting Sprite0 Hit at the wrong time? When does it need to be set? I'm currently setting it when the pixel in question is actually rendered. So if the PPU is currently rendering x=0 to the screen, and Sprite0 and the Background both have a pixel set there, the hit flag is set.

Edit: Toying with the code, if I allow Sprite0 Hit to be set when the background pixel is empty, TMNT's status bar appears, but the vertical offset still looks wrong. Thanks for the quick help by the way.

User avatar
Dwedit
Posts: 4411
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Post by Dwedit » Thu Apr 23, 2009 1:46 pm

Setting it at the wrong time would just mean the game would draw the status bar at the wrong time, maybe causing it to shake, or be drawn too high or too low. It wouldn't remove it completely.

I'm guessing the background being drawn too high is causing Ninja Turtles and Megaman 2 to not get a sprite hit.

You sure the status bar in Battletoads is drawn at the correct position? I can't tell from your 240x224 screenshot. If you don't emulate the extra CPU cycle used by page crossing instructions, it will be drawn too high, and miss collision.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

allthatremains
Posts: 7
Joined: Thu Apr 23, 2009 12:14 pm

Post by allthatremains » Thu Apr 23, 2009 2:15 pm

Sorry about that, I trimmed the edges on the display because I didn't like how certain things looked untrimmed (artifacts, the empty left-edge, etc). Here's a screenshot of Battletoads level 1, without trimming the display.

Image

Also, before someone asks, the trimming was on output, so this doesn't change any of my sprite0 hit calculation.

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Thu Apr 23, 2009 3:11 pm

Level 2 in battletoads is EXTREMELY picky about several things:

1) NMI timing
2) Sprite 0 hit
3) PPU Scroll update changes

1 and 2 have test ROMs available, and if you pass them, you're okay. #3 doesn't have any test ROMs though (at least not that I know of). Be sure you do the following:

1) X scroll increment every 4th in a series of 8 cycles (dots 3, 11, 19, 27, etc -- but not during sprite fetches)
2) X scroll reset on dot 257
3) Y scroll increment on dot 251
4) all scroll updates done on the pre-render scanline ("scanline -1") as well as all 240 rendered scanlines. As long as the PPU is on.
5) scroll reset (loopy_v = loopy_t) on dot 304 of the pre-render scanline only, and only if PPU is on.

specifically, I think battletoads relies most on #2 and #3 of the above.

allthatremains
Posts: 7
Joined: Thu Apr 23, 2009 12:14 pm

Post by allthatremains » Thu Apr 23, 2009 3:32 pm

So, an update.

I was able to get Battletoads working. Not sure what was wrong exactly, but it did have something to do with the scroll counters.

TMNT and MM6 are still up in the air.

User avatar
Dwedit
Posts: 4411
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Post by Dwedit » Thu Apr 23, 2009 3:33 pm

TMNT uses negative Y scroll values and draws the attribute table. Make sure you emulate the Y increment correctly, and aren't just forcing out of bounds values to be in bounds.
Also test Slalom and SMB3 (when it shakes the screen during the title)
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

allthatremains
Posts: 7
Joined: Thu Apr 23, 2009 12:14 pm

Cha-Ching!

Post by allthatremains » Thu Apr 23, 2009 4:27 pm

Thanks, so I'm trying to dig for more information on negative Y scrolling. $F0-$FF are treated as negative values, right? $F0=-1, $FF=-15?

I guess that would account for the 2-tile vertical mis-offset, huh? :oops:

Edit: You guys rock.

It totally turned out to be a negative Y scroll issue.

Loopy said it best, even back when the emulation dinosaurs roamed:
there are some odd side effects
from this.. if you manually set the value above 29 (from either 2005 or
2006), the wrapping from 29 obviously won't happen, and attrib data will be
used as name table data. the "y scroll" still wraps to 0 from 31, but
without switching bit 11. this explains why writing 240+ to 'Y' in 2005
appeared as a negative scroll value.
So when incrementing the Y-scroll, if incrementing from 29, wrap back to 0, and increment the name table. If incrementing from 31, wrap back to 0, but do NOT increment the name table.

Everything works!

On a related note, one last question... what about negative sprite Y-offsets? Does anybody handle those specifically, or is it just accepted that sprites get cut-off when going off the top of the screen?

User avatar
Dwedit
Posts: 4411
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Post by Dwedit » Thu Apr 23, 2009 4:49 pm

Negative sprites are just out of bounds on the bottom. I don't think they're treated as signed.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Thu Apr 23, 2009 4:53 pm

Congrats

Let me know if you can run Fire Hawk and MiG 29 Soviet Fighter without problems. I await to hear your shouting of obscenities

=)

allthatremains
Posts: 7
Joined: Thu Apr 23, 2009 12:14 pm

Post by allthatremains » Thu Apr 23, 2009 5:01 pm

I haven't implemented mapper 71. It'll be interesting to see if I can get those running well, since I pass all of the timing tests out there (AFAIK). I'll let you know if I get around to it. Right now I just want to get the big boys implemented. I think that leaves me MMC5 right now, for Castlevania 3.

Thanks again to all involved, I'm pretty stoked right now.

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Thu Apr 23, 2009 6:24 pm

071 is pretty easy -- not much different from 002, really.

Obligatory plug/link:
http://www.romhacking.net/docs/362/

provided you don't already have them

</shameless>

User avatar
Dwedit
Posts: 4411
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Post by Dwedit » Thu Apr 23, 2009 8:18 pm

Some people emulate 71 by using their mapper 2 code.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

Post Reply