开发者

NES Programming - Nametables?

I'm wondering about how the NES displays its graphical muscle. I've researched stuff online and read through it, but I'm wondering about one last thing: Nametables.

Basically, from what I've read, each 8x8 block in a NES nametable points to a location in the pattern table, which holds graphic memory. In addition, the nametable also has an attribute table which sets a certain color palette for each 16x16 block. They're linked up together like this:

(assuming 16 8x8 blocks) Nametable, with A B C D = pointers to sprite data:

ABBB
CDCC
DDDD
DDDD

Attribute table, with 1 2 3 = pointers to color palette data, with < referencing value to the left, ^ above, and ' to the left and above:

1<2<
^'^'
3<3<
^'^'

So, in the example above, the blocks would be colored as so

1A 1B 2B 2B

1C 1D 2C 2C

3D 3D 3D 3D

3D 3D 3D 3D

Now, if I have this on a fixed screen - it works great! Because the NES resolution is 256x240 pixels. Now, how do these tables get adjusted for scrolling?

Because Nametable 0 can scroll into Nametable 1, and if you keep scrolling Nametable 0 will wrap around again. That I get. But what I don't get is how to scroll the attribute table wraps around as well. From what I've read online, the 16x16 blocks it assigns attributes for will cause color distortions on the edge tiles of the screen (as seen when you scroll left to right and vice-versa in SMB3).

The concern I have is that I understand how to scroll the nametables, but how do you scroll the attribute table? For intsance, if I have a green block on the left side of the screen, moving the screen to right should in theory cause the tiles to the right to be green as well until they move more into frame, to which they'll revert to their normal colors.

~~~~EDIT: I do wan开发者_如何学Pythont to point out that I know about the scanlines, X and Y. This thought just ran through my mind.

Let's say I'm at scanline Y of 10. That means I'm reading 10 values into my nametables, horizontally. That would mean my first column is off of the screen, as it only has pixel width of 8. However, the color attribute stays, since it has width of 16.

Assuming the color attribute for the entire column is green, would I be correct in assuming that to the user, the first 6 pixels on the left of the screen would be colored green, and the rightmost 10 on the screen should be green as well? So, would I be correct in my assumption that according to the screen, the left?


This site I'm sure you are already very, very familiar with. I will preface this by saying I never got to program for the NES, but I am very experienced with all the Gameboy hardware that was ever released and the NES shares many, ahh quirks with the GB/DMG. I going to bet that you either need to do one of a few things:

  1. Don't scroll the attribute table. Make sure that your levels all have similiar color blocks along the direction you are moving. I'd guess that many first generation games did this.

  2. Go ahead and allow limited attribute scrolling - just make sure that the areas where the changes are occuring are either partially color shared or sparce enough that the change isn't going to be noticable.

  3. Get out your old skool atari 2600 timer and time a write to register $2006 in the end of HBlank update to get the color swap you need done, wait a few tics, then revert during the HBlank return period so that the left edge of the next line isn't affected. I have a feeling this is the solution used most often, but without a really good emulator and patience, it will be a pain in the butt. It will also eat a bit into your overall CPU usage as you have to wait around in interrupts on multiple scan lines to get your effect done.

I wish I had a more concrete answer for you, but this hopefully helps a bit. Thanks goodness the GB/DMG had a slightly more advanced scrolling system. :)


Both Super Mario Bros. 3 and Kirby's Adventure display coloring artifacts on the edge of the screen when you scroll. I believe both games set the bit that blanks the left 8 pixels of the screen, so 0-8 pixels will be affected on any one frame.

If I remember correctly, Kirby's Adventure always tries to put the color-glitched columns on the side of the screen that is scrolling off to make it less noticeable. I don't think these artifacts are preventable without switching to vertical mirroring, which introduces difficulties of its own.

Disclaimer: it's been like five years since I wrote any NES code.


Each nametable has its own attribute table, so there should be no graphical artifacts when scrolling from one nametable to another. The type of color glitching you are referring to is really only an issue if your game scrolls both vertically and horizontally. You only have two nametables, so scrolling both ways requires you to cannibalize the visible screen. There are various solutions to this problem, a great summary of which can be found in this nesdev post:

http://nesdev.parodius.com/bbs/viewtopic.php?p=58509#58509


This site may be of some help. http://www.games4nintendo.com/nes/faq.php#4

(Search for "What's up with $2005/2006?" and begin reading around that area.)

It basically looks like its impossible to get it pixel perfect, however those are going to be the bits you're probably going to need to look into.

Wish I could be more help.


Each nametable has its own attribute table. If you limit your game world to just two screens, you'll only need to write the nametables and attribute tables once. The hard part comes when you try to make worlds larger than two screens. Super Mario Bros. 1 did this by scrolling to the right, wrapping around as necessary, and rendering the level one column of blocks at a time (16 pixels) just before that column came into view. I don't know how one would code this efficiently (keep in mind you only have a millisecond of vblank time).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜