Causes for erroneous scroll changes?

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
Guilty
Posts: 93
Joined: Fri Apr 08, 2016 5:58 pm
Location: California, USA

Causes for erroneous scroll changes?

Post by Guilty »

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?
lidnariq
Posts: 10677
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Causes for erroneous scroll changes?

Post by lidnariq »

Two guesses:

* $2006 and $2005 control the same bits, just in a different order
Given
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).
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.

* 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.
User avatar
Guilty
Posts: 93
Joined: Fri Apr 08, 2016 5:58 pm
Location: California, USA

Re: Causes for erroneous scroll changes?

Post by Guilty »

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.
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
Posts: 10677
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Causes for erroneous scroll changes?

Post by lidnariq »

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.
User avatar
dougeff
Posts: 2875
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Causes for erroneous scroll changes?

Post by dougeff »

I don't really understand the 'scanline' information on the FCEUX debugger
Scanlines 0-239 = rendering.
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
User avatar
Guilty
Posts: 93
Joined: Fri Apr 08, 2016 5:58 pm
Location: California, USA

Re: Causes for erroneous scroll changes?

Post by Guilty »

dougeff wrote:Scanlines 0-239 = rendering.
Scanlines 240+ = v-blank
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.
Well... yeah, it's spilling out of VBlank. Just friggin barely.
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...?
User avatar
thefox
Posts: 3139
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: Causes for erroneous scroll changes?

Post by thefox »

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...?
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.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Causes for erroneous scroll changes?

Post by rainwarrior »

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
User avatar
Guilty
Posts: 93
Joined: Fri Apr 08, 2016 5:58 pm
Location: California, USA

Re: Causes for erroneous scroll changes?

Post by Guilty »

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.
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?
rainwarrior wrote:The topic of writing fast PPU uploads has come up many times in the past. Here's two relevant threads:
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.
User avatar
dougeff
Posts: 2875
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Causes for erroneous scroll changes?

Post by dougeff »

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
User avatar
thefox
Posts: 3139
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: Causes for erroneous scroll changes?

Post by thefox »

Guilty wrote:
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.
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?
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.

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
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Causes for erroneous scroll changes?

Post by rainwarrior »

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?
Depending on whether you turn rendering back on before or after the end of vblank, you'll have a different result.

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

Re: Causes for erroneous scroll changes?

Post by tokumaru »

Guilty wrote:But, unless I'm very confused, my rendering is disabled until my ppu updates are all finished;
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").
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?
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.

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.
Post Reply