Causes for erroneous scroll changes?
Moderator: Moderators
Causes for erroneous scroll changes?
Hi again. I'm working on what I'd call an advanced animation routine, and it's come along so nicely, but... for some reason each time the animation loops, the vertical scrolling is knocked down for a single frame.
I've been using FCEUX's debugger to set breakpoints on writing to $2005, because that's the only thing that could effect my scrolling... right? Or is there something else that could cause it? Running through the code, it seems like the scroll register is only written to near the beginning of my NMI, and I write #$00 to it twice (as my trace logger verifies).
So is there something else that could by janking my background around?
I've been using FCEUX's debugger to set breakpoints on writing to $2005, because that's the only thing that could effect my scrolling... right? Or is there something else that could cause it? Running through the code, it seems like the scroll register is only written to near the beginning of my NMI, and I write #$00 to it twice (as my trace logger verifies).
So is there something else that could by janking my background around?
Re: Causes for erroneous scroll changes?
Two guesses:
* $2006 and $2005 control the same bits, just in a different order
Given
* Make sure that your vblank handler isn't overflowing into the active drawing portion of the screen; at that point $2005 and $2006 start behaving differently.
* $2006 and $2005 control the same bits, just in a different order
Given
that's probably it. You'll want to write the scroll value at the end of your nmi handler, after any nametable / pattern table updates.it seems like the scroll register is only written to near the beginning of my NMI, and I write #$00 to it twice (as my trace logger verifies).
* Make sure that your vblank handler isn't overflowing into the active drawing portion of the screen; at that point $2005 and $2006 start behaving differently.
Re: Causes for erroneous scroll changes?
This is good information but... I'm not sure if I'm spilling out of vblank or not. I don't really understand the 'scanline' information on the FCEUX debugger or what might be a better tool. I am really worried about spilling out of vblank though, because I am attempting to go full BattleToads. I'm using ChrRam to load the tiles for a single frame of animation into memory at once. But I'm only copying eight tiles tops, and they're being moved directly from ROM according to a run-length style buffer in ram. I don't think I'm doing anything too rough...lidnariq wrote:Make sure that your vblank handler isn't overflowing into the active drawing portion of the screen; at that point $2005 and $2006 start behaving differently.
Re: Causes for erroneous scroll changes?
Scanlines in FCEUX's debugger unfortunately don't indicate timing while out of the active picture. Certainly once it becomes 0 (after having been 239), rendering has restarted.
Re: Causes for erroneous scroll changes?
Scanlines 0-239 = rendering.I don't really understand the 'scanline' information on the FCEUX debugger
Scanlines 240+ = v-blank
For a game without parallax scrolling or split screens, all writes to 2005-2006-2007 should be done during v-blank.
nesdoug.com -- blog/tutorial on programming for the NES
Re: Causes for erroneous scroll changes?
dougeff wrote:Scanlines 0-239 = rendering.
Scanlines 240+ = v-blank
Well... yeah, it's spilling out of VBlank. Just friggin barely.lidnariq wrote:Scanlines in FCEUX's debugger unfortunately don't indicate timing while out of the active picture. Certainly once it becomes 0 (after having been 239), rendering has restarted.
Which really makes me wonder how in the hell BattleToads is able to update tiles for both players simultaneously without having this problem. I thought I wrote a really efficient copier. I wonder if there's a faster way of doing this, but maybe that wouldn't be good question for the newbie forum...?
Re: Causes for erroneous scroll changes?
Battletoads keeps rendering disabled at the top of the screen (before status bar) to get more time for updates. The amount of extra blanking can even change for each level.Guilty wrote:Which really makes me wonder how in the hell BattleToads is able to update tiles for both players simultaneously without having this problem. I thought I wrote a really efficient copier. I wonder if there's a faster way of doing this, but maybe that wouldn't be good question for the newbie forum...?
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Causes for erroneous scroll changes?
The topic of writing fast PPU uploads has come up many times in the past. Here's two relevant threads:
viewtopic.php?f=2&t=12325
viewtopic.php?f=2&t=13285
viewtopic.php?f=2&t=12325
viewtopic.php?f=2&t=13285
Re: Causes for erroneous scroll changes?
That's something I've heard before. But, unless I'm very confused, my rendering is disabled until my ppu updates are all finished; at the start of the nmi I write #$00 to PPUMASK and don't touch it again till shortly before the RTI. ...that is how it's done, right?thefox wrote:Battletoads keeps rendering disabled at the top of the screen (before status bar) to get more time for updates. The amount of extra blanking can even change for each level.
Well right off the bat I see a point of interest: Sprite DMA. I'll be looking into how that might effect my process, and also read the rest of that thread+the other you linked.rainwarrior wrote:The topic of writing fast PPU uploads has come up many times in the past. Here's two relevant threads:
Re: Causes for erroneous scroll changes?
You can skip sprite DMA every other frame, if it will help you get it in under v-blank period. (Alternate frames)
nesdoug.com -- blog/tutorial on programming for the NES
Re: Causes for erroneous scroll changes?
Yeah. However, if you keep rendering disabled beyond VBlank, you can no longer rely on PPU to initialize its internal registers correctly when rendering starts. You have to do it manually (with a mix of $2005 and $2006 writes) instead. Moreover, you have to make sure that you always set the scroll at the (approximately) same time in each frame, otherwise you'll get a shaky screen. I think Battletoads does this by polling for sprite 0 hit after re-enabling rendering, just before the status bar.Guilty wrote:That's something I've heard before. But, unless I'm very confused, my rendering is disabled until my ppu updates are all finished; at the start of the nmi I write #$00 to PPUMASK and don't touch it again till shortly before the RTI. ...that is how it's done, right?thefox wrote:Battletoads keeps rendering disabled at the top of the screen (before status bar) to get more time for updates. The amount of extra blanking can even change for each level.
EDIT: Battletoads seems to poll for sprite 0 hit at the bottom of the status bar, so that would imply that it has to use a statically timed VBlank handler.
Last edited by thefox on Sat May 21, 2016 7:53 pm, edited 1 time in total.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Causes for erroneous scroll changes?
Depending on whether you turn rendering back on before or after the end of vblank, you'll have a different result.Guilty wrote:That's something I've heard before. But, unless I'm very confused, my rendering is disabled until my ppu updates are all finished; at the start of the nmi I write #$00 to PPUMASK and don't touch it again till shortly before the RTI. ...that is how it's done, right?
The scroll position is set up from the last values written to $2005 (or $2006) near the end of vblank only if rendering is on. If rendering is off at this point, the setup is skipped, and you'll need to set it up manually. Manually setting the scroll is a little bit more complicated, instructions here: NESDev Wiki: PPU scrolling # Split X/Y scroll
Edit: thefox got to it first, and made the additional point that if manually scrolling you need to ensure consistent timing somehow (either measure and adjust all branches of your NMI code to have identical timing, or use something else to synchronize with).
Re: Causes for erroneous scroll changes?
This is the reason you're having a slight scroll issue, instead of severe glitching and VRAM corruption. In order to properly use forced blanking, you must make sure you're enabling rendering at the exact same time every frame, or the screen will jump as a consequence of starting rendering at different scanlines each frame. To time this right, you either need to make the entire vblank handler constant-timed (pretty annoying to pull off), detect the end of vblank by waiting for the sprite overflow or sprite 0 hit flags to be cleared (you need to be sure the flag did get set during the frame) and make only the final operations constant-timed, or use cycle-based mapper IRQs. Also, after the vertical blank ends, the scroll can only be fully set by combined $2005/6 writes ("the skinny on NES scrolling").Guilty wrote:But, unless I'm very confused, my rendering is disabled until my ppu updates are all finished;
This is not necessary if you're absolute sure there will be no VRAM accesses past the end of vblank. It is necessary if you're doing forced blanking, but some people feel safer doing this even if they're not.at the start of the nmi I write #$00 to PPUMASK and don't touch it again till shortly before the RTI. ...that is how it's done, right?
I personally prefer to not waste any time turning rendering of and on so I can use every last cycle for VRAM updates, which I carefully time to never spill.