Switching Nametables During Vblank

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Zsy
Posts: 26
Joined: Sun Jul 25, 2010 9:47 am
Location: CT, USA
Contact:

Switching Nametables During Vblank

Post by Zsy »

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.
User avatar
Bregalad
Posts: 8036
Joined: Fri Nov 12, 2004 2:49 pm
Location: Caen, France

Post by Bregalad »

If you don't use 1-screen mirroring, it's not necessary to switch name-tables as they are both always accessible. If you use 1-screen mirroring tough, yes you can switch nametables during VBlank and nothing will be seen.
Useless, lumbering half-wits don't scare us.
User avatar
thefox
Posts: 3139
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Post by thefox »

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.
Zsy
Posts: 26
Joined: Sun Jul 25, 2010 9:47 am
Location: CT, USA
Contact:

Post by Zsy »

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.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

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...
Yes.
Also, how does one go about changing the framerate?
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?
Zsy
Posts: 26
Joined: Sun Jul 25, 2010 9:47 am
Location: CT, USA
Contact:

Post by Zsy »

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?
Sorry about that, only just joined and forgot to fill in the profile section.
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?
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

Zsy wrote: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?
Correct. But unless you use timed code to lengthen blanking, you'll need to go down to 15 fps or lower.
Zsy
Posts: 26
Joined: Sun Jul 25, 2010 9:47 am
Location: CT, USA
Contact:

Post by Zsy »

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?
User avatar
Memblers
Site Admin
Posts: 3901
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers »

Zsy wrote: And my question is, do you always need to clear a nametable immediately before drawing to it?
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
Posts: 26
Joined: Sun Jul 25, 2010 9:47 am
Location: CT, USA
Contact:

Post by Zsy »

Memblers wrote:
Zsy wrote: And my question is, do you always need to clear a nametable immediately before drawing to it?
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).
So nothing bad will happen if I just overwrite the nametable?
(Well, assuming it's the one that's not being shown onscreen.)
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

Zsy wrote:So nothing bad will happen if I just overwrite the nametable?
There is no reason to clear it if you are rewriting all 960 bytes. Just draw the new screen over the old one.
(Well, assuming it's the one that's not being shown onscreen.)
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.
Zsy
Posts: 26
Joined: Sun Jul 25, 2010 9:47 am
Location: CT, USA
Contact:

Post by Zsy »

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, this would be my problem.
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...
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

Zsy wrote:I assumed it was safe to overwrite a nametable simply because it was offscreen.
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?
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...
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.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

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.
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.

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.
User avatar
Dwedit
Posts: 4470
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Post by Dwedit »

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.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Post Reply