Seamless All-direction Scrolling
Moderator: Moderators
Re: Seamless All-direction Scrolling
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.
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
Re: Seamless All-direction Scrolling
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 !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.
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.
Booo cheating !Edit, I'm using 4 screen mode, btw.
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.
Re: Seamless All-direction Scrolling
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.
Re: Seamless All-direction Scrolling
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.dougeff wrote:(99% because I see some missing tiles in the corners if you're going diagonally).
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.No attribute tables yet.
Oh, so you may not need to do any serious attribute juggling after all.Edit, I'm using 4 screen mode, btw.
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.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.
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.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.
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.hardware wise it makes a lot of sense to solve the problem this way
Re: Seamless All-direction Scrolling
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 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.
Re: Seamless All-direction Scrolling
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.
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.
Re: Seamless All-direction Scrolling
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.
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.
Re: Seamless All-direction Scrolling
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?
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?
Re: Seamless All-direction Scrolling
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.
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.
Re: Seamless All-direction Scrolling
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.
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.
Re: Seamless All-direction Scrolling
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.
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.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.
Re: Seamless All-direction Scrolling
Yeah, sprite overflow is buggy, but 9 high priority sprites before anything else does guarantee that the flag is set consistently.
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?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.
Re: Seamless All-direction Scrolling
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.
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
Re: Seamless All-direction Scrolling
dougeff wrote:130 scanlines of filling buffers, and there's no music.
Those could be serious problems for a fast-paced game, but might be OK for something slower, like an RPG.and right up against the end of v-blank every frame, like 10-20 instructions before the pre-render scanline.
Re: Seamless All-direction Scrolling
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?
The scroll advantage 4 nametables is very interesting, but I think before reaching this easier to explain first serious lesson right?