Simple vertical scrolling with status bar

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Simple vertical scrolling with status bar

Post by tokumaru »

There are no glitches when changing only the NT because $2000 writes only affect the temporary VRAM address register. Then, only at the start of hblank does the PPU copy the horizontal scroll bits to the actual address register. You don't have direct control over the active scroll through $2000 alone, so any changes you make are effectively delayed until hblank.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Simple vertical scrolling with status bar

Post by tepples »

DRW wrote:Is this maybe a specific behavior of the NES, that scrolling can be changed anytime mid-frame and you have to take care of the timing yourself, while a name table switch automatically only takes place during the next hblank?
Correct. Changing bit 0 of $2000 (horizontal nametable select) is considered a coarse horizontal scroll and takes effect on the next scanline. Changing bit 1 of the same port is considered a vertical scroll and takes effect on the next frame. But for fine horizontal scrolling, you do need to take care of the timing yourself. The same is true of forced scrolling (the $2006-$2005-$2005-$2006).
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Simple vertical scrolling with status bar

Post by DRW »

Interesting.

Is there a specific reason why this wasn't done for scrolling as well?

I mean, I cannot really imagine a situation where you do a mid-frame horizontal scrolling change and don't intend it to take place during hblank, but where you actually want the change to happen in the middle of the line.

In my previous game, where I created parallax scrolling with a sprite 0 split, I was able to circumvent the whole problem by creating the fog in a way, so that there's one continuous line of a single color above the highest possible platform:
Screenshot.PNG
Screenshot.PNG (4.38 KiB) Viewed 1519 times
This way I could place the sprite 0 at the left side and didn't need to bother about timing.

But for a status bar with vertical scrolling in the new game, this would have posed a problem.
Either, I would have had to experiment with the timer to try to implement a counter that goes exactly to the end of the line, by the pixel. (A feat that not even professional games like "The Legend of Zelda" or "Journey to Silius" managed.)
Or I would have covered the rest of the line with black sprites.

Fortunately, since for dialog boxes only the name table is changed (since no scrolling is done when a dialog box is open) while the always on-screen status bar will be just a bunch of sprites, this is one less problem that I have to think about.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Simple vertical scrolling with status bar

Post by tepples »

DRW wrote:Is there a specific reason why this wasn't done for scrolling as well?
This sort of buffering was done for scrolling, but only coarse scrolling, not fine scrolling, and not forced scrolling.

As for why fine scroll ($2005 first write bits 2-0) wasn't buffered, here's my speculation: Extra registers for that would have cost money in three ways: engineering time to design and test, the die size to hold them, and risk of loss of first mover advantage while waiting for engineers to finish. Nintendo wanted to beat Sega to market, and price was consoles' primary advantages over home computers of the time. The workaround using blank lines between the status bar and the playfield was deemed an acceptable engineering compromise.

As for why forced scrolling ($2006-$2005-$2005-$2006) wasn't buffered, the correct write sequence for that wasn't even discovered during the NES's original commercial era (prior to 1997). I think it was discovered soon after loopy posted "The skinny on NES scrolling".
In my previous game, where I created parallax scrolling with a sprite 0 split, I was able to circumvent the whole problem by creating the fog in a way, so that there's one continuous line of a single color above the highest possible platform
In Super Mario Bros., Vs. Super Mario Bros., and Super Mario Bros. 2 (J), the scanline between the status bar and the playfield was left blank for a similar reason. This is why the numbers in Vs. SMB and SMB2 (J) aren't as tall as the letters.
experiment with the timer to try to implement a counter that goes exactly to the end of the line, by the pixel.
That's what you have to do if you want neither blank lines nor glitches. Use the forced scrolling sequence, and make sure that the last two writes come between x=256 (start of sprite fetch) and x=320 (start of next line's background fetch).
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Simple vertical scrolling with status bar

Post by tokumaru »

DRW wrote:Is there a specific reason why this wasn't done for scrolling as well?
But it was... with the exception of the fine X scroll, all scroll bits are buffered (i.e. they go to the temporary address register), but due to the way that rendering works, only the horizontal bits are restored (i.e. copied from t to v) every scanline. The clean NT switch isn't necessarily a deliberate design decision, but more like a side effect of the way rendering and scrolling work. The horizontal NT bit just happens to be one of the bits that's copied from t to v every scanline.
I mean, I cannot really imagine a situation where you do a mid-frame horizontal scrolling change and don't intend it to take place during hblank, but where you actually want the change to happen in the middle of the line.
Well, much like the Atari 2600 was originally designed for Pong and Combat, but ended up getting versions of Double Dragon and Ikari Warriors, which had to use the video hardware in unconventional ways to produce their visuals, Nintendo engineers certainly didn't put much thought into raster effects when designing the NES PPU. It barely has anything to help with timing effects (the sprite 0 hit is a joke) and almost everything you do to the PPU mid-screen screws up the picture.
I would have had to experiment with the timer to try to implement a counter that goes exactly to the end of the line, by the pixel. (A feat that not even professional games like "The Legend of Zelda" or "Journey to Silius" managed.)
It's impossible to align "by the pixel" on the NES. The exact point where the scroll change happens WILL vary over time, you just have to make sure that the variation is hidden between one scanline and the next (i.e. the first 21 or so cycles of hblank - that's equivalent to 64 pixels, which's plenty of space to hide glitches without the aid of sprites).
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Simple vertical scrolling with status bar

Post by DRW »

Bregalad wrote:
What are the best ways to do this?
I know some (especially Tokumary) will disagree, but my personal opinion is that the "best way" is, by far, to do like 98% of the NES games out there : To ignore this non-issue. It is just an accepted standard to have some minour glitches on the sides of the screen, ESPECIALLY at the top and bottom.

What you can however do is to minimize the issue. By updating a name table row when the fine scroll is exactly 4 or 12, and an attribute table when the fine scroll is 8, you have on each side :
  • At maximum 4 pixels of wrong tile displayed
  • At maximum 8 pixels of wrong color displayed
Which is much less noticeable than what most games does (most of them have 8 pixels of wrong color AND wrong tile displayed on top and bottom).
By the way, this is exactly what I did now.
The scrolling is completely finished and I came to the conclusion that having four pixels of incorrect tiles and eight pixels of incorrect colors during vertical scrolling is sufficient. Doing timed code to switch the rendering on and off is not really worth the hassle, especially since I always scroll four pixels per frame anyway (i.e. the scrolling goes for one second) and it's screen-by-screen.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Post Reply