I just implemented iNES mapper 118: Goal 2, Pro Sport Hockey, Armadillo, Ys 3, NES Play Action Football.
I'm having problems getting Ys 3 and Goal 2 run correctly, both have their status screens shaking vertically by 1 line, making me think IRQ handling is the suspect. But, none of the other MMC3 games are having any IRQ problems anymore (of the ones I've tested, and that's a lot). So I was wondering, does this mapper use a different IRQ mechanism ?
Nope - it's a plain old MMC3, just hooked up a bit differently. If you're getting screen shaking at IRQ points then you're likely getting the same problem on the SMB3 titlescreen, which is caused by alternating between CPU and PPU execution too infrequently - you must switch at least twice per scanline, once at the beginning of the scanline and again at the beginning of HBLANK (and you must generate MMC3 IRQs at the beginning of HBLANK; MMC5 IRQs, however, get generated at the beginning of the scanline itself).
(to add 1 to my list above: Alien Syndrome (U) also seems to use this mapper).
I've got several hacks up my sleeve for Goal 2 to work correctly, like feeding the PPU addressbus with loopy_v when in vblank, or disabling palette reads affecting the addressbus. But none for Ys 3...
I've tried those in Nintendulator, and Goal 2 is working fine, but Ys 3 is showing some evil shaking (and Armadillo is not working correctly, but probably not due to IRQs).
Anyway, SMB3 is working ok here, and so are any other MMC3 games I used to have problems with, like Kick Master, Magical Doropie (intro clouds), or Days of Thunder, or even the mighty Star Wars (E).
The problem in Armadillo was related to IRQs.
My MMC3 implementation directly monitors PPU A12 to activate the IRQ counter, and it requires a certain delay after it goes high before it will accept another rising edge. Armadillo has BG and sprites in the 'wrong' pattern tables, which was causing the IRQ counter to decrement after the first BG fetch and the 3rd one (due to the short delay between them) - I just had to increase the required delay between rising edges.
As for the shaking in Ys 3, it is somewhat sparse (not nearly as bad as SMB3 is in a lesser emulator) and might be related to PPU VRAM address reload timing (which has not yet been verified).
Ah, I found the cause: My MMC3 IRQ handler gets called whenever there's a PPU read or write, so when there's a delay between two accesses, the 2nd access might get interpreted as a valid rising edge when it wasn't, 'refreshing' the handler constantly fixed Goal 2.
Strangely, I haven't seen this bug affecting other MMC3 games.
Quietust wrote:
The problem in Armadillo was related to IRQs.
My MMC3 implementation directly monitors PPU A12 to activate the IRQ counter, and it requires a certain delay after it goes high before it will accept another rising edge.
Has anybody done tests on either of the two following hypotheses to see which is correct or what is the right value of
n?
- Waits for PPU A12 to be low for at least n straight cycles.
- Ignores PPU A12 for at least n cycles after a rising edge.
The MMC3 waits for PPU A12 to be low for at least n cycles in a row before it will recognize an additional rising edge. If it were the latter (ignore A12 for n cycles after a rising edge), then n would have to be VERY high to prevent it from messing up when background tiles are in the upper pattern table (since this would cause 34 rising edges in a row, and only the FIRST one is detected).
By manually toggling PPU A12 (by writing to $2006), the MMC3 will decrement the counter on every rising edge, so the absolute maximum delay is 9 CPU cycles (around 13 complete PPU memory accesses).