This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Eliminating worst-case diagonal updates in an 8-way scroller

Eliminating worst-case diagonal updates in an 8-way scroller
by on (#113313)
I've been very embroiled in trying to cut out the fat in my 8-way scrolling engine for The Legends of Owlia, and I made at least one really interesting discovery that is allowing my engine to perform no worse than a 2-way scrolling engine. I searched for prior discussion about this but could not find it.

The scroller in its current form is capable of uploading both a row and a column (both nametable and attribute table) to the PPU in a single frame. This accounts for the possibility that the camera may follow the hero along a perfect diagonal where both a row and a column are aligned with the edges of the screen every 8 pixels moved diagonally. (and 16 for attributes).

However, if the camera happens to follow the hero along any of the other possible diagonal lines, the row and column updates will alternate, halving the amount of CPU time needed to decode the next frame, and also freeing up a lot of time in an otherwise very tightly packed vblank.

What I discovered is, if you detect that you're starting to move along one of these "forbidden diagonals," you need only to correct it on the very first frame (by maybe a pixel or two), and then you can continue scrolling diagonally. I find that this "bump" is unnoticeable because it is so minor. That's a small price to pay for eliminating worst case performance!

I'll be happy to upload a before and after video, if anyone is interested, with the monochrome bit trick showing cpu time used by the scrolling portion of my engine. I'm guessing I'm not the first to exploit this "trick" if you can call it that, but I thought I'd share anyway...8 way scrolling used to seem so intimidating, but now I find it doesn't need to be any worse performance wise than 2 way scrolling! I was quite shocked when I realized this.
Re: Eliminating worst-case diagonal updates in an 8-way scro
by on (#113315)
tl;dr: "If the sliding window moves both horizontally and vertically in one frame, move one way at a time."

This will work fine if your character can't move more than 4 pixels per frame, allowing the scroll update to alternate rows and columns of tiles. In that case, it can be guaranteed that bumps are minor. But in before tokumaru points out that this won't work if you're already planning to scroll 16 pixels per frame diagonally, like in the first part of Chemical Plant Zone act 2 in Sonic the Hedgehog 2 for Sega Genesis.
Re: Eliminating worst-case diagonal updates in an 8-way scro
by on (#113316)
I guess it depends on how much you scroll each time... If you only scroll 1 or 2 pixels per frame, then yes, you can make small adjustments to the camera to avoid the case when both a row and a column need to be updated, but you scroll more than that, the chances of having to perform both updates increases, and the adjustments start to become noticeable.

In my engine I have 2 slots for updates of all kinds (column of blocks, row of blocks, palette, block of patterns, sparse blocks), and when a column and a row have to be updated at the same time, so be it. This shouldn't happen so often though, because I can't think of many cases when the main character would be moving in a perfect diagonal at maximum speed for long periods of time, so there will surely be an occasional slot free for other tasks. Also, at such high speed, the player would hardly notice the other things that are not being updated as fast! If he did notice something, as soon as he stopped to look the updates would catch up and he'd hardly notice anything then!

EDIT: Ninja'd by tepples! Man, you know me too well... XD I tried to avoid numbers, but yeah, I was thinking of speeds as high as 16 pixels per frame when I wrote my post.
Re: Eliminating worst-case diagonal updates in an 8-way scro
by on (#113322)
Hmm, if I ever needed high speed, I might as well pause (or throttle) all entities in this case, no player is going to be able to react at that speed to lots of active enemies anyway. Thankfully for this game I don't think I'll need it. I suppose I got lucky! That's kind of interesting to think about though. It seems that sleight-of-hand is quite useful in nes development. *edit* sorry, I think I just said the same thing as tokumaru in different words. I'm tired :)
Re: Eliminating worst-case diagonal updates in an 8-way scro
by on (#113326)
This is the scene I was referring to, starting here at TIME 0:05 or here at TIME 0:09.