A Hard Look At Hardware – Rendering On The NES

Hey reader! You read that title right, today I’m looking at the rendering systems of the Nintendo Entertainment System. It’s an old system, and one I’m not likely to be developing on in the near future, so it’s an understandably and odd choice to be analysing. However, it’s one of the few consoles that not only has a host of hardware information readily available, but also has an architecture simple enough to get a grasp on with relative ease.

Anyway, the core of what I’m going to be looking at today is the rendering processes and limitations of the console, since I don’t have to break down the entire thing. More importantly, I’m going to be looking at some of the ways these impact how one would design a game for the NES. So let’s get to it.

First and foremost, on the NES you’ve got a screen size of 256 x 240 pixels to work with. The sprites you can use must either be 8 x 8, or 8 x 16. If you want anything bigger than that you’ll need to break it up and put it back together during run-time. This also means you can fit 32 sprites across the screen, and 30 sprites down the screen (assuming you use only 8 x 8 sprites). Not that you can actually have that many though, due to physical hardware limitations.

Speaking of which, the NES has a physical limit of how many sprites it can store to be rendered to any given frame. With the available memory and with each sprite taking up 4 bytes of data, a total of 64 sprites can be stored. However, it should be noted that these are individual instances of sprite, not the sprites themselves.

As such, this means that only 64 different things can be rendered in a frame at any given time. Even if you’re rendering the same sprite of an office chair over and over (perhaps for a NES rendition of Casual Office Extreme: Learning Edition), you can only have 64 of that six-wheeled beast on the screen at any time. This is because the 4 bytes doesn’t contain the sprite itself, but is a reference to the pattern table that allows the sprite to be constructed (along with a lot of other useful data about its position and the like).

What’s more, is that the rendering process renders the frame line by line, moving down the screen through each individual row of pixels. And here we encounter a second physical limit, in that for each line only eight sprites may be stored in the buffer and, subsequently, rendered.

But which eight sprites are chosen? That depends primarily on how you load them into the original 64 sprite buffer. The first sprite loaded in will be rendered first and at the front. Every subsequent sprite is then loaded sequentially behind that first sprite. It possible to further refine this to a point using a front priority boolean on each sprite, the defines which is rendered first regardless of order, but has a lot of quirks related to transparency.

Regardless, all this means that if one part or another of more than eight sprites is on the current line, whatever is ninth is out of luck. Kind of. There is a system in place to detect when there are more sprites waiting to be rendered, but it has a serious bug in it. This bug causes it to begin checking the waiting data incorrectly, and as such results in frequent false-positives and false-negatives, both of which help nobody.

This limitation means that if you’re implementing a character, for example, they can be no wider than 64 pixels, otherwise you’ll be surpassing the 8 sprite limit. At this point, the sprites are going to flicker in and out of existence, which isn’t going to look good. You can, however, make that character as tall as you please. Up to the 240 pixel screen height, that is, if you’re also willing to sacrifice 30 of your 64 sprites for the frame… and they’re only one sprite wide.

Lastly, let’s talk colours. More specifically, background colours. When defining the frame’s background (not via sprites), each 16 x 16 group of pixels is limited to using a single colour pallette. Each colour pallette is then limited to containing 4 colours. However, the first colour of every pallette must be the same. And considering you can only have 4 different pallettes, this leaves a total of 13 colours available for a single background.

So essentially, your background on the NES must be designed very deliberately, with pixel by pixel detail (made easier by the fact that there’s not that many). For example, here’s how a background would be divided into a grid:

thwaite_bg_with_attr_grid

Image via NES DEV, and created from the game Thwaite.

And here’s how the four pallettes would apply to that grid:

thwaite_attrs

thwaite_palette_color_sets

Images via NES DEV.

 

Note that the first colour of every pallette is black. The last colour of every pallette is white, but it’s worth noting this is coincidence, not any form of necessity like the first. But this just goes to show the extremely tight colour budget you have for the creation of your NES game background.

So, after all that, it’s pretty obvious that to develop for the NES, you need to take into account a lot of rather harsh limitation, especially by our current standards. You need to pay close attention to exactly how many sprites you’re using, exactly how big the sprites you intend to use are, exactly how many are going to be at the same height at the same time, and exactly how you’re going to spread your colours across your background pixels. And all of this is exactly why I probably won’t be making a NES game any time soon…

NOTE: For all of you wondering where I got all of this fascinating technical information from (and those lovely diagrams), the NES DEV community is relentlessly thorough. You can find a plethora of additional information down to some of the most minute physical specifications there and on their wiki.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s