Hi,
I have posted here before, but I can't remember my old username, so hello again (a few years ago I made a copyNES from kevtris' schematic on his site, I was also considering using a NES to read controller data and output data to an XBOX for emulation, but never tried it.) So..
I have always wanted to, but recently decided maybe I would get more serious about learning to code for the NES. I have read tons of docs, and asm code, but once you start to actually code you realize you are not clear on some details.
I realize that this information is out there, I just want a an explicit clear answers/opinions to some questions I have.:
1. Should or can any PPU writes be done during the frame, besides of course ones that must be for desired effects - split screen scrolling, etc
2. When the PPU activates the NMI is it okay to immediately start writing to the PPU (Is the PPU already in vblank as soon as NMI code is hit or does the NMI activate a few clocks early)?
3. I see it is common practice to buffer most writes and push them to the PPU in NMI, but what about nametables? They take up a lot of space. would you buffer new offscreen tiles when scrolling? Is it common practice to buffer a nametable, or is the code for that done in the NMI, or is this where metatiles help?
4. When is it a good idea to turn off the PPU? I see the PPU has to be off if you are filling the whole nametable, is there anything else that takes more than vblank time?
5. If I am in my NMI and I know a sub routine is going to take more than vblank is it okay to shut off the PPU in NMI and do my thing, then turn it back on and continue.. any issues to worry about?
6. Proper way to shut off the PPU for long writes? Turn off rendering? Everything?
7. What is with the read of $2002 in NMI? do I really need to read (acknowledge) it? what if I don't? (more just curious here..)
Some basics..
Moderator: Moderators
Re: Some basics..
You can write to PPU registers $2000, $2001 freely. You can't read/write $2006/$2007 (unless rendering is disabled).Movax12 wrote: 1. Should or can any PPU writes be done during the frame, besides of course ones that must be for desired effects - split screen scrolling, etc
Yes it's ok.2. When the PPU activates the NMI is it okay to immediately start writing to the PPU (Is the PPU already in vblank as soon as NMI code is hit or does the NMI activate a few clocks early)?
The reason writes are buffered is because there's not very much VBLANK time per frame (~2K cycles). This means with even a completely unrolled loop you can only write about 250 bytes per frame. Not enough to update an entire nametable.3. I see it is common practice to buffer most writes and push them to the PPU in NMI, but what about nametables? They take up a lot of space. would you buffer new offscreen tiles when scrolling? Is it common practice to buffer a nametable, or is the code for that done in the NMI, or is this where metatiles help?
Games don't update the entire nametable every frame, they only update what's needed (for a sidescrolling game around 30 tiles (bytes) + attributes).
You should wait for VBLANK before turning rendering on/off to avoid glitches. Also make sure palette writes are in VBLANK if you don't want any glitches on screen.4. When is it a good idea to turn off the PPU? I see the PPU has to be off if you are filling the whole nametable, is there anything else that takes more than vblank time?
This depends on the situation but usually you don't want to do this. Black (/bg colored) frames don't look too good in between rendered frames.5. If I am in my NMI and I know a sub routine is going to take more than vblank is it okay to shut off the PPU in NMI and do my thing, then turn it back on and continue.. any issues to worry about?
Turn off BG and sprite rendering by writing to $2001.6. Proper way to shut off the PPU for long writes? Turn off rendering? Everything?
It's good practice but not strictly necessary. Not acknowledging it can lead to some nasty bugs in some cases.. for example if you toggle the NMI flag (in $2000) in your NMI code and didn't ack, it will cause a bogus new NMI to be generated.7. What is with the read of $2002 in NMI? do I really need to read (acknowledge) it? what if I don't? (more just curious here..)
Re: Some basics..
The only PPU writes you do while the PPU is rendering are ones which change the screen scrolling, or turning off the screen. You don't do any data writes while the PPU is rendering.Movax12 wrote:Hi,
I have posted here before, but I can't remember my old username, so hello again (a few years ago I made a copyNES from kevtris' schematic on his site, I was also considering using a NES to read controller data and output data to an XBOX for emulation, but never tried it.) So..
I have always wanted to, but recently decided maybe I would get more serious about learning to code for the NES. I have read tons of docs, and asm code, but once you start to actually code you realize you are not clear on some details.
I realize that this information is out there, I just want a an explicit clear answers/opinions to some questions I have.:
1. Should or can any PPU writes be done during the frame, besides of course ones that must be for desired effects - split screen scrolling, etc
Turning off the screen only seems to be 'safe' to do when you are in later pixels, but not quite at HBLANK time, around 200-255 seems safe. Otherwise you sometimes get sprite glitches in the next frame. This is new stuff that was discovered recently, and is still not understood well. Most games back in the day that turned off the screen during rendering time seemed to do it fine.
The NMI actually comes a scanline late, there's an entire blank scanline where you are able to freely do drawing before the Vblank period starts. But the only way to take advantage of that is a well-timed interrupt near the bottom of the screen.Movax12 wrote: 2. When the PPU activates the NMI is it okay to immediately start writing to the PPU (Is the PPU already in vblank as soon as NMI code is hit or does the NMI activate a few clocks early)?
Often games only use a small buffer for nametable updates. A row or column of tiles is about 32 bytes large, so a game may allocate 64 bytes for tile data, 16 bytes for tile attribute data, and any pointers and length information needed to draw it.Movax12 wrote: 3. I see it is common practice to buffer most writes and push them to the PPU in NMI, but what about nametables? They take up a lot of space. would you buffer new offscreen tiles when scrolling? Is it common practice to buffer a nametable, or is the code for that done in the NMI, or is this where metatiles help?
Mostly games draw a new row or column of background data as it scrolls. Some games draw two columns instead of just one, some even draw more.
Metatiles are still too slow for NMI processing time, you need to convert the metatiles into physical tiles during your main loop, then blast out the data during vblank time.
In my Chu Chu Rocket game, I'm using 216 bytes for nametable updates, and I'm blasting out an entire half-nametable every frame. This extends about 4 scanlines into the screen, then I do the scrolling and turn on the screen after it's done with all the drawing.
When you have CHR RAM, and you want to load an entire character set, that's also a good time to have the screen off for a few frames.Movax12 wrote: 4. When is it a good idea to turn off the PPU? I see the PPU has to be off if you are filling the whole nametable, is there anything else that takes more than vblank time?
Or you might be using a system that runs the game's scrolling code to fill in the initial nametables, so you can call the code that produces the tiles and the code that consumes the tiles. I do that in one game, and it takes about 5 frames to draw the screen.
If you do that, you turn the screen back on, and it will treat whenever you turned it on as the top of the screen, so you'll see the entire screen drawn too low for that frame.Movax12 wrote: 5. If I am in my NMI and I know a sub routine is going to take more than vblank is it okay to shut off the PPU in NMI and do my thing, then turn it back on and continue.. any issues to worry about?
If you know you will *consistently* draw more than NMI time every frame, you can have some of the top scanlines always blank, and make the effective top of the screen lower.
Usually you want to turn off the PPU during Vblank time for best results, then you don't have to worry about the sprite glitching bug.Movax12 wrote: 6. Proper way to shut off the PPU for long writes? Turn off rendering? Everything?
If you're turning it off during rendering, and want to leave it off for a few frames, then you can get away with turning the screen off late.
If you're turning off the screen during rendering in order to make some PPU writes, try to do it late in a scanline, but not quite at HBLANK time. The DMC channel can sometime halt the CPU to fetch a byte, and that eats 5 CPU cycles, or 15 ppu pixels.
Reading 2002 (PPUSTAT) will clear the VBL flag, and reset the low-byte high-byte latch that's used when you do your two writes to 2005 (PPUSCROLL) or 2006 (PPUADDR). It's a way of guaranteeing that the correct address is used when you set the PPU address. But if you need the help of reading 2002 to ensure the larch is in the right place, you probably have messy code.Movax12 wrote: 7. What is with the read of $2002 in NMI? do I really need to read (acknowledge) it? what if I don't? (more just curious here..)
If you don't do the 2002 read at the beginning of NMI, then you could get a second NMI interrupt if you disable then re-enable NMI, because the VBL flag is still set.
Sometimes a game will read 2002 a lot during vblank, this is because the Sprite 0 Hit flag does not clear until vblank ends. So games wait for the flag to become clear, then they know when rendering time has started, and they can start waiting for a new sprite 0 hit.
If you know you have a long NMI handler that always spills past VBLANK time, you can even read the VBL flag as a crude way of detecting a PAL region console.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
I think between the two replies you've answered all my questions at least for the moment, thank you. If anyone would like to add anything though, feel free, more info is never bad.
From what I've just read, I would think then it is generally a good idea to wait for vblank to turn PPU drawing on or off, unless you know have the timing perfect?
thefox, I do realize that turning off the PPU for a few frames will result in the image disappearing for a few frames, I was thinking for setting up a new nametable (title screen to game for example).
From what I've just read, I would think then it is generally a good idea to wait for vblank to turn PPU drawing on or off, unless you know have the timing perfect?
thefox, I do realize that turning off the PPU for a few frames will result in the image disappearing for a few frames, I was thinking for setting up a new nametable (title screen to game for example).
You are correct. The side effects of not waiting for VBlank are not very bad though, the image just "jumps" for 1 frame, and in fact, many early commercial games do that once in a while, but it's certainly more professional to avoid this if you can.Movax12 wrote:From what I've just read, I would think then it is generally a good idea to wait for vblank to turn PPU drawing on or off, unless you know have the timing perfect?
Yes, you typically turn rendering off for large screen updates between sections of the game. When rendering is off you don't even have to worry about buffering data, since the PPu is completely free for writing/reading.I do realize that turning off the PPU for a few frames will result in the image disappearing for a few frames, I was thinking for setting up a new nametable (title screen to game for example).