The vertical scroll can't be changed mid-screen through normal means, because of the way the PPU renders the screen. The scroll register, $2005, only affects the temporary VRAM address register, and parts of this register are copied to the actual VRAM address at key moments. At the beginning of the picture, everything is copied, but during rendering, only the X component is copied every scanline, so that the PPU can start each scanline from the left. The Y coordinate is only incremented from the initial value during the whole picture, which is why changing the temporary VRAM address does nothing.

To force a VRAM address update, you have to write to $2006. If you only need to "snap" to whole tiles, which is probably the case with a status bar, 2 $2006 writes will do, but if you need pixel-perfect precision you might need the infamous $2006/5/5/6 trick.

Note that the fine X scroll is stored somewhere else, so you still need a $2005 write if you want to change it.

The need for combining $2006 and $2005 writes for pixel-perfect scrolling arises from the fact that the highest bit of the fine Y scroll is automatically cleared by the PPU on the first write to $2006, so the only way to set it by using a $2006/5/5/6 sequence. Only on the final $2006 write the VRAM address register is changed.

EDIT: This is what the "The skinny on NES scrolling" document is all about. It describes how and when the temporary VRAM register and the actual VRAM register are changed.

Last edited by tokumaru on Sun Jan 08, 2017 2:38 pm, edited 1 time in total.

I believe Zelda 1 uses a combination of switching to single-screen mirroring (since it uses MMC1) and some of what tokumaru described above. It doesn't appear to use sprite 0 hit (just in case someone brings that up -- I checked in NO$NES).

I believe Zelda 1 uses a combination of switching to single-screen mirroring (since it uses MMC1) and some of what tokumaru described above.

Yeah, I noticed the mirror switching. This one is a good general way to do horizontal and vertical scrolling in the same game, so that you don't have to fiddle around with graphical artifacts. But the mirror switching is still unrelated to the status bar tricks, so yeah, that particular issue is still done with those other methods.

Thanks for your help. I'll have to see whether I do further research for this or whether I simply use a small status bar created from sprites or whether I simply disable rendering during a screen switch.

DRW, there's no need to be scared off by this. Since the status bar is always in the same place, you don't even need to calculate the values to write in real time, you can simply use hardcoded values and that's it.

If you're doing vertical scrolling with a status bar, there are basically 3 possibilities:1. Status bar is at the bottom - you do a 6-6-5 write at the split point (6-6 to set render location, 5 to set fine X scroll)2. Status bar is at the top, and you have a 4 scanline gap below it - for fine Y scroll of 0-3, you do a 6-6-5 write at the bottom of the gap, and for fine Y scroll of 4-7 you do a 6-6-5 write at the top of the gap.3. Status bar is at the top, and you have no gap - you do a 6-5-5-6 write at the split point

Most games used technique #1 (SMB3, Startropics) or #2 (Castlevania 3, Battletoads) - technique #3 wasn't really known until we discovered it.

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

It has pattern table layouts for different setups of lines coming from the horizon towards the screen, and bankswitches between them several times mid-screen to create vertical detail, and changes the split points over time to create movement. It also changes the horizontal scroll several times when moving the screen sideways, but I'm not sure whether it touches the vertical scroll.

EDIT: Your debugger is configured to display the state of the PPU on scanline 200, which happens to be the last pattern you're seeing on the screen (big cyan stripe on the left, blue on the right), but if you change it to show the state on previous scanlines you'll see each one of the stripe configurations at a time.

If you're doing vertical scrolling with a status bar, there are basically 3 possibilities:1. Status bar is at the bottom - you do a 6-6-5 write at the split point (6-6 to set render location, 5 to set fine X scroll)2. Status bar is at the top, and you have a 4 scanline gap below it - for fine Y scroll of 0-3, you do a 6-6-5 write at the bottom of the gap, and for fine Y scroll of 4-7 you do a 6-6-5 write at the top of the gap.3. Status bar is at the top, and you have no gap - you do a 6-5-5-6 write at the split point

Most games used technique #1 (SMB3, Startropics) or #2 (Castlevania 3, Battletoads) - technique #3 wasn't really known until we discovered it.

Correct, but I'll also mention technique #2b, my favorite, which is the same but uses a 8 scanline gap. You simply do a 6-6-5 write within the gap depending on the fine scroll. Also for both technique 2 and 2b you need to disable background explicitly via $2001 (or via CHR-ROM switch to blank tiles) until the end of the gap.

In addition to that, you can also have one extra pixel of fine scrolling depending on whether the 6-6-5 write is done at the end of the scanline or at the start, so it's possible to have fine-scolling over 5 positions, so it's possible to have only a 3-scanline gap.

You simply do a 6-6-5 write within the gap depending on the fine scroll. Also for both technique 2 and 2b you need to disable background explicitly via $2001 (or via CHR-ROM switch to blank tiles) until the end of the gap.

Why would you choose to have a mandatory 8 scanline gap, and the added complications of varying the timing and masking the background, while you could just use the 6-5-5-6 sequence instead and have pixel-perfect precision with none of that extra complication?

Why would you choose to have a mandatory 8 scanline gap, and the added complications of varying the timing and masking the background

Well for most status bars to look good you neede a gap anyway and because the NES is a tiled system a 8-scanline (that is a 1 tile row) gap comes naturally. What you refer to as extra complexity is actually very simple, something like 4 instructions in assembly.

The extra complexity is in timing the actual scroll change, which can happen in any one of 8 scanlines, while with the 6-5-5-6 method you can just split at a constant point, because you have full control over the fine vertical scroll. The 6-6-5 method requires a blank area (which is optional with the other method) more PPU writes, more timed code, and offers no advantage at all.

Who is online

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