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.

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?

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.

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 [ 5.82 KiB | Viewed 2730 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.

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.)

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.

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.

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.

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.

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.

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)?

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.

_________________Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

Who is online

Users browsing this forum: No registered users and 4 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum