This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Updating the screen

Updating the screen
by on (#105153)
So, I'm trying to understand NES game code on a conceptual level. I've done some asm with other CPUs, but not the 6502, or the 2A03 for that matter.

I would like to know the manner in which the nametable data and attribute table actually get to the PPU during the NMI. Does the CPU block transfer all 960 bytes of the nametable and the attribute table at once? From what I gather, the actual transfer is usually a loop.
Re: Updating the screen
by on (#105154)
xgamer wrote:
Does the CPU block transfer all 960 bytes of the nametable and the attribute table at once?

No, there's no time for that during VBlank. Games just transfer the parts that change from one frame to the next. For example, when a game scrolls, a large portion of the background remains the same, only the new parts that are scrolling into view need to be updated.

Quote:
From what I gather, the actual transfer is usually a loop.

It can be a loop, but it depends on how much data needs to be transferred. If you have a lot of data to transfer, unrolling the loop would be a good idea. Realistically, you can transfer at most ~270 bytes to VRAM, and that's with an unrolled chain of LDAs STAs and you don't do anything else in the same VBlank (no sprite updates). If you do update the sprites, you can transfer about 210 bytes with fast unrolled code. The number drops significantly when you use traditional loops.

You can buy some extra time with forced blanking which is turning rendering off during the visible portion of the frame. You can chop some scanlines at the top and bottom and get some extra VBlank time, but this is not so trivial and not recommended for beginners.
Re: Updating the screen
by on (#105155)
tokumaru wrote:
No, there's no time for that during VBlank. Games just transfer the parts that change from one frame to the next. For example, when a game scrolls, a large portion of the background remains the same, only the new parts that are scrolling into view need to be updated.

Ah, the dirty rectangles method. But wouldn't checking for differences in the tables take as much time as block transferring the whole thing? Wouldn't you have to compare byte to byte?
Re: Updating the screen
by on (#105157)
When you scroll, new areas of the map become exposed, so you draw new rows of columns of tiles onto the nametable. No checking, no dirty rectangles.
If you're scrolling in 4 directions, that's a column of 32 tiles, a row of 32 tiles, 8 bytes of attributes for a row of tiles, and 8 bytes of attributes for a column of tiles.
You also might be using more than 32 tiles in a row or column, depending on how the nametables are arranged. For example, you might use 34 or 36 tiles for a row instead of 32 if you are using vertical mirroring.
You might also allow tiles on the map to change as well, so that's 4 bytes that change, plus 1 for the new attribute byte.

Every time writes aren't contiguous, you write a new vram address before each set of bytes. Note that there is also a +32 increment mode to let you write columns of tiles.

When you write a row of tiles, you might be breaking the row into two pieces. One set of writes for one nametable, and another set of writes for another nametable.
Re: Updating the screen
by on (#105158)
xgamer wrote:
But wouldn't checking for differences in the tables take as much time as block transferring the whole thing? Wouldn't you have to compare byte to byte?

You don't have to compare the contents of the name table. A scrolling engine is meant to keep track of what's on screen and what's not, so it can easily tell what parts of the map are entering the screen and where in the name tables they should be drawn.

The math is quite simple really. Think of a side-scroller. The level just started and an entire screen has been drawn, 32 columns (since it's a side scroller, screens are always drawn in columns) of tiles. Scroll one pixel to the left and the game's in trouble, since the 33rd column contains uninitialized data (i.e. garbage). So, before the next frame is rendered, the game needs to fetch the 33rd column of tile from the level map and write it to the 33rd column of the name tables (that would be the first column of the second name table, assuming the game is using vertical mirroring and has the name tables arranged side by side).

That just goes on and on, every time a new section is about to enter the screen, the scrolling engine reads the data from the level map and writes it to the correct spot in the name tables. You can see that in action if you use an emulator with good debugging features. Open a game that scrolls in FCEUX for example. Then open the name table viewer and walk around and you'll see how the name tables are updated, and how new tiles overwrite old ones. The amount of tiles updated varies from game to game depending on how their level maps are stored and how the name tables are arranged, but the basic concept is always the same.
Re: Updating the screen
by on (#105166)
Image

Scrolling seam updates in Super Mario Bros.
The red brackets represent the visible area, and the :?: blocks represent the area of the map that the CPU is decoding and uploading to the PPU during vblank
Re: Updating the screen
by on (#105169)
tepples wrote:
Image

Scrolling seam updates in Super Mario Bros.
The red brackets represent the visible area, and the :?: blocks represent the area of the map that the CPU is decoding and uploading to the PPU during vblank

Yeah, I understand how updating works during scrolling. What about when a significant part of the background changes, for example, in Metal Man's stage in Mega Man 2, where the machinery in the background is moving relatively quick. What's more is that the areas that need to be updated aren't contiguous in memory. How does the update routine know exactly which blocks need to be updated?
Re: Updating the screen
by on (#105171)
The gears in the background of Metal Man's stage are animated via palette cycling; the last two colors change pretty much every frame; the conveyor belts are animated in the same fashion.
Re: Updating the screen
by on (#105173)
xgamer wrote:
Yeah, I understand how updating works during scrolling. What about when a significant part of the background changes, for example, in Metal Man's stage in Mega Man 2, where the machinery in the background is moving relatively quick. What's more is that the areas that need to be updated aren't contiguous in memory. How does the update routine know exactly which blocks need to be updated?

Like freem said, that's just an illusion. Notice how these animations use only 2 colors, instead of the 4 the NES is capable of. This makes it possible to store 2 different images in the same tile, and with some palette trickery you can display one or the other. The background itself doesn't change.

There other tricks to animate the background, such as tile bankswitching or pattern table updates (possible with CHR-RAM). When tiles in the pattern tables change, all instances of them will display the new graphics when the next frame is rendered. The blocks in SMB3 for example are animated like this, the name table isn't touched at all.
Re: Updating the screen
by on (#105175)
If you need to do a dirty rectangles style update, you will normally do all the calculation you can outside of the NMI (where you have much more time), and just update a simple list (or block of code in RAM) to be sent to the PPU very quickly during the next NMI.

I forget which Mega Man has this, but there's one with a Wily stage boss that's basically a giant machine that covers the whole screen, and you can see very clearly that it takes the game many frames to get around to updating the whole thing. The update ends up looking rather ragged, actually. (This is why big bosses are usually done with scrolling tricks instead.)
Re: Updating the screen
by on (#105178)
After looking at MM2 again, I see what you guys are saying. I can see the illusion now, especially in Bubble Man's stage. The tile patterns of the "waterfall" in the background don't actually change at all, the palettes are just alternating between white, and 2 different shades of blue. That's a cool trick.
Re: Updating the screen
by on (#105179)
Tricks like these are the reason coding for these old consoles is fun! If it was just about straightforward programming to get a game done we'd all be coding for PCs, not for the NES.
Re: Updating the screen
by on (#105181)
The other problems with PCs are that you can't rely on a gamepad's presence and that a lot of players expect more complex graphics than one person can reasonably make.
Re: Updating the screen
by on (#105182)
tepples wrote:
a lot of players expect more complex graphics than one person can reasonably make.

If that was the case, there wouldn't be so many retro-looking games. Anyway, we're not talking mainstream gaming here, the number of people who still own old consoles or play on emulators regularly is probably not much different than the number of people playing indie PC games.