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
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Simple vertical scrolling with status bar

Post by DRW »

My graphics artist likes the idea of using a small sprite-based status bar like in "Mega Man" or "Grand Master". Which is of course much easier to program because in this case, the status bar is a non-issue when it comes to scrolling.

But in this case, there's another problem:

If I cannot switch the mirroring, vertical scrolling will produce graphical artifacts because I write the new data on the currently visible screen. And in this case, there's not status bar to hide it.

I know that this might not be visible due to a TV's overscan, but I still prefer to hide these artifcats.

What are the best ways to do this?

"Legends of Owlia" has four way scrolling without any visible artifacts. The first two rows of the screen are always solid black. But I have no idea how he did this. When watching the whole PPU data in an emulator, there is no black bar anywhere. And it cannot be sprites either since it would be more than eight sprites.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Rahsennor
Posts: 479
Joined: Thu Aug 20, 2015 3:09 am

Re: Simple vertical scrolling with status bar

Post by Rahsennor »

One way to do that is to disable background rendering for a few scanlines. You can no longer time from sprite zero hit, but you can time from when the sprite zero hit flag is cleared at the end of NMI. I've never actually tried it though so I don't know how difficult it is.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Simple vertical scrolling with status bar

Post by DRW »

Sprite 0 is not necessary anymore if my status bar consists of sprites, so that's not a problem.

But wouldn't turning off the rendering result in this inexact graphical glitch again where the last line of the "non-rendering" jumps longer or shorter in every frame, like in one of my previous posts where I wasn't able to do the status bar split exactly in hblank?
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Simple vertical scrolling with status bar

Post by Bregalad »

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).

The results of a 16-pixel scroll pattern is as follows (rotated by 90° in order to have been easier for me to create) :

Code: Select all

Fine
VScroll
 0	-------------------------------------
 1	#------------------------------------
 2	##-----------------------------------
 3	###----------------------------------
 4	~~~~-----------------------------xxxx  (NT update)
 5	~~~~~-----------------------------xxx
 6	~~~~~~-----------------------------xx
 7	~~~~~~~-----------------------------x
 8	-----------------------------~~~~~~~~  (AT update)
 9	x-----------------------------~~~~~~~
10	xx-----------------------------~~~~~~
11	xxx-----------------------------~~~~~
12	---------------------------------####  (NT update)
13	----------------------------------###
14	-----------------------------------##
15	------------------------------------#
 0	-------------------------------------

- Correct tile displayed with correct colorus
~ Correct tile displayed with wrong colours
x Wrong tile displayed with correct colours
# Wrong tile displayed with wrong colours
If you opt for horizontal mirroring it's even better with the hardware feature to hide the left 8 pixels, you can have only 3 pixels of wrong colour on one side and 4 on the other, which is hardly noticeable at all.

Diagram for a 16-pixel scroll pattern (this time in the correct direction):

Code: Select all

Fine
HScroll
 0   --------|------------------------
 1   #-------|------------------------
 2   ##------|------------------------
 3   ###-----|------------------------
 4   ####----|------------------------
 5   #####---|------------------------
 6   ######--|------------------------
 7   #######-|------------------------
 8   ~~~~~~~~|------------------------  (NT update)
 9   #~~~~~~~|~-----------------------
10   ##~~~~~~|~~----------------------
11   ###~~~~~|~~~---------------------
12   xxxx----|--------------------~~~~  (AT update)
13   xxxxx---|---------------------~~~
14   xxxxxx--|----------------------~~
15   xxxxxxx-|-----------------------~
 0   --------|------------------------  (NT update)
     ^^^^^^^^
   Hidden part (by hardware through $2001)

- Correct tile displayed with correct colorus
~ Correct tile displayed with wrong colours
x Wrong tile displayed with correct colours
# Wrong tile displayed with wrong colours
Last edited by Bregalad on Fri Jan 13, 2017 7:00 am, edited 1 time in total.
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:I did the CNROM chapter from the Nerdy Nights tutorial, but this one was nothing more than switching between two sets of graphics data.
Well, all that CNROM can do is switch between 8KB CHR sets, so...
Is there a similar explanation that teaches you how to do UNROM? I mean, I know how to do NES programming in general.
UNROM is very simple because it only has one register, which selects a 16KB PRG-ROM page at $8000-$BFFF, while $C000-$FFFF is hardwired to the last bank in the ROM. Having a hardwired bank is very convenient, it serves as a safe place to put the stuff that must be available at all times, such as the CPU vectors, and the interrupt handlers, as well as the code that manages the switchable slot. Stuff like music code and data, graphics, maps, etc. would be switched into $8000-$BFFF as necessary. Even parts of the engine can go into switchable banks if the hardwired bank isn't enough, but this is something you're gonna have to design carefully. No document/tutorial will teach you how to organize your code and data across different PRG-ROM banks.

Another significant difference compared to NROM is that UNROM uses CHR-RAM, so you have to upload any tiles you're gonna use to VRAM yourself (using $2006/$2007, exactly like you do when writing to the name tables), but you can easily simulate NROM-style CHR-ROM by only uploading 8KB chunks of CHR if that makes you more comfortable than if you had to manage smaller chunks more dynamically.
DRW wrote:If I cannot switch the mirroring, vertical scrolling will produce graphical artifacts because I write the new data on the currently visible screen. And in this case, there's not status bar to hide it.
Yes, that might be a problem. Not a big one if you're doing delayed scrolling like in Zelda or Mega Man. If you scroll 16-pixels per frame, you can do it without glitches. If you want smooth scrolling though, then yeah, there will be visible glitches at the top and/or bottom of the screen.
I know that this might not be visible due to a TV's overscan, but I still prefer to hide these artifcats.
Me too.
What are the best ways to do this?
There are several ways to implement glitch-free 8-way scrolling. Here are 2 techniques used by commercial games:

Jurassic Park: Uses IRQs to blank the background at the top and bottom 8 scanlines, effectively creating a 16-scanline area where to hide the scroll seam. You don't have IRQs with NROM or UNROM, but you can still mask scanlines at the top of the screen without much trouble.

Alfred Chicken: Uses horizontal mirroring, so that there are no vertical glitches, and hides horizontal glitches by masking the leftmost 8 pixels (the PPU can do this if you tell it to) and covering the rightmost 8 pixels using a column of sprites that spans the entire height of the screen. Yeah, it sucks to use that many sprites for this, and it sucks that your sprites-per-scanline limit is effectively reduced to 7, but it works. Felix the Cat is another example of a game that hides scrolling glitches that way, and it still manages to have pretty big sprites throughout the game.

For a long time, my preferred technique for implementing glitch-free 8-way scrolling consisted in putting 9 high priority 8x16 sprites at the very top of the screen, and starting the frame with background rendering disabled. The high priority sprites served 2 purposes: mask any other sprites that eventually went up there, and trigger the overflow flag so I could tell when the frame started, so I could start timing the 16 scanlines it'd take until it was time to turn background rendering on.

This technique worked pretty well, but many people found the 16 blank scanlines unappealing, and I was basically wasting 9 sprites and some CPU time that could otherwise be spent on the actual game. So I ultimately decided to use a 4-screen layout (no NT mirroring) and do away with all the complications. In emulation, all you have to do is set a flag in the iNES header and there you have it, 4 name tables available for glorious 8-way scrolling, without the need for any tricks. On actual hardware, it's also pretty simple if you're using CHR-RAM, and it's practically free since nowadays you can't really buy 8KB RAM chips anymore, so the memory that would normally be wasted can be used for name tables instead. If you want my honest advice, go with a 4-screen layout and forget about all the tricks.

4-screen is definitely overkill if you're only doing delayed Zelda-like scrolling, but it's the most versatile NT layout you can get since there are lots of off-screen areas where to hide all sorts of updates.
Bregalad wrote: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.
I do indeed find scrolling glitches terribly distracting. In all TVs I played NES games on, these glitches were very apparent and kept distracting me from the gameplay, no matter if they were horizontal or vertical.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Simple vertical scrolling with status bar

Post by Bregalad »

tokumaru wrote: Jurassic Park: Uses IRQs to blank the background at the top and bottom 8 scanlines, effectively creating a 16-scanline area where to hide the scroll seam.
You'll have to blank sprites as well abusing the 8-sprites per line trick (in order to avoid full forced blanking).
Alfred Chicken: Uses horizontal mirroring, so that there are no vertical glitches, and hides horizontal glitches by masking the leftmost 8 pixels (the PPU can do this if you tell it to) and covering the rightmost 8 pixels using a column of sprites that spans the entire height of the screen.
This does not solve the problem that sprites will "pop" after the 8 or 16 top scanlines.
For a long time, my preferred technique for implementing glitch-free 8-way scrolling consisted in putting 9 high priority 8x16 sprites at the very top of the screen, and starting the frame with background rendering disabled. The high priority sprites served 2 purposes: mask any other sprites that eventually went up there, and trigger the overflow flag so I could tell when the frame started, so I could start timing the 16 scanlines it'd take until it was time to turn background rendering on.
I agree it's elegant indeed ! The method even "automatically" adjust to sprite size of 8x8 or 8x16. It's a shame the sprite overflow flag is that unreliable :(
So I ultimately decided to use a 4-screen layout (no NT mirroring) and do away with all the complications. In emulation, all you have to do is set a flag in the iNES header and there you have it, 4 name tables available for glorious 8-way scrolling, without the need for any tricks. On actual hardware, it's also pretty simple if you're using CHR-RAM, and it's practically free since nowadays you can't really buy 8KB RAM chips anymore, so the memory that would normally be wasted can be used for name tables instead. If you want my honest advice, go with a 4-screen layout and forget about all the tricks.
Still does not solve the sprite popping at the top problem.

The only way to have FULLY clean scrolling with NEITHER attribute glitches NOR sprite popping (nor a status bar) is to hide the left 8 scanlines with $2001 *and* the top 7/15 scanlines (using whathever technique you like). You also require vertical mirroring.
Yeah, it sucks to use that many sprites for this, and it sucks that your sprites-per-scanline limit is effectively reduced to 7, but it works.
Depending on your graphical style if your sprite palette happens to match your background palette for whathever reason, you could even hide attribute clashes with sprites which re-use background tiles, but with the correct palette. With *low* priority sprites. That way attribute clashes won't appear, exept if you already have 8 sprites per line.
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 »

Bregalad wrote:You'll have to blank sprites as well abusing the 8-sprites per line trick (in order to avoid full forced blanking).
Jurassic Park just uses blank patterns for everything, it doesn't even use the PPU registers. If you don't have CHR switching, then yeah, you have to do the masking some other way.
This does not solve the problem that sprites will "pop" after the 8 or 16 top scanlines.
Indeed it doesn't. I personally don't consider sprite "popping" as bad as background glitches, but I can't speak for everyone.
I agree it's elegant indeed ! The method even "automatically" adjust to sprite size of 8x8 or 8x16. It's a shame the sprite overflow flag is that unreliable :(
Actually, it's perfectly reliable if you use 9 high priority sprites (lower OAM indices) without any sprites above them. According to the wiki:
Nesdev Wiki wrote:During sprite evaluation, if eight in-range sprites have been found so far, the sprite evaluation logic continues to scan the primary OAM looking for one more in-range sprite to determine whether to set the sprite overflow flag. The first such check correctly checks the y coordinate of the next OAM entry, but after that the logic breaks and starts scanning OAM "diagonally"
Since these 9 sprites use the first OAM entries, the 9th is correctly evaluated and guaranteed to set the overflow flag, and as long as there are no sprites above (lower Y coordinate) those 9, there'll be no accidental overflows or false positives in the previous scanlines.
Still does not solve the sprite popping at the top problem.
Nope. At this point, I don't care. Actually, I do care a little bit. If I ever finish a game like this, I have plans to code a dedicated emulator for it, and this emulator will allow negative Y coordinates for sprites. For this reason, my meta-sprite system correctly generates negative Y coordinates for the individual OAM entries, even though on the NES itself those sprites just end up not showing.

Unfortunately, the same thing can't be done to avoid popping on the left side of the screen, since the screen is 256 pixels wide, but I'm seriously considering stealing one of the unused attribute bits to extend the X coordinate to 9 bits so that it can be negative too in this dedicated emulator.
Depending on your graphical style if your sprite palette happens to match your background palette for whathever reason, you could even hide attribute clashes with sprites which re-use background tiles, but with the correct palette. With *low* priority sprites. That way attribute clashes won't appear, exept if you already have 8 sprites per line.
That's soooo much trouble... better use the 4-screen NT layout.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Simple vertical scrolling with status bar

Post by DRW »

O.k., thanks for the information so far. I'll have a look at all of this when I try it out in my test program and see which tricks I'll use.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Simple vertical scrolling with status bar

Post by tepples »

Info dumps in Concentration Room and Haunted: Halloween '85 scroll vertically with vertical mirroring. They minimize glitches by writing all space characters to the row of the nametable that straddles the top and bottom of the screen. This reduces visibility of background glitches to that of sprite popping, but it requires a bit more video memory bandwidth.
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 »

That's an interesting idea I don't see discussed very often, tepples. I guess I prefer background popping than wrong tiles, but an entire row of popping might end up being just as distracting.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Simple vertical scrolling with status bar

Post by Bregalad »

tokumaru wrote:That's an interesting idea I don't see discussed very often, tepples. I guess I prefer background popping than wrong tiles, but an entire row of popping might end up being just as distracting.
It's the second time you mention popping as better than lies with completely wrong graphics, and although both looks bad, I do not see why popping would be a lesser problem. Especially when an entiere 8 pixel row would turn from black to some other colour, it'd definitely be very noticeable and a bit distracting.
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 »

I think it's better in the sense that there are no "corrupted" graphics visible, the graphics are either there or not there.
Bregalad wrote:it'd definitely be very noticeable and a bit distracting.
I did say it might be just as distracting, didn't I?
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Simple vertical scrolling with status bar

Post by DRW »

I've got a question that is related to the issue that I mentioned some posts ago, the problem with the mid-frame scrolling split and that you can never really time it exactly to the pixel:
Screenshot.png
Screenshot.png (3.96 KiB) Viewed 3021 times
Since we do a sprite-based status bar now, this very situation is not an issue anymore. But I did something similar:

When a dialog box pops up, it is first rendered in the invisible screen. (Since the game only scrolls screen-by-screen, you always have one full unused screen during the regular gameplay.)

During the main game loop, right after NMI, if the flag for "show dialog box" is set, I first switch the name table.
Then I wait for a sprite 0 split. (Sprite 0 is located in the last line of the dialog box.)
And then I switch the name table back.

In this case, the upper part of the screen shows the dialog box from the off-screen while the lower part shows the remaining playfield from the primary screen.


Now the curious thing: Despite the fact that the sprite 0 is located at the leftmost position of the screen, the dialog box always gets shown completely. You never have an incomplete pixel line due to switching the name table mid-frame.

Why is that the case? Why does setting the scrolling position with sprite 0 make the last pixel line wobble because the timing is always slightly different, but switching the name table mid-frame still renders the full line and produces no artifacts?
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
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 »

I didn't quite understand the difference between when you get the glitch and when you don't, but if you take the time to debug the timing properly, instead of guessing or just observing the glitches, you can get a clean split every time regardless of where the sprite 0 hit happens. There's plenty of time to change the scroll during hblank, but you have to make sure your timing is consistent across frames so the split point varies as little as possible from frame to frame. There's no magic, just time things properly and you'll be fine.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Simple vertical scrolling with status bar

Post by DRW »

tokumaru wrote:I didn't quite understand the difference between when you get the glitch and when you don't
The big difference is: In the glitchy case, I updated the scrolling position during mid-frame. In the non-glitchy case, I updated only the name table while scrolling is always at 0.
tokumaru wrote:but if you take the time to debug the timing properly, instead of guessing or just observing the glitches, you can get a clean split every time regardless of where the sprite 0 hit happens.
Yeah, but that's not what I'm wondering.
What I'm wondering is: How come the mid-frame name table split never produces glitches in the first place?

I didn't do any kind of timing. I put the sprite 0 at the left side of the last dialog box line and the whole line is still visible. Unlike with scrolling, where the line of the pre-sprite 0 rendering stops some pixels after the sprite 0 position and the post-sprite 0 rendering is done.

Here, let me show you:
Screenshot.PNG
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?
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Post Reply