Seamless All-direction Scrolling

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
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: Seamless All-direction Scrolling

Post by dougeff »

Ok, I got a 99% funcional all-direction (top down) engine working. (99% because I see some missing tiles in the corners if you're going diagonally).

No attribute tables yet. No collisions with BG yet. Had to rewrite how neslib handles scrolling, and rewrite the nmi routine.

I'm going to have to drop this project and get back to it...I have so many things to work on right now.

Edit, I'm using 4 screen mode, btw.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Seamless All-direction Scrolling

Post by Bregalad »

tokumaru wrote: It doesn't require a constant-timed NMI routine. If you can guarantee a sprite 0 hit or a sprite overflow (which is what I use to mask sprites at the top of the screen as opposed to keeping rendering completely off and getting the alternate dot crawl pattern) every frame, you can wait for one of these flags to be cleared in order to detect the end of vblank after you're done with your non-contant-timed NMI handler. Then you wait 16 scanlines with timed code (you can do some contant-timed tasks here if you want), and finally turn background rendering on.
You are indeed right that a constant-timed NMI routine is not needed. For some reason I tought sprite zero hit was mainly for synchronizing at the HIT point, but I forgot that it also allows to synchronize at the end of VBlank, even if the hit point is not even used at all !

Techniques for blanking the first 8 or 16 lines (needed if you do not want any sprite pop-up !) can range from disabling BG by $2001 and having 8 high priority sprites there, to disable rendering completely, or leave everything enabled but use blank CHR-ROM pages for everything.

Also I forgot to mention that IF you're using 8x8 sprites, you could also use horizontal mirroring, and hide the left and right 8 pxiels (requires 30 sprites !!) and hide only the top 8 lines. Since it requires so many sprites, it's not the greatest idea, but it's an alternate way to get completely glitch-free scrolling without sprite poping nor attribute clases. I still belive vertical mirroring to be more convenient.
Edit, I'm using 4 screen mode, btw.
Booo cheating !
Just kidding, actually hardware wise it makes a lot of sense to solve the problem this way, but it isn't the 80's way of solving the problem.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Seamless All-direction Scrolling

Post by Pokun »

I don't understand how you can mask the topmost 8 or 16 scanlines of BG characters using just 8 high priority sprites? Sprites are just 8 dot wide and BG characters are not affected by the sprite overflow.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Seamless All-direction Scrolling

Post by tokumaru »

dougeff wrote:(99% because I see some missing tiles in the corners if you're going diagonally).
This usually happens because of rows overwriting columns and/or vice versa. When you move diagonally, the column and the row that need to be updated overlap at the corner of the screen, so if you do things in the wrong order, you may corrupt that corner.
No attribute tables yet.
I guess you were a bit too optimistic with that 99% figure then... attributes are easily the worst part of an 8-way scroller, specially if the map is built with 256x256-pixel blocks instead of 256x240 ones. I think you mentioned using 256x240, so your case is not so bad, but you still have to split and combine attribute bytes vertically when updating rows, which's kind of annoying.
Edit, I'm using 4 screen mode, btw.
Oh, so you may not need to do any serious attribute juggling after all.
Bregalad wrote:Techniques for blanking the first 8 or 16 lines (needed if you do not want any sprite pop-up !) can range from disabling BG by $2001 and having 8 high priority sprites there, to disable rendering completely, or leave everything enabled but use blank CHR-ROM pages for everything.
Yeah, that's right. Jurassic Park uses the blank (actually black) patterns approach. This is better because it doesn't waste any sprites, but the other method is not so bad IMO.
Also I forgot to mention that IF you're using 8x8 sprites, you could also use horizontal mirroring, and hide the left and right 8 pxiels (requires 30 sprites !!) and hide only the top 8 lines. Since it requires so many sprites, it's not the greatest idea, but it's an alternate way to get completely glitch-free scrolling without sprite poping nor attribute clases. I still belive vertical mirroring to be more convenient.
Felix the Cat and Alfred Chicken use sprites to hide the rightmost column of the background, but I'm pretty sure they use 8x16 sprites. That's still pretty wasteful though, because not only you have to waste 15 sprites (compared to only 9 with the other approach), but you also effectively reduce the number of sprites per scanline to 7, as if 8 wasn't already bad enough.
hardware wise it makes a lot of sense to solve the problem this way
That was my conclusion. No need to be masochistic about something just so you can be 100% authentic to some specific time period, if you can just go with a very simple solution that has no real drawbacks.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Seamless All-direction Scrolling

Post by tokumaru »

Pokun wrote:I don't understand how you can mask the topmost 8 or 16 scanlines of BG characters using just 8 high priority sprites? Sprites are just 8 dot wide and BG characters are not affected by the sprite overflow.
The high priority sprites are for hiding sprites only (and you need 9 if you want to trigger the overflow flag)... the background is disabled normally using $2001, which's why you need timed code to enable the it back at the correct time.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Seamless All-direction Scrolling

Post by Pokun »

Oh now I see. I misunderstood Bergalad's message, he said turn off BG AND hide sprites using sprite overflow.

OK so by only turning off the BG it doesn't count as forced blanking because sprites are still on, just that stray sprites that go up there are hidden by the overflow.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Seamless All-direction Scrolling

Post by tokumaru »

Exactly. There are two advantages in using a sprite overflow instead of disabling rendering completely:

1- By keeping rendering on, you avoid the alternate dot crawl pattern in NTSC, which can look weird;

2- You can use the sprite overflow flag to sync up with the start of the frame, eliminating the need for a constant-timed NMI handler, which is all but trivial to code.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Seamless All-direction Scrolling

Post by Pokun »

3- You finally get to use that buggy sprite overflow flag, although probably not what it was designed for!

BTW how exactly do you check for the flag? Do you poll $2002 in the beginning of your main loop right after a vblank or something?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Seamless All-direction Scrolling

Post by tokumaru »

If you want to detect the end of vblank, you have to poll $2002 in the vblank handler, after all PPU operations are done, waiting for the overflow flag to be *cleared*.

All raster effects timed from the start of the frame should be done in the NMI handler, because you want them to happen every frame, even if the game logic lags, otherwise the image will glitch every time the game slows down.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Seamless All-direction Scrolling

Post by Bregalad »

And, more importantly:

4 - You can scroll using $2005/$2000 normally and don't have to touch $2006.

On the other hand, an advantage of using real forced blanking for the first 16 lines would be to have extended time for VRAM updates.

Using sprite overflow flag might be elegant, but does it really work ? I mean all I heard about this flag is that it's buggy and it's usage should be avoided.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Seamless All-direction Scrolling

Post by Pokun »

Yeah I thought that as well, how can you rely on it if it's inconsistent? But according to the wiki: "games can intentionally place 9 or more sprites in a scanline to trigger the overflow flag consistently, as long as no previous scanlines have exactly 8 sprites." It sounds like its behaviour is consistent on the very first overflow. And if you use it on the first 8 scanlines there should be no risk for unexpected behaviour.

tokumaru wrote:If you want to detect the end of vblank, you have to poll $2002 in the vblank handler, after all PPU operations are done, waiting for the overflow flag to be *cleared*.

All raster effects timed from the start of the frame should be done in the NMI handler, because you want them to happen every frame, even if the game logic lags, otherwise the image will glitch every time the game slows down.
I see, one disadvantage of this is that you are potentially loosing some time for your logic to run in waiting for the flag I guess. But slowdown is better than graphical glitches.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Seamless All-direction Scrolling

Post by tokumaru »

Yeah, sprite overflow is buggy, but 9 high priority sprites before anything else does guarantee that the flag is set consistently.
Pokun wrote:I see, one disadvantage of this is that you are potentially loosing some time for your logic to run in waiting for the flag I guess. But slowdown is better than graphical glitches.
Yeah, you waste some time waiting for the end of vblank, and some more while timing the border itself, but you may at least run constant-timed tasks during the second wait... Maybe a constant-cycle music engine?
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: Seamless All-direction Scrolling

Post by dougeff »

Here's a video of my top-down, all direction game engine (like Crystalis). Will put on the blog soon. Got collisions and attribute tables working. Coding this was a huge pain in the ass (or back, since it's actually my back and eyes that hurt)...about a dozen bugs that I fixed, probably more that I missed.

https://youtu.be/gqVa3RHxMjE


All the 'under the hood' code is in asm, but the main code is in C (cc65). I am buffering nametable writes every frame, lots of them. 130 scanlines of filling buffers, and there's no music.

EDIT - and right up against the end of v-blank every frame, like 10-20 instructions before the pre-render scanline. So...basically, no PPU updates or palette changes of any kind, unless I shut off my own PPU updates for a frame.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Seamless All-direction Scrolling

Post by tokumaru »

dougeff wrote:130 scanlines of filling buffers, and there's no music.
and right up against the end of v-blank every frame, like 10-20 instructions before the pre-render scanline.
Those could be serious problems for a fast-paced game, but might be OK for something slower, like an RPG.
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: Seamless All-direction Scrolling

Post by Diskover »

This is great, but why not first make a single left-right scrolling, and another simple scroll up-down?

The scroll advantage 4 nametables is very interesting, but I think before reaching this easier to explain first serious lesson right?
Post Reply