Switching Nametables During Vblank
Moderator: Moderators
Switching Nametables During Vblank
Hi everyone, I'm Kyle and I'm new here!
I was wondering if anyone knows if it's possible to swap to a different nametable during Vblank or if loading another nametable takes more time than the Vblank allows. I want to rapidly switch nametables to do a full screen animation but I'm not sure if that's even a feasible idea without using a mapper.
I was wondering if anyone knows if it's possible to swap to a different nametable during Vblank or if loading another nametable takes more time than the Vblank allows. I want to rapidly switch nametables to do a full screen animation but I'm not sure if that's even a feasible idea without using a mapper.
NTSC vblank is roughly 2,2k CPU cycles (20*341/3), and assuming that the uploading to PPU memory is done using 4 cycle LDA and STA instructions you'd have time to upload ~284 bytes per frame, so not enough to update all of the nametable (960 bytes, not counting the attributes).
So if you want 60 FPS you'll need to extend the vblank to upload more bytes (you need ~68 scanlines total so 48 scanlines of forced vblank in addition to normal 20 vblank scanlines). Or you can drop the framerate. You have two nametables available so you can use double buffering.
I'd probably go with 30 FPS... you'd need ~34 scanlines worth of CPU time to update full screen.
And for something like this mapper doesn't really offer anything too helpful.
So if you want 60 FPS you'll need to extend the vblank to upload more bytes (you need ~68 scanlines total so 48 scanlines of forced vblank in addition to normal 20 vblank scanlines). Or you can drop the framerate. You have two nametables available so you can use double buffering.
I'd probably go with 30 FPS... you'd need ~34 scanlines worth of CPU time to update full screen.
And for something like this mapper doesn't really offer anything too helpful.
Thanks for the speedy reply guys!
So the best way to do this would be to use either horizontal or vertical mirroring and load the next nametable while the other one is being displayed then switch them out...
Looks like I've got a lot to learn.
Also, how does one go about changing the framerate?
It might be easier for the project I'm working on to just change the frame rate rather than buffering the next screen. All I need to display is a looping 7 frame animation where each frame is saved as one nametable and each frame has the same palette.
So the best way to do this would be to use either horizontal or vertical mirroring and load the next nametable while the other one is being displayed then switch them out...
Looks like I've got a lot to learn.
Also, how does one go about changing the framerate?
It might be easier for the project I'm working on to just change the frame rate rather than buffering the next screen. All I need to display is a looping 7 frame animation where each frame is saved as one nametable and each frame has the same palette.
Yes.Zsy wrote:So the best way to do this would be to use either horizontal or vertical mirroring and load the next nametable while the other one is being displayed then switch them out...
By waiting for more than one vblank. The exact details depend on which country's version of the NES you're targeting, but it appears you've left the Location field in your profile blank. Do you live in North America, Japan, Brazil, Europe, Australia, or elsewhere?Also, how does one go about changing the framerate?
Sorry about that, only just joined and forgot to fill in the profile section.By waiting for more than one vblank. The exact details depend on which country's version of the NES you're targeting, but it appears you've left the Location field in your profile blank. Do you live in North America, Japan, Brazil, Europe, Australia, or elsewhere?
I'm targeting the NTSC version of the NES.
So since I would be going from 60 fps to 30 fps I could just use a binary variable to count every other Vblank?
Thanks for all of the help guys, I've been working on a routine to cycle through 8 frames by drawing the next one onto the nametable that's not currently being used.
(Since I'm using vertical mirroring these would be $2000 and $2400)
And my question is, do you always need to clear a nametable immediately before drawing to it?
(Since I'm using vertical mirroring these would be $2000 and $2400)
And my question is, do you always need to clear a nametable immediately before drawing to it?
So nothing bad will happen if I just overwrite the nametable?Memblers wrote:Only if you want to leave some of the previous contents in there. Then drawing to it would do the clearing (overwriting in this case).Zsy wrote: And my question is, do you always need to clear a nametable immediately before drawing to it?
(Well, assuming it's the one that's not being shown onscreen.)
There is no reason to clear it if you are rewriting all 960 bytes. Just draw the new screen over the old one.Zsy wrote:So nothing bad will happen if I just overwrite the nametable?
Yes, but the fact that a name table is not being displayed doesn't mean you can write to it at any time, you still have to do it during VBlank.(Well, assuming it's the one that's not being shown onscreen.)
Well, this would be my problem.Yes, but the fact that a name table is not being displayed doesn't mean you can write to it at any time, you still have to do it during VBlank.
I assumed it was safe to overwrite a nametable simply because it was offscreen.
Right now all of my code is running on an NMI triggered by Vblank and I'm getting glitchy graphics till about halfway through the screen. So I think what may be happening is the nametable starts to get drawn but then the NMI is triggered again, restarting the code...
Nope. Pretend a nametable is half onscreen and half off due to scrolling. Under your mental model of PPU operation, what would be safe to overwrite?Zsy wrote:I assumed it was safe to overwrite a nametable simply because it was offscreen.
Try tracing through it in a debugger such as that in Nintendulator or FCEUX. And it might improve things if you acknowledge the NMI by reading PPUSTATUS ($2002) near the start of your NMI handler.Right now all of my code is running on an NMI triggered by Vblank and I'm getting glitchy graphics till about halfway through the screen. So I think what may be happening is the nametable starts to get drawn but then the NMI is triggered again, restarting the code...
I think your data transfer is taking too long. When VBlank starts, you start copying tiles, then VBlank ends and the frame starts rendering, but you're still copying tiles, which glitches the display.Zsy wrote:Right now all of my code is running on an NMI triggered by Vblank and I'm getting glitchy graphics till about halfway through the screen.
With the fastest possible byte copying routine, which is just a long series of LDA $XXXX; STA $2007, you can update about 280 tiles. Since a name table has 960 tiles, you would need 4 VBlanks to update them all (the animation would play ay 15fps).
If you have a lot of PRG-ROM space left, and your screens are always the same, you can make the updates a little faster by loading A with immediate values, so you'd have a long series of LDA #$XX; STA $2007. With that code you could update about 370 tiles per VBlank, so it's take only 3 of them to update a full screen (the animation would play at 20fps). But like I said, that would use a lot of RAM, 5 * 960 bytes per screen to be exact. You could fit 6 screens in 32 KB that way.
One thing I like to do is write to the scroll such that I switch between nametable #0 and nametable #3. That way it doesn't matter whether it's horizontal or vertical mirroring. But that will fail on mapper-controlled single screen mirroring.
I did tons of nametable updates for Chu Chu Rocket, but I only had to transfer 432 tiles. So that's 18 rows worth of 24 tiles, and 18 changes of PPU address. I did it over two frames, and that's with extending vblank by about 4 scanlines. Of course, you also have to scroll correctly on frames where you don't extend vblank. Turning off early may be easier, but that has a whole other can of worms from sprite glitch problems, which emulators don't emulate.
I did tons of nametable updates for Chu Chu Rocket, but I only had to transfer 432 tiles. So that's 18 rows worth of 24 tiles, and 18 changes of PPU address. I did it over two frames, and that's with extending vblank by about 4 scanlines. Of course, you also have to scroll correctly on frames where you don't extend vblank. Turning off early may be easier, but that has a whole other can of worms from sprite glitch problems, which emulators don't emulate.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!