MMC3 scanline counter off by 1 between fceux and Nestopia

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
MMC3 scanline counter off by 1 between fceux and Nestopia
by on (#227994)
I included an IRQ interrupt into my MMC3 game and it woks quite well, except for one thing:

I do a mid-frame name table change when the interrupt starts.

(Then, in NMI, I set the name table back to its original value. So, the output is: Upper part of the screen is the regular level, lower part is solid blue from the opposite name table.)

But on fceux and Nestopia, the name table switch happens in different scanlines. So, the output is different in both versions: One of them happens one scanline earlier than the other one.

This did not happen when I used simple sprite 0 checks for mid-frame splits.


If you need to, I can later provide you details about what exactly I do in my code as well as show you a comparison screenshot. (I'm not at home in the moment.)

But maybe this is a commonly-known issue.

So, why do both emulators do the name table switch in different scanlines? And is there a way to make both behave the same?
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#227998)
Without seeing your IRQ handler, I can't say anything for sure, but IIRC, FCEUX's PPU emulation is not cycle-accurate, meaning that certain changes in rendering parameters may not be visible right away. Are you using FCEUX's new or old PPU emulation? You can toggle this in the menus and see if it makes any difference.

Anyway, MMC3 IRQs, when used the standard way, fire way late in the scanline, well into the hblank already, so there isn't enough time to do a clean split right away before the next scanline starts rendering. For a proper, glitch-free split, you have to wait until the *next* hblank and do the switch then.

If you do raster effects without any regards to what the PPU is doing, your updates may conflict with the PPU's auto increments, and may be interpreted differently by emulators with differing levels of accuracy. It should be possible get a stable result across the most popular emulators, but you have to mind the scanline timing and make sure that the crucial PPU writes happen at safe times.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228007)
Make sure your MMC3 IRQ is set to start at a safer time, such as during Background Rendering time (X = 0 to 255), not during Sprite Fetch time (X = 256 to 340). Manually resetting the scroll (V=T) could also possibly trigger a tick if Fine Y scroll is in a certain range with rendering disabled?
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228008)
Dwedit wrote:
Make sure your MMC3 IRQ is set to start at a safer time, such as during Background Rendering time (X = 0 to 255), not during Sprite Fetch time (X = 256 to 340).

Oh yeah, good call. If you setup the IRQ near the time when the scanline counter gets clocked, slight variations in timing could cause it to be clocked one extra time or one time less than expected, resulting in an of by one error when the IRQ fires.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228009)
O.k., here's what my code looks like.

The scanline counter only gets enabled during NMI, so I hope that I don't have to pay attention to hblank etc.

After certain checks whether the general code inside NMI should run at all, I set the PPUMASK value, then the sprites, then I do my UpdatePpu function, then name table, then scrolling position.

Afterwards, I do this:
Code:
   LDA EnableIrq
   BEQ @end

   LDA #160
   STA $C000
   STA $C001
   STA $E001

@end:

And then, after the @end label, I do the music update.

I also tried to put the above code before the sprite updates. (To make sure that the IRQ is definitely still enabled inside vblank.) But it's the same result: Both emulators show it differently.

Now to the IRQ itself:
Code:
Irq:

   PHA
   TXA
   PHA
   TYA
   PHA

   STA $E000

   LDA NameTable
   EOR #%00000011
   ORA #PpuCtrlValue
   STA PpuCtrl

   PLA
   TAY
   PLA
   TAX
   PLA

   RTI

The EnableIrq variable is set somewhere inside the game logic.
NameTable and PpuCtrlValue are buffer variables. PpuCtrl is a constant to the actual register.

The effect is shown in both, the old PPU and new PPU in fceux.

There are no visible glitches in the middle of the line.
Some months ago I found out that, if you change the name table in the middle of a scanline, the change only appears when the next scanline is shown. So, unlike with a mid-frame scrolling change, there are never any visual glitches when you change the value live during rendering. This was true even when I changed the name table by waiting for sprite 0 (before I ever implemented an IRQ, when it was still an MMC1 game).

There's no scrolling here at all.

This is the result:
Attachment:
Screenshots.png
Screenshots.png [ 5.82 KiB | Viewed 4778 times ]

As you see, fceux processes one scanline later.

How can I circumvent this? Even if fceux is not cycle exact, I'd still like to avoid this issue. After all, it refers to a whole pixel row and not just some random glitches in the middle of a row.
Also, the line position is not even arbitrary. The white part is merely supposed to become the dialog box, so of course I want the game to look right in both emulators.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228011)
Make sure the PPU address is low, and not in the range of 2000-3FFF when setting up the MMC3 IRQs. 0000 will do.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228012)
I'm not sure what you mean. Which PPU address? Do you mean PPUADDR/$2006?

O.k., I included
Code:
   LDA #$00
   STA PpuAddr
   STA PpuAddr
before the name table and scrolling updates in NMI. But it's still the same result.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228013)
DRW: The PPU address that you set with $2006 (or change with $2007). Wait until you're done doing updates in vblank and set it to 0 or something similar before setting up the IRQ. (Otherwise you might get an extra ticking of the scanline when it changes at the start of rendering.)

Also, I think it's standard practice to wait until the next scanline in the IRQ before actually setting the new scroll position, not doing it right away like you are here. If your write happens somewhere nonspecific in hblank, that's exactly the kind of thing that emulators like FCEUX get subtly wrong.

The "easy" thing to do is just add a bunch of NOP instructions to your IRQ until it looks correct. You may notice commercial era games tend to do it in a visible part of the scanline, so there's always some jittery pixels visible on that scanline. That's the safest way to do it though.

If you're more careful you can probably find a very precise timing within hblank (on the next scanline after the IRQ begins) that makes all emulators happy. (Once again the easy way is just to add another NOP and test, repeat until good.)

Also, if you want to make it work well in FCEUX, test with both New PPU and Old PPU, because people use both. New PPU is a lot closer to accurate, but you can probably find a timing that satisfies both.

e.g. put this before that PPU write in your IRQ, and increase that number 30 until you're satisfied. (You can do NOP equivalents in a more space efficient way, but just figure out the timing first before you optimize for space.)
Code:
.repeat 30
    nop
.endrepeat
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228015)
Thanks. It works now.

rainwarrior wrote:
DRW: The PPU address that you set with $2006 (or change with $2007). Wait until you're done doing updates in vblank and set it to 0 or something similar before setting up the IRQ. (Otherwise you might get an extra ticking of the scanline when it changes at the start of rendering.)

I changed it after background updates, but before name table and scrolling changes. Is this correct? Because if I do it afterwards, the name table value gets totally confused and the whole screen becomes the white from the other name table.

rainwarrior wrote:
The "easy" thing to do is just add a bunch of NOP instructions to your IRQ until it looks correct. You may notice commercial era games tend to do it in a visible part of the scanline, so there's always some jittery pixels visible on that scanline. That's the safest way to do it though.

I'm not sure why you're worried with jittery pixels. Sure, if you change the scrolling position in the middle of rendering and you do it in an arbitrary scanline, you get graphical artifacts and jumping around.
But in my case, I only change whole name tables. And for some reason, this one is always artifacts-free. No matter where I am in the scanline, a name table change only seems to take place when the next scanline starts.
That's also the reason why I didn't have to care about exact timing when I was still using a sprite 0 split for the mid-frame screen change: Unlike scrolling changes, name table changes never jitter.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228016)
I've got two more questions:

Why does IRQ only work when I put CLI in the initialization code (after writing $40 to $4017 and before setting up the hardware stack).
And why is this nowhere mentioned in the wiki under MMC3? I only saw this because I found a tutorial on the internet.

What's the deal with the idea that backgrounds have to go to nametable 0 and sprites to nametable 1 when using IRQs?
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228017)
DRW wrote:
Why does IRQ only work when I put CLI in the initialization code (after writing $40 to $4017 and before setting up the hardware stack).
And why is this nowhere mentioned in the wiki under MMC3? I only saw this because I found a tutorial on the internet.

Because CLI is the instruction that enables interrupts to affect the CPU. (SEI disables them.)

Why isn't it mentioned under MMC3? I dunno, I guess cause it's part of the CPU not the MMC3. The interrupt flag affects all interrupts (except NMI), it's not specific to the MMC3.

DRW wrote:
I'm not sure why you're worried with jittery pixels. Sure, if you change the scrolling position in the middle of rendering and you do it in an arbitrary scanline, you get graphical artifacts and jumping around.
But in my case, I only change whole name tables. And for some reason, this one is always artifacts-free. No matter where I am in the scanline, a name table change only seems to take place when the next scanline starts.

Well, it is a scroll change regardless, but yes you're right if you only change the horizontal nametable select bit via $2000, that change should be buffered until it gets copied over at pixel 257.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228018)
Thanks for your help. I got a combination now that allows me a glitchless name table switch on both emulators as well as a background bank change for the dialog characters.


Now, what's the deal with this idea that the backgrounds have to go on the left pattern table and the sprites on the right one? Many MMC3 games do this, although other games (NROM, UNROM, MMC1) usually do it the other way around.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228019)
DRW wrote:
Now, what's the deal with this idea that the backgrounds have to go on the left pattern table and the sprites on the right one? Many MMC3 games do this, although other games (NROM, UNROM, MMC1) usually do it the other way around.

The scanline counter works by watching the 13th PPU address line (A12), which is the line that selects between PPU $0000 and $1000. If the background uses tiles from $0000, A12 will remain low throughout the entire scanline, but as soon as the visible scanline ends and the PPU starts fetching sprite tiles from $1000, A12 goes high, and that's what clocks the scanline counter (A12 is supposed to transition from 0 to 1 exactly only once per scanline). If you disobey this rule and swap the pattern tables around, or access sprite tiles from both pattern tables using 8x16 sprites, A12 transitions will not work as expected and that'll confuse the mapper. There other valid combinations that will cause IRQs to fire at predictable times, but the standard way is as you mentioned.

Games that don't have an A12-based scanline counter (or no scanline counter at all) are free to setup their name tables however they want.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228021)
O.k., I only understood a fraction of what you said. :mrgreen:

So, is this only an issue when I switch around the pattern tables during the game? Or do I really have to put background to 0 and sprites to 1? And what happens if I don't (in non-technical terms please: What happens then)?
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228023)
tokumaru wrote:
If the background uses tiles from $0000, A12 will remain low throughout the entire scanline, but as soon as the visible scanline ends and the PPU starts fetching sprite tiles from $1000, A12 goes high, and that's what clocks the scanline counter (A12 is supposed to transition from 0 to 1 exactly only once per scanline).

Actually, A12 transitions from 0 to 1 8 times in that configuration, but the MMC3 has some sort of lowpass filter on its A12 input so it ignores the "fast" toggles that happen when alternating between pattern table and nametable fetches.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228025)
DRW wrote:
Or do I really have to put background to 0 and sprites to 1? And what happens if I don't (in non-technical terms please: What happens then)?
nesdevwiki:MMC3§IRQ Specifics , the "regarding PPU A12" subsection
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228026)
Sorry, but I still don't understand this.

For example:
What is A12? What are rising edges? How does a line remain low and what does this mean at all? What is M2?

Is there any explanation that doesn't include a million words that need their own explanation as well?

I just need a clear description: What might be the issue when the sprites are in nametable 0? Does the counter get confused then? Will there be any glitches? Out of sync issues? Wrong colors? Games freezing?
What is the final consequence, the actual observable issue?

Also, what doesn this mean?
Quote:
The scanline counter will also work when the BG uses the right pattern table ($1000) and the sprites use the left pattern table ($0000), but this is less common.

So, does this mean it doesn't matter? The counter will work with both combinations? If yes, why is this combination less common if it doesn't really make a difference?
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228027)
The counter won't work as expected. This can manifest as irqs firing too early, too late or somewhere in between. The exact outcome depends on what is being rendered.

In short, A12 is address line 12, m2 has something to do with the cpu clock, going high and low to allow for reads and writes on the same bus.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228028)
DRW wrote:
Sorry, but I still don't understand this.
I said to read the "regarding PPU A12" subsection because it directly answers your question without the other jargon. What is unclear about
wiki wrote:
When using 8x8 sprites, if the BG uses $0000, and the sprites use $1000, the IRQ counter should decrement on PPU cycle 260, right after the visible part of the target scanline has ended.
When using 8x8 sprites, if the BG uses $1000, and the sprites use $0000, the IRQ counter should decrement on PPU cycle 324 of the previous scanline (as in, right before the target scanline is about to be drawn).
?

The only thing missing is what happens if you put both background and foreground from the same 4KiB pattern table, for which the answer is: no IRQs at all.

In practice the answer is: Pick the configuration that that gives the horizontal IRQ phase you want. Use the MMC3's "CHR A12 inversion" control to specify whether the background gets the two 2KiB banks, or the sprites get the two 2KiB banks instead.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228029)
DRW wrote:
How does a line remain low

A line is "low" when it carries a low voltage, which represents a value zero. A line is "high" when it carries a high voltage, which represents a value of one. A line "remains" in a state when its value does not change.

DRW wrote:
What is A12?

A12 is address line 12, the line whose state differs between addresses that are 2^12 ($1000) bytes apart. PPU A12 is low when the PPU is reading $0000-$0FFF or $2000-$2FFF, or high when the PPU is reading $1000-$1FFF. (The PPU does not read $3000-$3FFF during rendering.) Converting a few addresses from hexadecimal to binary may help you see the pattern:
Code:
      13 12 11 10  9  8  7  6  5  4  3  2  1  0
$0000  0  0  0  0  0  0  0  0  0  0  0  0  0  0
$0001  0  0  0  0  0  0  0  0  0  0  0  0  0  1
$0FFF  0  0  1  1  1  1  1  1  1  1  1  1  1  1
$1000  0  1  0  0  0  0  0  0  0  0  0  0  0  0
$1001  0  1  0  0  0  0  0  0  0  0  0  0  0  1
$1FFF  0  1  1  1  1  1  1  1  1  1  1  1  1  1
$2000  1  0  0  0  0  0  0  0  0  0  0  0  0  0
$2001  1  0  0  0  0  0  0  0  0  0  0  0  0  1
$2FFF  1  0  1  1  1  1  1  1  1  1  1  1  1  1


DRW wrote:
What are rising edges?

An "edge" is a transition of a digital signal from one state to another. A "rising edge" is such a transition from 0 to 1. Rising edges on A12 indicate a switch from reading $0000-$0FFF to $1000-$1FFF, or from $2000-$2FFF to $1000-1FFF. On the PPU, these represent a transition from the first pattern table to the second, or from the nametables to the second pattern table. During usual MMC3 operation, this happens during the sprite pattern fetch phase of a scanline (x=257 to 320), between dummy nametable fetches and fetches from the second pattern table.

DRW wrote:
What is M2?

M2 is the primary CPU clock signal going into the Game Pak. It has one rising edge and one falling edge for each full CPU cycle, or 1,789,773 of each edge per second.

DRW wrote:
What might be the issue when the sprites are in nametable 0?

Nametables (tilemaps) don't matter for this. Pattern tables (CHR, at $0000-$0FFF and $1000-$1FFF) do.

DRW wrote:
Does the counter get confused then?

Yes.

DRW wrote:
Will there be any glitches? Out of sync issues? Wrong colors? Games freezing?

What is the final consequence, the actual observable issue?

Using sprites in $0000 and background tiles in $1000 causes the IRQ to trigger around X=325 instead of X=261. If the rest of the timing of the MMC3 interval timer handler assumes X=261, as is the case for the majority of MMC3 games, it might produce a visible glitch that involves the background visibly changing in the middle of a scanline on the split's border, or the background below the split shaking up and down by one pixel, or both.

Using 8x16-pixel sprites from both pattern tables confuses the timer even more, as this increases the time between edges on PPU A12 past the time that the MMC3 is able to filter out, causing the timer to count more than once per scanline. The visible effect of this is a split that appears 8, 16, or more scanlines above where you expect it to appear.

DRW wrote:
Also, what doesn this mean?
Quote:
The scanline counter will also work when the BG uses the right pattern table ($1000) and the sprites use the left pattern table ($0000), but this is less common.

So, does this mean it doesn't matter? The counter will work with both combinations? If yes, why is this combination less common if it doesn't really make a difference?

The going hypothesis is that Nintendo provided a manual with the MMC3, and the manual recommended use of background at $0000 and sprites at $1000.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228030)
For once I do understand something.

A12 is this bit in the PPU address.

0001 0000 0000 0000

So, when the PPU is reading from tileset #0, Addresses 0-fff, this bit is zero. When the PPU is reading from tileset #1, addresses 1000-1fff, this bit is one.

If you have the PPU control set to have BG on tileset #0, and sprites on tileset #1, then at exactly dot 256 of a scanline A12 will go from 0 (low) to 1 (high). (It spends the entire scanline drawing BG tiles, and evaluates the next line's sprites during Hblank).

If however, you have BG on tileset #1 and Sprites on tileset #0, A12 will remain high (1) the entire scanline, and won't go from low to high till the end of the H blank period, and the IRQ will fire at the start of the NEXT line.

If you have both BG and Sprites on tileset #0 (or both on #1), then A12 will stay low (0) the entire screen. And the IRQ won't fire.

(Several people posted while I was typing, oh well).
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228036)
tepples wrote:
The going hypothesis is that Nintendo provided a manual with the MMC3, and the manual recommended use of background at $0000 and sprites at $1000.

It's less of a hypothesis and actually confirmed. (Pages 3 and 4 of both MMC3 manuals (1987/12/15 and 1988/05/24) both cover this)
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
by on (#228038)
DRW wrote:
What might be the issue when the sprites are in nametable 0? Does the counter get confused then? Will there be any glitches? Out of sync issues? Wrong colors? Games freezing?
What is the final consequence, the actual observable issue?

The worse that can happen is that the IRQ will fire on the wrong scanline, which can be pretty bad.

Quote:
Quote:
The scanline counter will also work when the BG uses the right pattern table ($1000) and the sprites use the left pattern table ($0000), but this is less common.

So, does this mean it doesn't matter? The counter will work with both combinations? If yes, why is this combination less common if it doesn't really make a difference?

Using $0000 for sprites and $1000 for the background will cause the IRQ to fire at a different time in the scanline, but will work fine if you use 8x8 sprites exclusively. If you use 8x16 sprites though, even if you don't explicitly use patterns from the $1000 side, the PPU will still do some dummy sprite fetches from that side, causing the scanline counter to malfunction. That's probably the reason why using $0000 for the background and $1000 for sprites is the suggested configuration.