Repeating pattern parallax scrolling with CHR RAM

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Repeating pattern parallax scrolling with CHR RAM
by on (#203393)
Sword Master and MetalStorm fake parallax scrolling by filling the background with a repeating pattern and then scrolling the pixels in the tiles that make up that pattern to cancel out a fraction of the background movement. But this technique usually requires a lot of CHR ROM, one bank for each horizontal position, and on MMC3, this can limit flexibility of what sprites can appear together.

So I decided to see if I could get pixel scrolling working with CHR RAM, using the Popslide engine for uploading the scrolled tiles to video memory. This doesn't scroll the background (yet), but it does scroll a 32x32 pixel pattern.

Because copying graphics to CHR RAM without self-modifying code takes 8 cycles per byte, there's not enough time to upload both 16 tiles to CHR RAM and a display list to OAM in an NTSC vblank. So I split them over two frames, which can cause tearing artifacts. To avoid this, you can either extend blanking or use a 32x16 pixel pattern, possibly using a brick wall tessellation. I don't know if 1bpp tiles would save appreciable vblank time, as there'd be more seeks when uploading the tiles.
Re: Repeating pattern parallax scrolling with CHR RAM
by on (#203395)
Can't run the demo as I'm on my phone, but I don't think CHR-RAM is the best solution for parallax scrolling. It takes so much time away from other more important types of video updates, not only OAM updates like you mentioned, but also NT/AT updates for scrolling and erasing destroyed stuff, pattern updates for character animations, and so on. And it's not like you can lower the priority of what's essentially an embellishment, because you can't double buffer the tiles and you can't delay updating them since that'd cause the background to shake. Parallax effects have to react to scrolling with zero delay, otherwise the effect breaks.

So yeah, I don't think a mere embellishment deserves such high priority in the update queue, causing more important things (scrolling and character animation, mostly) to lag. That's not to say that this technique is completely useless, it can definitely be used in menus, cutscenes, or other environments that are easier to control than a fast-paced action game. Even slower games that don't need so many updates every frame could probably squeeze this in if the VRAM bandwidth was planned carefully.

But as a general solution that could be used in any CHR-RAM project? Definitely no, specially considering that a lot of homebrew projects these days are scrolling platformers, and people have trouble making all updates fit in vblank time as it is.

Edit: IMO, there are certain things that unfortunately will remain in the realm of more complex mappers (MMC3 and up), such as parallax scrolling and various types of raster effects that require the CPU to know which scanline is being rendered. Of course that a limited number of these effects are possible without the aid of mappers, but it can be such an Herculean task to pull them off sometimes without having to make sacrifices elsewhere that you have to wonder if it wouldn't make more sense to drop these unneeded embellishments or simply use a mapper that makes them trivial to pull off rather than masochistically insist that you want to do everything while using as few resources as possible.
Re: Repeating pattern parallax scrolling with CHR RAM
by on (#203396)
tepples wrote:
But this technique usually requires a lot of CHR ROM, one bank for each horizontal position, and on MMC3, this can limit flexibility of what sprites can appear together.

That's where TQROM comes to the rescue...

Quote:
Can't run the demo as I'm on my phone, but I don't think CHR-RAM is the best solution for parallax scrolling

Battletoads does this with CHR-RAM but at the price of an extended VBlank using forced blanking for a dozen of scanlines at the top of the screen.

Quote:
Because copying graphics to CHR RAM without self-modifying code takes 8 cycles per byte, there's not enough time to upload both 16 tiles to CHR RAM and a display list to OAM in an NTSC vblank.

So why don't you do it with less tiles?
Re: Repeating pattern parallax scrolling with CHR RAM
by on (#203399)
I think if mapper complexity is not the greatest concern, maybe bank switchable CHR-RAM is quite good for parallax effects (among many other things)?

In this way, you don't need very large ROM for all the bankable patterns, as the tiles can be compressed and loaded before each level (you may even generate the patterns on the fly before each level, if you think the players can wait a little), and you don't need to continuously overwriting the tiles every x frames.

Considering that "large" RAM chips won't be much more expensive nowadays I think the only thing that matters is which mapper supports this (I think there were some discussion here before, like a dinosaur colouring game or something use bank switched CHR-RAM?). To simplify things, you may even do it the dirty way by bank switching the whole CHR area each time(with the tiles in all the RAM banks almost identical, save only for the parallax offset tiles), instead of having a mapper that can bank switch separate portions of the area.
Re: Repeating pattern parallax scrolling with CHR RAM
by on (#203400)
gilbert wrote:
maybe bank switchable CHR-RAM is quite good for parallax effects


I was thinking the same. This should solve the size problem while providing momentary/instant switching.

If you've got a defined height for the parallax strip, you could even keep all pixel shifted variants in bank "b". if you've got both pt and nt banking, you can keep them lined up in one or two nametables, and set a vertical coarse scroll the size of the strip height. To the user, it will look like horz scrolling, not vert scroll. This means you only need to update the bank once per scene/level/board, though you need to count scanlines to set mid screen bank splits, and you'd either need a seamless loop or load columns like the rest of the bg. The parallax bg can get very varied/detailed this way.
Re: Repeating pattern parallax scrolling with CHR RAM
by on (#203410)
tokumaru wrote:
not only OAM updates like you mentioned, but also NT/AT updates for scrolling and erasing destroyed stuff, pattern updates for character animations, and so on.

After uploading 128 bytes of pattern updates for parallax scrolling, I have room for one more row or column of nametable. But I acknowledge that I don't have room for character animations or replacing no-longer-visible background tiles with tiles for the coming area.

tokumaru wrote:
you can't double buffer the tiles

You can if you bankswitch CHR RAM $0C00-$0FFF, as Gilbert pointed out. But then uploading tiles for newly reached parts of the level becomes more complex because you have to upload them in both banks. And on MIMIC or MMC3 (not MMC5/VRC/FME/whatever), using the 1K banks for your backgrounds means you have to use 2K banks for your sprites, with all its drawbacks. And scrolling would still need to be slow (1 pixel or less per frame on average) so that double buffering can keep up.

Bregalad wrote:
That's where TQROM comes to the rescue...

Advantage: It should be possible to get 64K of CHR ROM and 32K of CHR RAM this way.
Disadvantage: I imagine TQROM is a bit more expensive to replicate than the board used for The Curse of Possum Hollow, which is a TGROM (MMC3 + CHR RAM) clone with CHR RAM expanded to 32K. Its engine emulates TQROM semantics on top of an oversize-TGROM board because one memory is cheaper than two. Look at other topics where people unironically recommend using otherwise unused CHR RAM as work RAM.

Bregalad wrote:
tepples wrote:
To avoid this, you can either extend blanking or use a 32x16 pixel pattern, possibly using a brick wall tessellation.

So why don't you do it with less tiles?

In some cases, you can indeed get away with eight tiles, as I hinted with "32x16". But that's not big enough for the blue mountain background in the first level of Sword Master, which appears to be 32x32 and which inspired this whole effort.

Gilbert wrote:
I think if mapper complexity is not the greatest concern, maybe bank switchable CHR-RAM is quite good for parallax effects (among many other things)?

It'd practically need to be a 128K CHR RAM. A 32K CHR RAM has only 32 1K banks, which would require every 1K bank to contain a frame of the animation. This would severely cut down on the RAM available to other background and sprite elements.

Gilbert wrote:
In this way, you don't need very large ROM for all the bankable patterns, as the tiles can be compressed and loaded before each level (you may even generate the patterns on the fly before each level, if you think the players can wait a little)

And this is an example of such generation. It might not even be a perceptible wait, as the game could generate a couple patterns on a blank screen, start the action, and freeze the camera for a second while generating the rest of the patterns in the background.

Gilbert wrote:
Considering that "large" RAM chips won't be much more expensive nowadays I think the only thing that matters is which mapper supports this (I think there were some discussion here before, like a dinosaur colouring game or something use bank switched CHR-RAM?).

It was Videomation, by the same developer (FarSight) who later went on to make Color a Dinosaur and the official, much-improved sequel to Action 52 for the Mega Drive.

But even though large RAM has become cheaper, it still isn't free. Another constraint we ran into for Curse was available logic elements in the CPLD we were using to clone the MMC3. To save 7 macrocells, we had to route PA12 directly to CHR A14 the way mapper 88 routes it CHR A16. This hardcoded the background (PPU $0000-$0FFF) to use banks 0-15 and the sprites (PPU $1000-$1FFF) to use banks 16-31, but it freed up one macrocell from bit 4 of each of six CHR windows and one more from the multiplexed A14 output.
Re: Repeating pattern parallax scrolling with CHR RAM
by on (#203453)
It's a cool technique, but though ROM is expensive, its cost per cartridge had dropped from 1983-now. Scarcity of CPU time on the Fami/NES, however, has remained constant (and higher). Don't bang your head against the wall doing this -- unless you enjoy the sensation, that is.
Re: Repeating pattern parallax scrolling with CHR RAM
by on (#203458)
Cost of ROM is going back up, I've read.

In this Tweet, infiniteneslives wrote:
NOR flash prices have officially doubled... OUCH

At high enough density, MCU-SRAM-SD was already cheaper. I suppose that threshold has dropped now. IDK when NOR prices will drop back down..