It is currently Tue Nov 20, 2018 5:07 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Wed Oct 24, 2018 3:00 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1737
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?

_________________
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


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 7:05 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10977
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 9:00 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4105
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!


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 9:48 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10977
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 11:08 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1737
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 1032 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.

_________________
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


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 11:26 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4105
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!


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 11:41 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1737
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.

_________________
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


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 12:06 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6961
Location: Canada
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


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 12:27 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1737
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.

_________________
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


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 12:32 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1737
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?

_________________
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


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 12:36 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6961
Location: Canada
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.


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 2:59 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1737
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.

_________________
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


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 3:32 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10977
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 3:44 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1737
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)?

_________________
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


Top
 Profile  
 
PostPosted: Wed Oct 24, 2018 3:51 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1440
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.

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


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 1 guest


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

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group