While testing some code with banking (which is now working fine), I realized that when I did a soft reset, for some reason it shows data from the OAM that was used before the reset.
Confused by the fact that I know that the startup code do reset the ram, which would clear the OAM buffer, it seems that it doesn't start at the same place as when you do a hard reset.
What did I missed? I'm surprised after all these years that I never knew about that issue. I guess it is because my engine is now starting to do a lot more than before and those bugs are now creeping out.
Clearing the shadow OAM in main RAM (often at $0200-$02FF) doesn't clear the OAM on the PPU itself. If you want to clear OAM, you need to push the shadow OAM to the PPU with a $4014 write during blanking. (Or on NTSC, just leave rendering off for more than a couple dozen scanlines.)
my NMI does push OAM on every vblank so something must be not doing what it's supposed to be. For now it's not a big issue but I will need to figure it out. Hmmm...
edit:
Maybe you where on to something. What I'm testing at the moment is not pushing any sprite yet so in that case, the OAM would not refresh. Maybe I should just flush the OAM on purpose during reset then. I will test that right away.
Thanks!
edit2:
On reset, I was updating the buffer with $F8 but I was not pushing it at all. I just changed that and it is now working fine. I was letting the first nmi updating the OAM but since my test doesn't use sprite yet, it was never pushed at all.
I execute an OAM-DMA the first thing after the second vblank wait in the init code to initialize OAM. After that I initialize the palettes. Since OAM-DMA must happen early in vblank for PAL compatibility and palette must be in vblank I think it makes sense to initialize these two first after a vblank wait before turning off forced blanking.
It's fine to initialize palette on any vblank, but OAM doesn't really need to be "initialized" ahead of time at all. It will decay to randomness whenever rendering is off anyway.
Yeah on NTSC, but how fast does that happen? Unless the initializations after that are long it might still make it no? Otherwise you'll need a third vblank wait just to init OAM before turning rendering on. Not that I've ever noticed any garbage on the screen or anything the first frame when not initializing OAM on a real Famicom.
Pokun wrote:
How fast does that happen?
Only a few milliseconds. If rendering is off, the OAM will stay stable for just barely longer than a vblank. Basically it only lasts the very minimum it has to. (It doesn't go all at once though, that's just the point where bits start dropping off. It takes longer to fully corrupt.)
I see, then I guess there is normally little point in flushing OAM during init.
If no games does this I can't think of a reason you have to go out of your way to initialize OAM before turning on display.