Is it possible to set the fine bits of the vertical scroll mid-screen?

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

Post Reply
User avatar
Individualised
Posts: 310
Joined: Mon Sep 05, 2022 6:46 am

Is it possible to set the fine bits of the vertical scroll mid-screen?

Post by Individualised »

Asking because there seems to be conflicting information on this. I know that you have to use PPUADDR to change the vertical scroll mid-screen, and that at the very least it is more difficult to set the fine bits, hence why most games that scroll vertically and have a status bar put it at the bottom.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Is it possible to set the fine bits of the vertical scroll mid-screen?

Post by rainwarrior »

Yes, it is possible. The process is described on the wiki at: PPU scrolling: Split X/Y scroll
User avatar
Individualised
Posts: 310
Joined: Mon Sep 05, 2022 6:46 am

Re: Is it possible to set the fine bits of the vertical scroll mid-screen?

Post by Individualised »

Thanks. So there is no real reason I couldn't, in a game that scrolls in all directions, e.g. have a status bar at the top of the screen or even one in the middle of the screen for something like a 2-player split screen game?
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Is it possible to set the fine bits of the vertical scroll mid-screen?

Post by rainwarrior »

Well, there are many reasons why games might avoid that.


Crystalis may be a good example to look at, if that's what you're aiming for. It's notable that it has a cartridge mapper with a scanline IRQ to assist with it.

The main problem with 2-axis scrolling and a status bar is that when you have to put the status bar somewhere on the same nametable, you can't vertically wrap anymore. Crystalis gets around this by doing an "artificial" vertical wrap with a scanline split mid-screen, but it has to be timed to the specific line, which moves with the scroll.


A simpler example might be Solar Jetman. It uses a 1-screen nametable configuration so that it can flip between the scrolling field (which wraps on 1 screen), and the status bar (which exists on the other 1 screen view).


Artifacts at the left and right side are still "hard" for both of these games, though. It's difficult to have clean horizontal edges if you're not using a horizontal nametable setup, but using a status bar tends to require a vertical or 1-screen setup like those two games. This is not a problem if your cart can provide 4-screen nametables, though.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Is it possible to set the fine bits of the vertical scroll mid-screen?

Post by tokumaru »

"The Jungle Book" uses another creative solution for it's status bar: it completely redraws it elsewhere in VRAM whenever the scrolling engine is about to overwrite it.

If you need a status bar and 2 independent free-scrolling playfields, I feel like 1-screen mirroring is the way to go. Each playfield would use a name table. The status bar would use a hidden part of one of the name tables, and be relocated whenever needed.

You'd still have attribute glitches at the horizontal edges of the flayfields (like SMB3 or Kirby), but if you really want to avoid those you can pull a "Felix the Cat"/"Alfred Chicken" and hide them with a column of solid sprites.

There are some MMC3 boards that can do 1-screen mirroring, so you can have that and a scanline counter.
User avatar
Individualised
Posts: 310
Joined: Mon Sep 05, 2022 6:46 am

Re: Is it possible to set the fine bits of the vertical scroll mid-screen?

Post by Individualised »

I'm aware of the issue with not being able to wrap vertically with a status bar; an example of a game that is severely limited by this is the bootleg Super Mario World port (which puts its status bar at the bottom rather than the top like the original), it heavily simplified or removed areas with a lot of vertical space. And speaking of bootleg games; I believe many of Super Game's titles, such as Aladdin and Boogerman contain a status bar with unlimited vertical and four-way scrolling, but I'm not quite sure what method they're using to achieve that. The exception seems to be Shinobi 3 which limited vertical movement like SMW. I'll have to check those games out in Mesen later.

I'm not too worried about attribute glitches or mappers; not that I'm anywhere near close being ready to create an NES game yet, never mind one that would use any of these features and tricks.

Thanks for the responses!
Drag
Posts: 1615
Joined: Mon Sep 27, 2004 2:57 pm
Contact:

Re: Is it possible to set the fine bits of the vertical scroll mid-screen?

Post by Drag »

For status bars plus unlimited four-way scrolling, a common way I've seen it done is, use horizontal mirroring, then write the status bar to the bottom of the nametable space (i.e., bottom of PPU$2800). Then, when you need to unroll new nametable data as you scroll, write that data both to PPU$2000 like usual, and also in the same place at PPU$2800, except where it'd overwrite the status bar.

This simulates having 1-screen mirroring, and when the scrolling is positioned such that the status bar in the nametable would start to scroll into view, the screen split you already do for the status bar ends up covering it up. Continue scrolling downward, and your Y scrolling coordinate wraps back around to 0 before the status bar tilemap scrolls into the playfield.

You could use this exact same method and put the status bar at the top of the screen too if you wanted. The screen split means the playfield is offset enough to prevent the status bar from scrolling into view from the bottom whenever you get near the scroll wrapping point.

I can think of two reasons the status bar is usually at the bottom:
1) It's marginally easier to split the screen to a static view, since it's just two writes to $2006. For a top status bar, you'd need to split the screen to a free-scrolling view, using the $2006/2005/2005/2006 trick, which is two more writes than before (but still not too bad, since it's only the last two writes that actually have a visible effect on the screen).
2) In the case of mistimed writes or missed IRQs, a flickering/shaking status bar is better than a flickering/shaking playfield. I wouldn't expect this to be hard to avoid though, unless you're using sprite 0 as the splitting point.
User avatar
Individualised
Posts: 310
Joined: Mon Sep 05, 2022 6:46 am

Re: Is it possible to set the fine bits of the vertical scroll mid-screen?

Post by Individualised »

Drag wrote: Mon Jan 02, 2023 11:27 am since it's only the last two writes that actually have a visible effect on the screen
It sounds like this would affect the image in some way, i.e. a flickering scanline where the split should be, no? Or did I misinterpret what you meant?
Drag
Posts: 1615
Joined: Mon Sep 27, 2004 2:57 pm
Contact:

Re: Is it possible to set the fine bits of the vertical scroll mid-screen?

Post by Drag »

Individualised wrote: Mon Jan 02, 2023 7:14 pm
Drag wrote: Mon Jan 02, 2023 11:27 am since it's only the last two writes that actually have a visible effect on the screen
It sounds like this would affect the image in some way, i.e. a flickering scanline where the split should be, no? Or did I misinterpret what you meant?
To clarify, when doing the $2006, $2005, $2005, $2006 trick to split the screen (which I'll refer to as writes A, B, C, and D):
Writes A and B will not cause any visual glitches on the current scanline, but write C does, and write D does, and therefore, you want to make sure writes C and D have good timing (ideally inside hblank).
Write C immediately updates the fine X scroll register (shifts the screen 0 to 7 pixels), which affects the rest of the scanline.
Write D immediately locks in your new scrolling values, which obviously affects the rest of the scanline.

Additionally, you need to make sure that write D always occurs inside hblank, and that the timing for the write does not jitter back and forth between being inside and outside of hblank (this is what causes vertical shaking, or a horizontally shaking/offset scanline).
Post Reply