MMC3 clocking and palettes, what are the details?
Moderator: Moderators
-
- Posts: 173
- Joined: Wed Jun 15, 2016 11:49 am
MMC3 clocking and palettes, what are the details?
I have something wrong with my implementation of mmc3 clocking when the palette is being read / written to, but I can't seem to figure out what it is. Specifically I am getting an error on the ending screen of Where's Waldo, where the game does some palette operations and expects different irq timing as a result.
I looked around but can't seem to find a thorough enough explanation to point me in the right direction.
Does anyone know the details that can explain what I should be doing? I'd really appreciate any insights.
I looked around but can't seem to find a thorough enough explanation to point me in the right direction.
Does anyone know the details that can explain what I should be doing? I'd really appreciate any insights.
Re: MMC3 clocking and palettes, what are the details?
Hopefully someone can go into further detail if needed, but the gist is that the PPU address bus contains the value of v when rendering is disabled, and so the cartridge can see that palette RAM is being targeted, it just can't see the writes. MMC3 is only looking for toggles on PPU A12, independent of the /rd and /wr signals, so when that bit is set in v from targeting palette RAM, it'll see that as a rising edge. It then won't see rising edges again until PPU A12 has been low for 3 M2 clock edges.
I might be able to help further if you can get more specific.
I might be able to help further if you can get more specific.
-
- Posts: 173
- Joined: Wed Jun 15, 2016 11:49 am
Re: MMC3 clocking and palettes, what are the details?
What is v in this case?
For example Where's Waldo does the following during vblank (changes one palette entry):
So what should the MMc3 see?
Thanks for the help!
For example Where's Waldo does the following during vblank (changes one palette entry):
Code: Select all
E361: A9 3F LDA #$3F A:C0 X:0D Y:41 SP:F7 P:E5 NVTbdIzC Cy:290774616 PPU-Cy:0
E363: 8D 06 20 STA $2006 A:3F X:0D Y:41 SP:F7 P:65 nVTbdIzC Cy:290774618 PPU-Cy:0
E366: A9 11 LDA #$11 A:3F X:0D Y:41 SP:F7 P:65 nVTbdIzC Cy:290774622 PPU-Cy:0
E368: 8D 06 20 STA $2006 A:11 X:0D Y:41 SP:F7 P:65 nVTbdIzC Cy:290774624 PPU-Cy:0
E36B: A5 55 LDA $55 A:11 X:0D Y:41 SP:F7 P:65 nVTbdIzC Cy:290774628 PPU-Cy:0
E36D: 8D 07 20 STA $2007 A:0D X:0D Y:41 SP:F7 P:65 nVTbdIzC Cy:290774631 PPU-Cy:0
E370: A9 00 LDA #$00 A:0D X:0D Y:41 SP:F7 P:65 nVTbdIzC Cy:290774635 PPU-Cy:0
Thanks for the help!
Re: MMC3 clocking and palettes, what are the details?
v is one of the PPU's internal registers. See this wiki page. In short, writes to $2005 and $2006 update a sort-of staging register t, and the 2nd write to $2006 transfers the contents of t to v. t and v are also used during rendering, but for accessing VRAM outside of rendering, t is just a buffer for v and v is the current address on the PPU bus.
In your example, the two $2006 writes set t to $3F11, and the second write transfers t to v, setting v to $3F11 (with no intermediate value). The address bus then updates to the value of v, so the cartridge sees it change to $3F11. After the first write to $2007, an increment occurs, so the cart sees the incremented value ($3F12 or $3F31, depending on increment mode), but A12 is unchanged, so it doesn't affect anything.
I'm not well-versed in the specifics of the PPU address bus. I don't know what the delay is between v updating and the address bus changing, nor the delay between the 2nd $2006 write and v getting its new value. It's not relevant here, but because the lower bits have to be latched, I'm also not sure if those bits change at the same time as the upper bits or on the next PPU cycle.
Note that there's another detail that may matter to you regarding MMC3 IRQ. The 'idle cycle', dot 0 of each rendering scanline, actually starts a memory fetch, the same one that is done later on cycle 5. This read never actually happens, but the because the address is put on the bus on the first cycle of a two-cycle fetch, the cartridge sees the address change on cycle 0. This matters because if sprites are on the $0000 table and BG on the $1000 table, then the gap here would cause extra clocks were it not for cycle 0 resetting the M2 filter. However, when the skipped dot occurs, which technically skips the last dot on the prerender scanline, the memory fetch that would have finished on that skipped dot instead finishes on dot 0 of scanline 0, preventing this aborted fetch from starting, so the cycle 5 address does not make it onto the bus in this case, which can produce an extra clock. This happens sometimes in Wario's Woods, causing the last visible scanline to flicker because rendering gets disabled a scanline early (starting gameplay should settle into an alignment where it always either does or doesn't flicker).
In your example, the two $2006 writes set t to $3F11, and the second write transfers t to v, setting v to $3F11 (with no intermediate value). The address bus then updates to the value of v, so the cartridge sees it change to $3F11. After the first write to $2007, an increment occurs, so the cart sees the incremented value ($3F12 or $3F31, depending on increment mode), but A12 is unchanged, so it doesn't affect anything.
I'm not well-versed in the specifics of the PPU address bus. I don't know what the delay is between v updating and the address bus changing, nor the delay between the 2nd $2006 write and v getting its new value. It's not relevant here, but because the lower bits have to be latched, I'm also not sure if those bits change at the same time as the upper bits or on the next PPU cycle.
Note that there's another detail that may matter to you regarding MMC3 IRQ. The 'idle cycle', dot 0 of each rendering scanline, actually starts a memory fetch, the same one that is done later on cycle 5. This read never actually happens, but the because the address is put on the bus on the first cycle of a two-cycle fetch, the cartridge sees the address change on cycle 0. This matters because if sprites are on the $0000 table and BG on the $1000 table, then the gap here would cause extra clocks were it not for cycle 0 resetting the M2 filter. However, when the skipped dot occurs, which technically skips the last dot on the prerender scanline, the memory fetch that would have finished on that skipped dot instead finishes on dot 0 of scanline 0, preventing this aborted fetch from starting, so the cycle 5 address does not make it onto the bus in this case, which can produce an extra clock. This happens sometimes in Wario's Woods, causing the last visible scanline to flicker because rendering gets disabled a scanline early (starting gameplay should settle into an alignment where it always either does or doesn't flicker).
-
- Posts: 173
- Joined: Wed Jun 15, 2016 11:49 am
Re: MMC3 clocking and palettes, what are the details?
Very interesting, thanks for the detailed reply.
one more question: after rendering is complete, what happens to v?
one more question: after rendering is complete, what happens to v?
Re: MMC3 clocking and palettes, what are the details?
While the meaning of v changes depending on whether the PPU is rendering, the value does not. v keeps its value when rendering starts, v gets mutated over time by the PPU as part of the rendering process, and v keeps that mutated value when rendering ends. In fact, the low 14 bits of v can be left after rendering with a value that points into palette RAM, and this results in the PPU drawing the color at that address just as if you had manually set v to a palette RAM address.
During rendering, the value on the PPU address bus doesn't come directly from v; rather, it's whatever the PPU needs to fetch based on the information in v. However, when rendering ends, the PPU address bus is again automatically set to the value in the low 14 bits of v.
During rendering, the value on the PPU address bus doesn't come directly from v; rather, it's whatever the PPU needs to fetch based on the information in v. However, when rendering ends, the PPU address bus is again automatically set to the value in the low 14 bits of v.
-
- Posts: 173
- Joined: Wed Jun 15, 2016 11:49 am
Re: MMC3 clocking and palettes, what are the details?
Ok, so I fixed Where's Waldo, but now I have a problem in Recca.
It seems the game expects one extra clock compared to what my emulator produces, but I'm not sure where it should come from.
The game does a bunch of palette writes during VBlank, and then it does the following:
So it writes 0 to $2006, then sets up IRQ variables, then enables IRQs. This happens around scanline 249.
Should this setting $2006 to zero cause an extra clock to happen somewhere other then the normal scanline clocks?
Either that, or it expects setting $2006 to 0x3F00 to not clock the IRQ for some reason.
It seems the game expects one extra clock compared to what my emulator produces, but I'm not sure where it should come from.
The game does a bunch of palette writes during VBlank, and then it does the following:
Code: Select all
E286: A9 3F LDA #$3F A:01 X:81 Y:0F SP:99 P:24 nvTbdIzc Cy:61405898 PPU-Cy:0
E288: 8D 06 20 STA $2006 A:3F X:81 Y:0F SP:99 P:24 nvTbdIzc Cy:61405900 PPU-Cy:0
E28B: A9 00 LDA #$00 A:3F X:81 Y:0F SP:99 P:24 nvTbdIzc Cy:61405904 PPU-Cy:0
E28D: 8D 06 20 STA $2006 A:00 X:81 Y:0F SP:99 P:26 nvTbdIZc Cy:61405906 PPU-Cy:0
E290: 8D 06 20 STA $2006 A:00 X:81 Y:0F SP:99 P:26 nvTbdIZc Cy:61405910 PPU-Cy:0
E293: 8D 06 20 STA $2006 A:00 X:81 Y:0F SP:99 P:26 nvTbdIZc Cy:61405914 PPU-Cy:0
E296: A6 FF LDX $FF A:00 X:81 Y:0F SP:99 P:26 nvTbdIZc Cy:61405918 PPU-Cy:0
E298: 9A TXS A:00 X:F1 Y:0F SP:99 P:A4 NvTbdIzc Cy:61405921 PPU-Cy:0
E299: 60 RTS A:00 X:F1 Y:0F SP:F1 P:A4 NvTbdIzc Cy:61405923 PPU-Cy:0
DCD6: A6 4B LDX $4B A:00 X:F1 Y:0F SP:F3 P:A4 NvTbdIzc Cy:61405929 PPU-Cy:0
DCD8: F0 10 BEQ $DCEA A:00 X:01 Y:0F SP:F3 P:24 nvTbdIzc Cy:61405932 PPU-Cy:0
DCDA: A5 3C LDA $3C A:00 X:01 Y:0F SP:F3 P:24 nvTbdIzc Cy:61405934 PPU-Cy:0
DCDC: 85 3E STA $3E A:36 X:01 Y:0F SP:F3 P:24 nvTbdIzc Cy:61405937 PPU-Cy:0
DCDE: A5 3D LDA $3D A:36 X:01 Y:0F SP:F3 P:24 nvTbdIzc Cy:61405940 PPU-Cy:0
DCE0: 85 3F STA $3F A:E8 X:01 Y:0F SP:F3 P:A4 NvTbdIzc Cy:61405943 PPU-Cy:0
DCE2: A5 3B LDA $3B A:E8 X:01 Y:0F SP:F3 P:A4 NvTbdIzc Cy:61405946 PPU-Cy:0
DCE4: 8D 00 C0 STA $C000 A:4F X:01 Y:0F SP:F3 P:24 nvTbdIzc Cy:61405949 PPU-Cy:0
DCE7: 8E 01 C0 STX $C001 A:4F X:01 Y:0F SP:F3 P:24 nvTbdIzc Cy:61405953 PPU-Cy:0
DCEA: A9 00 LDA #$00 A:4F X:01 Y:0F SP:F3 P:24 nvTbdIzc Cy:61405957 PPU-Cy:0
DCEC: 9D 00 E0 STA $E000,X A:00 X:01 Y:0F SP:F3 P:26 nvTbdIZc Cy:61405959 PPU-Cy:0
Should this setting $2006 to zero cause an extra clock to happen somewhere other then the normal scanline clocks?
Either that, or it expects setting $2006 to 0x3F00 to not clock the IRQ for some reason.
Re: MMC3 clocking and palettes, what are the details?
The $3F00 $0000 write pattern you see there is a workaround for a poorly-understood palette corruption bug. It won't clock the counter because the PPU address already had A12 set for writing to palette RAM, but the fact that it ends with A12 clear means that the next rising edge on A12 will be seen as a clock.
The $3F00 write at the start of that function before the popslide for writing palette data does clock the counter (in Mesen, I see the counter go $17->$16), since v seems to always have A12 clear before that. However, it doesn't seem to bring the counter to 0 and the code you quoted that runs shortly after both acks IRQs and schedules a reload for the next A12 clock, so I don't think that clock can matter.
The $3F00 write at the start of that function before the popslide for writing palette data does clock the counter (in Mesen, I see the counter go $17->$16), since v seems to always have A12 clear before that. However, it doesn't seem to bring the counter to 0 and the code you quoted that runs shortly after both acks IRQs and schedules a reload for the next A12 clock, so I don't think that clock can matter.
-
- Posts: 173
- Joined: Wed Jun 15, 2016 11:49 am
Re: MMC3 clocking and palettes, what are the details?
ok i think I finally understand what the problem is now.
For clarity, the issue I ave is one the hard mode title screen in Recca (with the flames.)
Shortly after the code I posted, the game writes to 2 times to $2005, the second write sets bit 12 in the t register. This gets set to the vram address at the end of pre-render scanline, before the first nametable fetches, so this causes a clock on the MMC3. I was not implementing this behaviour.
At least I think that's what's wrong.
Thanks for the help Fiskbit.
For clarity, the issue I ave is one the hard mode title screen in Recca (with the flames.)
Shortly after the code I posted, the game writes to 2 times to $2005, the second write sets bit 12 in the t register. This gets set to the vram address at the end of pre-render scanline, before the first nametable fetches, so this causes a clock on the MMC3. I was not implementing this behaviour.
At least I think that's what's wrong.
Thanks for the help Fiskbit.
-
- Posts: 173
- Joined: Wed Jun 15, 2016 11:49 am
Re: MMC3 clocking and palettes, what are the details?
Turns out I don't quite have it figured out.
I'm also getting stray clocks from sprite pattern table reads on the pre-render line. What addresses are used for sprite reading on the pre-render line?
I'm also getting stray clocks from sprite pattern table reads on the pre-render line. What addresses are used for sprite reading on the pre-render line?
Re: MMC3 clocking and palettes, what are the details?
Some months back I recorded the full PPU bus for four vsyncs displaying the SMB3 title screen. I can't directly tell what it is here, but I suspect the eight fetches on the prerender scanline are the possibly-decayed contents of secondary OAM on the final rendered scanline
- Attachments
-
- smb3title.sr.zip
- open with pulseview/sigrok
- (366.24 KiB) Downloaded 22 times
-
- Posts: 173
- Joined: Wed Jun 15, 2016 11:49 am
Re: MMC3 clocking and palettes, what are the details?
Thanks for the info, but after double checking with Mesen, it seems that is not my problem either.
Comparing to Mesen, I'm simply missing an IRQ. My IRQs are starting at the correct scanline, but Mesen gets an extra IRQ at the end.
This IRQ seems to be triggered on cycle 1 of the post render scanline. Is there anything happening at this point that can trigger an extra rising edge of A12? This also looks like the point where Mesen changes it's frame counter, maybe this is a glitch in Mesen that happens to work out?
This is very confusing.
Comparing to Mesen, I'm simply missing an IRQ. My IRQs are starting at the correct scanline, but Mesen gets an extra IRQ at the end.
This IRQ seems to be triggered on cycle 1 of the post render scanline. Is there anything happening at this point that can trigger an extra rising edge of A12? This also looks like the point where Mesen changes it's frame counter, maybe this is a glitch in Mesen that happens to work out?
This is very confusing.
Re: MMC3 clocking and palettes, what are the details?
At the start of post-render, rendering ends and the PPU address bus is changed to the value of v. The lowest bit of fine y from rendering occupies bit 12, so if fine y bit 0 is 1, you'll get an A12 rising edge here because the address bus was previously being used for nametable fetches, and I believe it should clock because background is on the $0000 table, so the M2 filter should have expired.
I wouldn't necessarily take Mesen as gospel here, for what it's worth.
I wouldn't necessarily take Mesen as gospel here, for what it's worth.
-
- Posts: 173
- Joined: Wed Jun 15, 2016 11:49 am
Re: MMC3 clocking and palettes, what are the details?
Aha! Yes if I implement that then everything seems to work correctly in both Recca and Where's Waldo without breaking anything.
I suppose such a case is seldom encountered as most games only use one or two IRQ's per screen and have them turned off by the time vblank happens.
Really happy to have this one finally sorted. I probably still have a few not quite correct edge cases, but it's a big step in the right direction.
Thanks for the help!
I suppose such a case is seldom encountered as most games only use one or two IRQ's per screen and have them turned off by the time vblank happens.
Really happy to have this one finally sorted. I probably still have a few not quite correct edge cases, but it's a big step in the right direction.
Thanks for the help!
-
- Posts: 173
- Joined: Wed Jun 15, 2016 11:49 am
Re: MMC3 clocking and palettes, what are the details?
Small bit of follow up here.
It seems Burai Fighter expects soam to decay during vblank, otherwise extra clocks occur on scanline 0 causing the screen to shake, due to left over sprite values. At least that fixes it for me.
It seems Burai Fighter expects soam to decay during vblank, otherwise extra clocks occur on scanline 0 causing the screen to shake, due to left over sprite values. At least that fixes it for me.