PowerPak + Tetramino = sprite flicker
Moderator: Moderators
X position, I don't know. I was scrolling the screen with a half cut-off sprite where the rendering was disabled, and the sprite seems to be able to display itself on all parts of the scanline, so it might be disabled in hblank.
Y position, I'm not good at counting blank scanlines, but it's definitely 16 or more scanlines before the natural end of the frame. Looks like maybe 24.
Y position, I'm not good at counting blank scanlines, but it's definitely 16 or more scanlines before the natural end of the frame. Looks like maybe 24.
Good idea!qbradq wrote:You can set up a breakpoint for the PPU control registers in Nintendulator to see when it disables the rendering. Nintendulator has this nice PPU scanline and pixel counter when single-stepping.
If I'm reading this correctly:
SLNum: 209
CPU Ticks: ranges from 306-317 / 102-105
So scanline 209, but I dunno what pixel that translates to. It's outside of the 64-255 range though.
(The breakpoint I set was on $E2BF, and I used fceux to find that address by looking for writes to $2001)
I'm aware of that, but I don't know which of the theoretical 341 pixels are the 256 that show the game screen.tepples wrote:When things are in a 3:1 ratio like 306/102, it probably means the first is PPU cycles (i.e. dots) and the second is CPU cycles.
So, after reading Brad Taylor's doc (which REALLY could use some visuals... this might be good for wikification), it seems that the screen rendering is turned off offscreen, during the time where the tile data for the next scanline's sprites is fetched. I'm assuming this is considered hblank, but I'm not sure.
Again, is this game susceptible to the sprite oam glitch by doing this?
Re: PowerPak + Tetramino = sprite flicker
Did anyone ever get around to testing this quirk for the situation where rendering is disabled for N number of scanlines, and then re-enabled, instead of just happening at the end of the frame?
I'm trying to have a black bar at the top instead of the bottom, and since I don't want the alternative dot crawl pattern of Battletoads, I have rendering enabled for 1 line just to prevent that. I wait for the previously set sprite#0 hit flag to clear to find end of vblank, delay N lines (normally one but about 20 in my current debug setting just to see what's going on) and then disable rendering in the "safe" area of 64-250.
But it doesn't seem to help, even when no sprites are intersecting. Or more specifically, it works fine for most reset states, but I can sometimes get it into a reset state where sprites get corrupted. And that seems to include sprite#0, which causes the "wait for end of vblank" sequence to fail miserably since sprite#0 doesn't get hit.
Based on the previous theories, is it even possible to do this? If the sprite evalution state machine will have been interrupted in a state of acessing secondary OAM, I guess secondary OAM should have the state from where it was turned off while scanning of primary OAM would depend on pixel location where screen was re-enabled again?
I'm also quite surprised why I never encountered this bug when making Years Behind, where I did the following seemingly more complicated sequences:
* Waiting for sprite#0 hit flag to get cleared to find end of vblank
* Enabling rendering
* Waiting for sprite#0 hit flag to get set
* Turning off rendering to re-write the palette for the status bar
* Turning on rendering
* Turning off rendering to restore the palette
* Turning on Rendering
* Finally, turning off rendering prematurely before the frame ends
...all without having any troubles of this kind as far as I can remember. Then again, did anyone ever verify that the PAL NES has the same problem? (I'm using an NTSC NES now while Years Behind was developed exclusively on PAL)
I'm trying to have a black bar at the top instead of the bottom, and since I don't want the alternative dot crawl pattern of Battletoads, I have rendering enabled for 1 line just to prevent that. I wait for the previously set sprite#0 hit flag to clear to find end of vblank, delay N lines (normally one but about 20 in my current debug setting just to see what's going on) and then disable rendering in the "safe" area of 64-250.
But it doesn't seem to help, even when no sprites are intersecting. Or more specifically, it works fine for most reset states, but I can sometimes get it into a reset state where sprites get corrupted. And that seems to include sprite#0, which causes the "wait for end of vblank" sequence to fail miserably since sprite#0 doesn't get hit.
Based on the previous theories, is it even possible to do this? If the sprite evalution state machine will have been interrupted in a state of acessing secondary OAM, I guess secondary OAM should have the state from where it was turned off while scanning of primary OAM would depend on pixel location where screen was re-enabled again?
I'm also quite surprised why I never encountered this bug when making Years Behind, where I did the following seemingly more complicated sequences:
* Waiting for sprite#0 hit flag to get cleared to find end of vblank
* Enabling rendering
* Waiting for sprite#0 hit flag to get set
* Turning off rendering to re-write the palette for the status bar
* Turning on rendering
* Turning off rendering to restore the palette
* Turning on Rendering
* Finally, turning off rendering prematurely before the frame ends
...all without having any troubles of this kind as far as I can remember. Then again, did anyone ever verify that the PAL NES has the same problem? (I'm using an NTSC NES now while Years Behind was developed exclusively on PAL)
Re: PowerPak + Tetramino = sprite flicker
My bet is that this problem does not ever happens on PAL NES, but this would have to be confirmed. At least the DPCM-interferring-with-joypad-reads glitch does never happen on PAL NES.
You should also rememebr that the NTSC NES has 4 possible states possible at reset/power on while the PAL NES only have 1.
Last edited by Bregalad on Sun Jan 13, 2013 2:02 pm, edited 2 times in total.
Re: PowerPak + Tetramino = sprite flicker
You've lost me there... didn't Blargg come to the opposite conclusion in this post, which explained how there are 8 different power-up states on PAL? And the readme.txt in Blargg's synchronization package also talk of how the exact position of the writes "will change randomly each time you press reset".You should also rememebr that the NTSC NES has 4 possible states possible at reset/power on while the PAL NES only have 1.
This sure isn't a totally scientific test... but I've now played around with my game on my PAL console and no matter where I disable/enable rendering and no matter where my metasprites go, I get no corrupted sprites. So I'm prepared to accept your hypothesis of this hardware bug being fixed in the PAL NES as fact. That makes one more aspect where the PAL NES is superior to the NTSC one.
I've also realized that this OAM corruption bug totally kills my plan to have a really cool water effect in my game by disabling the screen/switching on the monochrome bit and updating almost the entire palette to get a noisy white scanline followed by turning on rendering/switching off the monochrome bit and starting a wavy effect loop. Because it wouldn't be worth much if all water would need to be placed at a point where game characters can't pass through it
Or alternatively, I guess I could go with the previously made statement that sprite flickering "characterizes NES games", and just let NTSC users suffer a flicker-fest that PAL users are spared of whenever there's water on a screen.
Oh PAL-centric innonence of my nesdev youth, how I want thee back... never realized back then that I was spoiled with more simplicities than just long vblank times!
Re: PowerPak + Tetramino = sprite flicker
Hmm, I still wonder whether disabling/enabling rendering only during dot 320-340 could magically avoid the bug. With Blargg's synchronization libraries, it seems like it shouldn't be too difficult to make the 1-(CPU) cycle store fall within that window...
Re: PowerPak + Tetramino = sprite flicker
Oh I almost forgot about that. Blargg is probably right because he's way better than me at this kind of stuff. So yeah there is multiple alignments and I even proved it myself and I don't even remember it. Yeah. Just discard my post above.You've lost me there... didn't Blargg come to the opposite conclusion in this post, which explained how there are 8 different power-up states on PAL? And the readme.txt in Blargg's synchronization package also talk of how the exact position of the writes "will change randomly each time you press reset".
I never really understood where those 8 alignments comes from.
PAL NES is technically superior, but unfortunately 99% of the game library was made for the NTSC NES which made their PAL version suck. Even European-developped games, such as Battletoads, runs better on NTSC because the music wasn't adapter to PAL properly.
Re: PowerPak + Tetramino = sprite flicker
I had the exact same problem. I could never fix the sprite glitching, so now I keep only the background disabled, and to mask sprites I put 9 high priority transparent sprites at the very top of the screen. This completely hides sprites for the first 17 scanlines, and doesn't mess with the dot crawl pattern.Bananmos wrote:I'm trying to have a black bar at the top instead of the bottom, and since I don't want the alternative dot crawl pattern of Battletoads, I have rendering enabled for 1 line just to prevent that.
Yes, having to waste 9 sprites is far from optimal, but it's not so bad when you use 8x16 sprites (you can still have more "sprite pixels" onscreen than you can with all 64 8x8 sprites), and is also better than what Felix the Cat and Alfred Chicken do, which wastes nearly a whole column of sprites and effectively reduces the sprites-per-scanline limit to 7.
With 9 sprites at the very top of the screen I can use the sprite overflow flag to detect the end of VBlank instead, since sprite 0 hits are harder to guarantee when you scroll both horizontally and vertically.I wait for the previously set sprite#0 hit flag to clear to find end of vblank
I'm sorry for not being able to help with the actual problem, but I wanted to share my experience with it. Since I couldn't solve the problem myself I just went with another solution that used more well documented behavior.
Re: PowerPak + Tetramino = sprite flicker
Thanks for the tip Tokumaru, but the main reason for my top black bar is not to hide sprites but to get some extra vblank time to do CHR animation. I guess the difficulty of this seriously makes me consider CHR-ROM instead though. But even with that my idea for the water effect still can't be done without turning screen off/on...
I realized my game's timing is a bit too unreliable to use Blarggs sync code at the moment, since some code takes more than a frame, which also means I can't always do DMA. Probably better to play around with Blarrg's example code instead, as this has already turned a seemingly simple task of adding more sprite animations to my game into a task of rewriting its code into a testbench...
Trying to move the point of disabling/enabling screen to always be around dot 330 did however show promises even without Blargg synchronization: Glitching is now totally independent of whether my metasprite intersects the black bar or not, and I get the following different glitch behaviors instead:
1: Sprites 2 and 3 have flickering chr patterns
2: Sprites 2 and 3 have flickering chr patterns, but less noticable than in case A
3: No sprite flickering, but palette color index $01 and $0E get changed in some frames
4: No sprite flickering, but palette color index $02 gets changed in some frames
5: No sprite flickering, but palette color index $0E gets changed in some frames
The glitch patterns I get seem to be a combination of reset state, and timing differences somehow trigerred by the "software reset" feature in my very simple in-game level editor in pause mode: Pressing SELECT turns screen off, copies a saved map in ROM to the normal RAM location and updates the PPU memory with it.
So at least I'm getting somewhere, as case 1 and 2 would actually be acceptable to have in a game - you would just have to make sure not to use those sprite indices. And with Blargg Synchronization it should probably be possible to squeeze the write into the "perfect" spot. I already have code to avoid using the first sprite index for any metasprites so changing that to start at index 4 is no biggie, even if it'd waste 4 sprites out of 64.
The other cases really confuse me though, as I don't understand how the palette entries could get corrupted unless written to? Seems to be yet another undocumented "feature" of the NES PPU... I have seen weird stuff like this happen if you write to $2007 while rendering is enabled, but I make sure to both lda $2002 to clear the latch, write #$08 to $2000 and #$00 to $2001 and double-write a constant chr pattern address to $2006 before doing any of the chr writes to $2007 in the black-bar area.
EDIT: I found the cause of the palette glitches. I had forgotten to set the scroll values before waiting for end of vblank, and since I write the palette in every vblank that happened to be what VADDR was pointing at in the first scanlines. As long as rendering is enabled, the PPU seems to read just the lower bits of the address and thus rendering a seemingly correct picture (albeit with shifted scroll values). But for some reason I do not yet understand it will corrupt the palette entries when you disable rendering and VADDR is pointing at the palette region.
After fixing that, only two reset states seem to exist: The one without any fliclkering, and the one where it only affects makes sprites 2 and 3 flicker. It might be possible to always get the first case deterministically by Blargg Synchronization, but it's probably not worth doing that for this alone. I'm happy to never use the first four sprites if it can let me freely do PPU updates anywhere in the screen. And it should allow me to do the planned water effect as well!
So from what I can tell so far it seems that the easier guidelines for avoiding this hardware quirk are: Make sure disabling/enabling the screen happens around dot 330, and avoid using sprites 2 and 3.
I realized my game's timing is a bit too unreliable to use Blarggs sync code at the moment, since some code takes more than a frame, which also means I can't always do DMA. Probably better to play around with Blarrg's example code instead, as this has already turned a seemingly simple task of adding more sprite animations to my game into a task of rewriting its code into a testbench...
Trying to move the point of disabling/enabling screen to always be around dot 330 did however show promises even without Blargg synchronization: Glitching is now totally independent of whether my metasprite intersects the black bar or not, and I get the following different glitch behaviors instead:
1: Sprites 2 and 3 have flickering chr patterns
2: Sprites 2 and 3 have flickering chr patterns, but less noticable than in case A
3: No sprite flickering, but palette color index $01 and $0E get changed in some frames
4: No sprite flickering, but palette color index $02 gets changed in some frames
5: No sprite flickering, but palette color index $0E gets changed in some frames
The glitch patterns I get seem to be a combination of reset state, and timing differences somehow trigerred by the "software reset" feature in my very simple in-game level editor in pause mode: Pressing SELECT turns screen off, copies a saved map in ROM to the normal RAM location and updates the PPU memory with it.
So at least I'm getting somewhere, as case 1 and 2 would actually be acceptable to have in a game - you would just have to make sure not to use those sprite indices. And with Blargg Synchronization it should probably be possible to squeeze the write into the "perfect" spot. I already have code to avoid using the first sprite index for any metasprites so changing that to start at index 4 is no biggie, even if it'd waste 4 sprites out of 64.
The other cases really confuse me though, as I don't understand how the palette entries could get corrupted unless written to? Seems to be yet another undocumented "feature" of the NES PPU... I have seen weird stuff like this happen if you write to $2007 while rendering is enabled, but I make sure to both lda $2002 to clear the latch, write #$08 to $2000 and #$00 to $2001 and double-write a constant chr pattern address to $2006 before doing any of the chr writes to $2007 in the black-bar area.
EDIT: I found the cause of the palette glitches. I had forgotten to set the scroll values before waiting for end of vblank, and since I write the palette in every vblank that happened to be what VADDR was pointing at in the first scanlines. As long as rendering is enabled, the PPU seems to read just the lower bits of the address and thus rendering a seemingly correct picture (albeit with shifted scroll values). But for some reason I do not yet understand it will corrupt the palette entries when you disable rendering and VADDR is pointing at the palette region.
After fixing that, only two reset states seem to exist: The one without any fliclkering, and the one where it only affects makes sprites 2 and 3 flicker. It might be possible to always get the first case deterministically by Blargg Synchronization, but it's probably not worth doing that for this alone. I'm happy to never use the first four sprites if it can let me freely do PPU updates anywhere in the screen. And it should allow me to do the planned water effect as well!
So from what I can tell so far it seems that the easier guidelines for avoiding this hardware quirk are: Make sure disabling/enabling the screen happens around dot 330, and avoid using sprites 2 and 3.
Last edited by Bananmos on Sun Jan 13, 2013 6:18 pm, edited 1 time in total.
Re: PowerPak + Tetramino = sprite flicker
Yeah, my problem was EXACTLY the same as yours. My blank bar was meant for hiding scrolling glitches AND for extra VRAM updates, but it was so much trouble that I decided to cut back on the CHR animations (not as many tiles animate each frame). The possibility of using the MMC3 was indeed really tempting.Bananmos wrote:Thanks for the tip Tokumaru, but the main reason for my top black bar is not to hide sprites but to get some extra vblank time to do CHR animation. I guess the difficulty of this seriously makes me consider CHR-ROM instead though.
Yeah, that's a tough one.But even with that my idea for the water effect still can't be done without turning screen off/on...
I'm very surprised by this too! Never heard of this!The other cases really confuse me though, as I don't understand how the palette entries could get corrupted unless written to?