It is currently Tue Nov 13, 2018 9:31 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: Sat Oct 27, 2018 4:59 am 
Offline

Joined: Mon Apr 04, 2016 3:19 am
Posts: 85
I've been busy creating my own multi-directional scrolling code. It's hard work, but I've finally gotten it to work! I'm using single-screen mirroring (I want to use the other nametables for cool effects), and naturally there are a few challenges.

Although there are great articles like this that gives all the technical information you might need on scrolling, I'm on the hunt for all kinds "tricks" that exists that can be used to make the multi-directional scrolling better. I've found some here and there while googling around, but I'm hoping there is a whole lot more that I don't know about. The main issue to tackle is obviously scrolling artifacts, but I'm also on the hunt for things that decrease time spent in VBlank since multi-directional scrolling eats up a lot of it.

I figure I might start by listing out every trick I know:

    1. The most obvious thing to do is use more nametables and not have any scrolling artifacts whatsoever, but I always felt this was a bit of a waste, like using a laser cannon to kill an ant. So many cool effects can be done if you have some unused nametables. But it's an option.

    2. A well-known trick is to use the $2001 register to hide sprites and background in the leftmost 8 pixels of the screen, to partially hide scrolling artifacts on the horizontal scroll. This is enough to completely eliminate horizontal nametable artifacts, but not attribute artifacts.

    3. You can simulate hiding the 8 rightmost pixels of the screen by having a column made out of sprites. Probably not worth it due to the sprite limit. Maybe in a low-sprite situation like a world map or cutscene? This would hide horizontal attribute artifacts entirely.

    4. By using an IRQ (or some other means) you can turn off rendering for the bottom 8 pixels on the screen. Not only does this hide vertical nametable artifacts (and partially hide vertical attribute artifacts) but you can even start your VBlank updates early as long as you are careful about the "rainbow stripe" effect of messing with your palettes in that space.

    5. Instead of wastefully updating tiles on the edge of the screen every frame, you can store which row/column you updated last frame and not update again until the scroll has moved over to a new row/column.

    6. Instead of updating tiles on the exact 8px offset, you can offset your calculations to update tiles when they are scrolled halfway though. This makes scrolling artifacts less visible by dividing it equally between both sides of the screen.

    7. Instead of updating both the nametable and attribute table in one go, you can update them separately. You can then do nametable updates perfectly in the 8px "hidden" zone, while attribute updates can be done separately at a different scrolling offset to minimize visual color glitches. As a bonus you spread the VBlank work out over more frames which is a boon.

    8. A more practical rather than technical trick is to avoid mixing attributes too much in your level design. If your clouds use the same attributes as your sky background, then you'll avoid constant attribute glitches in the sky as the player is moving, as the game has no need to switch back and forth between the two attributes as the clouds swosh past.

    9. Few games are diehard about keeping the player in the dead center of the screen. By allowing a little "bias" you can avoid nasty situations where standing on a particular platform shows you constant attribute glitches on the vertical axis, because the game's engine simply scrolls a few pixels extra up or down before stopping, to align itself better.


I think that's all the ones I know. Are there any more, or maybe some ways to enhance these tricks I've mentioned to make them better?


Edit: Oh wait I totally forgot the obvious Statusbar coverup. It's essentially the same as point 4 on my list, but with a thicker statusbar you can cover up even the attribute glitches perfectly.


Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 7:34 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4104
Then there's an out-of-left-field option: Use a mapper which allows Checkerboard mirroring. Then scrolling glitches become mostly confined to corners.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 11:11 am 
Online
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10959
Location: Rio de Janeiro - Brazil
Drakim wrote:
3. You can simulate hiding the 8 rightmost pixels of the screen by having a column made out of sprites. Probably not worth it due to the sprite limit. Maybe in a low-sprite situation like a world map or cutscene? This would hide horizontal attribute artifacts entirely.

Felix the Cat uses this "trick", and it's pretty sprite-heavy considering it has a large protagonist, overlaid weapons/attacks, vehicles, and so on. I guess that if you use a good sprite flickering technique, losing 1 sprite per scanline isn't so bad.

If you don't plan to do anything to hide scrolling attributes though, you can at least have the camera "snap" to attribute boundaries so that things don't look glitchy when the player is not moving.


Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 12:52 pm 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7566
Location: Chexbres, VD, Switzerland
I think you pretty much summed it all. I particularly like the split of glitches between two oposite edges, so that each glitch is half as visible.

A very advanced trick, if your background and sprite palettes hapens to be identical, and that 8x16 spries are used, is to overlay the last background tile column with sprites representing the same objects. This will make colour artifacts normally invisible, but if you need 8 sprites per line (or more than 48 sprites per screen) for real gameplay, you can have them and the colour artifacts becomes visible instead of one sprite disapearing.


Last edited by Bregalad on Sun Oct 28, 2018 1:22 am, edited 2 times in total.

Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 1:47 pm 
Online
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10959
Location: Rio de Janeiro - Brazil
Making the sprite and background colors identical is a pretty big limitation, and together with the sprite coverage loss, the price is just too high. I'd much rather just pay the sprite price, and simply blank the right side.


Top
 Profile  
 
PostPosted: Sun Oct 28, 2018 12:36 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7566
Location: Chexbres, VD, Switzerland
tokumaru wrote:
Making the sprite and background colors identical is a pretty big limitation, and together with the sprite coverage loss, the price is just too high. I'd much rather just pay the sprite price, and simply blank the right side.

There's no sprite coverage loss - that's the whole point of this technique - the sprites are here only if there is room and they'd disappear first, making attribute clash visible only when there's too much sprites - rather than always. It makes sense only in cases where BG and sprites palettes were to be identical anyway, it does not make sense to make the palettes identical just for that.


Top
 Profile  
 
PostPosted: Sun Oct 28, 2018 12:44 am 
Online
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10959
Location: Rio de Janeiro - Brazil
Oh, I see. I think few people would be crazy enough to make sprite and background palettes equal though, unless they were doing something very simplistic.


Top
 Profile  
 
PostPosted: Sun Oct 28, 2018 1:11 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7566
Location: Chexbres, VD, Switzerland
tokumaru wrote:
Oh, I see. I think few people would be crazy enough to make sprite and background palettes equal though, unless they were doing something very simplistic.

I don't think it's that simple. Depending on what you want to do this makes things logical, for Fire Emblem for instance the sprites and BG palettes are the same. Also, it doesn't have to be ALL palettes being the same, using the trick to overlay only the tiles with palettes who are possible to overlay with sprites is also forceeable, although it's more complex to code and less efficient.


Top
 Profile  
 
PostPosted: Mon Oct 29, 2018 10:30 pm 
Offline

Joined: Wed Apr 04, 2018 7:29 pm
Posts: 38
Location: Montreal, Canada
That's a nice list, but which technique did you end up going with? I'm curious.

In the game I'm working on i used vertical mirroring and managed to limit all artefacts in the top/bottom 8px of the screen, where i hope they will be (mostly) hidden by overscan.

My algorithm is mostly stateless, it only keep tracks of the XY index of the current tile (a tile being 8x8), at the top left of the screen. Whenever the scroll position (which is also relative to the top-left) divided 8 doesnt match that cached XY (in X or Y), it means that its time to update "something". Sometimes only tiles are updated, something attributes, sometimes both. That also means I cant scroll faster than 8px per frame, which is perfectly fine for my game.

But you are right in saying its hard work. The number of edge you need to handle is quite surprising, especially in the Y axis where being on a odd/even nametable will offset things. And that last half-row of attributes is also annoying.

Good luck and looking forward to seeing what you do.

-Mat


Top
 Profile  
 
PostPosted: Mon Oct 29, 2018 11:01 pm 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 415
Quote:
The most obvious thing to do is use more nametables

I didn't realize this at first, but 4 nametable scrolling is actually the hardest to implement and has the clumsiest math. It's easier with 1 nametable mirrored in both directions.

Just something to keep in mind for anyone new to scrolling.


Top
 Profile  
 
PostPosted: Tue Oct 30, 2018 5:04 am 
Offline

Joined: Mon Apr 04, 2016 3:19 am
Posts: 85
bleubleu wrote:
That's a nice list, but which technique did you end up going with? I'm curious.

One nametable mirrored in both directions, left column hidden with PPUMASK ($2001), bottom row hidden with IRQ interrupt, limit nametable updates to once per column/row updated exactly underneath the hidden column/row, attribute bytes updated with a different timing to split the miscoloring between both sides of the screen.

Plus some macros to unroll the loops as they do the work, as there is a lot of repetition.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: Google Adsense [Bot], tepples and 7 guests


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

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group