MMC3 scanline counter off by 1 between fceux and Nestopia
Moderator: Moderators
MMC3 scanline counter off by 1 between fceux and Nestopia
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?
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?
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
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.
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
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?
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
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.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).
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
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:
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:
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: 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.
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: Select all
LDA EnableIrq
BEQ @end
LDA #160
STA $C000
STA $C001
STA $E001
@end: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: Select all
Irq:
PHA
TXA
PHA
TYA
PHA
STA $E000
LDA NameTable
EOR #%00000011
ORA #PpuCtrlValue
STA PpuCtrl
PLA
TAY
PLA
TAX
PLA
RTINameTable 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: 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.
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
Make sure the PPU address is low, and not in the range of 2000-3FFF when setting up the MMC3 IRQs. 0000 will do.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
I'm not sure what you mean. Which PPU address? Do you mean PPUADDR/$2006?
O.k., I includedbefore the name table and scrolling updates in NMI. But it's still the same result.
O.k., I included
Code: Select all
LDA #$00
STA PpuAddr
STA PpuAddrAvailable now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
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.)
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: Select all
.repeat 30
nop
.endrepeatRe: MMC3 scanline counter off by 1 between fceux and Nestopi
Thanks. It works now.
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.
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: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'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.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.
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.
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
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?
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?
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
Because CLI is the instruction that enables interrupts to affect the CPU. (SEI disables them.)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.
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.
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.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.
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
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.
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.
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
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.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.
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
O.k., I only understood a fraction of what you said. 
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)?
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)?
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg
Re: MMC3 scanline counter off by 1 between fceux and Nestopi
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.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).
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
P.S. If you don't get this note, let me know and I'll write you another.