My lizard is the Lizard of NES Sprite Rendering
I spoke a little about sprites in an earlier update but it was mostly about the tools I use to draw and assemble them. In this update I'd like to go more into technical detail about how they work on the NES.
NES rendering has two layers to it. One is a grid of 8x8 pixel tiles, which I will refer to as the background. The other layer is the sprite layer, which still works with tiles, but instead of being constrained to a grid each one can be individually placed.
The background layer has its own set of limitations, and you can read my previous update about tiled backgrounds for more information, but mostly the background is used for land, sky, or other inanimate parts of the world. The limitations of the grid make it difficult to use the background layer for animation, but at the same time the structure of the grid makes it very efficient for coverage. It's easy for the hardware to store and draw tiles when they're organized in a regular spacing like this.
The sprite layer is used for things that move around. Unlike the background layer, sprites can be updated quickly because the NES has a dedicated hardware feature for uploading sprites to the GPU every frame. Also unlike the background layer, they can be placed anywhere on the screen; there is no grid for sprites. This freedom and agility is essential for characters and animation, but they are much less efficient in hardware than the background. Even though the NES can draw nearly 1000 background tiles on the screen in any given frame, it can only show 64 sprite tiles. It takes a lot more circuitry to handle tiles that can go anywhere, and there were a lot of additional restrictions that they imposed to make them work.
This kind of two layered approach was not the only way to make graphics hardware for games, but they proved very effective for the NES, and together define how games look on the system.
The NES can draw up to 64 sprite tiles in a single frame. There are two options for tile size: they can be 8x8 pixels, like the background layer, or they can be double-height for 8x16 tiles. This is not a per-tile option; it applies to all sprites on the screen at once.
Game developers had to choose between a detailed, more careful arrangement of 8x8 tiles, or larger but less efficient characters using 8x16 tiles. Usually this choice has to do with how large the characters are. It may sound surprising that 8x8 tiles were used at all, but there are a lot of factors that made them a compelling option. Even games with large characters might favour 8x8 tiles if they're not having a problem with the 64 tile limit.
Sophia III from Blaster Master shows what you can do with the fine control of smaller tiles. Here you can see 6 sprite tiles making up the sprite. The wheels move separately from the other tiles, giving it very expressive motion. No pixels appear to be wasted here.
Teenage Mutant Ninja Turtles used double-high sprites, and you can see how this resulted in a lot of empty space around the characters. The main disadvantage of this is that the empty areas still take up space in tile ROM (or RAM), and that space is important.
The NES tends to favour characters that were tall vertically, rather than wide, and the double-high sprite mode was not the only reason for this (see Flickering below).
Lizard uses 8x8 sprite tiles. I wanted a world that was small and detailed, and it seemed the best choice for me. From what I've seen, 8x16 is not used as often in NES games. When I was looking for examples for this article, I was surprised to find that many games with large and tall sprites like Punch Out! still used the smaller tiles.
The NES has a collection of ~55 colours available for use. The actual colours produced are dependent on NTSC or PAL signal generation, and vary from TV to TV, but emulators try to approximate this with an RGB palette.
This scheme is basically a set of 4 intensities across a circle of 12 hues, plus a grey column. At the end of the palette is a leftover dark grey column; the darkest entry in this column is a forbidden colour that actually produces a signal that is too black, causing an unstable picture on some televisions.
So, there is this overall collection of 55 colours, but NES sprite tiles can each only use 3 colours taken from this larger set. Tiles have 2-bit pixels, which means they can have one of 4 values. Because a value of 0 represents a transparent pixel, there are only 3 values left to represent colours.
This shot from Wizards & Warriors shows a collection of 3 colour sprites. This is the typical way sprites look on the NES.
Game developers often wanted more than this, though. Because there are actually 4 sets of 3 colours available for use (see Four Palettes below), and a character sprite is made up of several tiles, you can use a different colour set for each tile.
Mega Man's face uses a separate tile with different colours from the rest of his body.
Bill from Contra has a different colour set on his top and bottom halves.
A set of colours is known as a palette. The NES has 4 palettes available for backgrounds, and 4 more just for sprites. The way a game organizes and uses these palettes deeply affects its design, and I think dealing with this problem is the cornerstone of what makes an NES game look like an NES game.
It's easy for a game to change the palettes whenever it is needed, but the difficult part is how to manage having only 4 to work with at a time.
Take a look at this underground scene from Super Mario Bros. and its palettes.
I won't cover the background palettes in detail, but it should be noted that one palette has an animated colour, and is used for stationary coins. Because the coins don't move, it was better to make them part of the background, and just update that small area of the background whenever you collect a coin. This allowed long rows of coins that wouldn't have been practical as sprites.
The sprite palettes:
- 1. This is reserved for Mario (or Luigi when he's playing). It will change colours if you pick up a fire flower.
- 2. Turtles, hammer bros, bowsers, and 1UP mushrooms all share this slot. Above ground it uses a green, white and yellow set of colours instead.
- 3. Red turtles, mushrooms, fireballs, and moving coins share this slot. Note how in the scene above, a sprite coin appears when the block is smashed from below. This coin uses different colours from the background coin it replaces, and is also only 8 pixels wide; if you're paying attention it looks curiously different than the stationary coins.
- 4. Goombas, and smashed bricks use this slot. Note how this means goombas will always be the same colour as brick tiles in any environment (e.g. they are grey in the castle).
If you just consider a single frame of an NES game, it's fairly easy to come up with a set of palettes that work for that screen, but when you have to think globally about the whole game it becomes a pretty significant problem. Do you reserve palettes for the player character? Do you have a status bar or HUD that needs a palette? Are characters allowed to change colour, or should they be consistent? Super Mario Bros. approaches this by dividing all of its characters into four categories.
In this screen from Battletoads you can see four sprite palettes in use. This game dedicates 3 whole palettes to the player characters. Because it is a two player game, two palettes are used to distinguish them; there is a green palette for player 1, and an orange palette for player 2. Both player sprites share a second yellow palette for the face and chest. The fourth palette is red, used for the Psyko Pig enemies.
This fourth palette is allowed to change over the course of a level, but the ones used for players are always fixed. This game features a lot of stopping points where you must defeat all enemies to proceed; this structure makes it easy to control which colours are needed in that fourth palette at any given time. Once you finish one batch of enemies, it can change the palette to prepare for the next set.
A lot of enemies or items in the game will use one of the player palettes to avoid having to allocate the free one. In the example above you can see pieces of the walker enemy on the ground, which used the fixed yellow palette.
In my game, I've dedicated two palettes the player: one for the current lizard, and one for the player's face. This leaves two free palettes to use in different ways. Because my game is grouped into rooms, I can choose combinations of creatures that don't require more than two. This is one of the ways the NES has really affected the design of my game; I am constantly making choices based on which combinations of characters can work with the palette restrictions.
Because the current lizard changes, and the player's skin colour is randomly selected, I generally avoid using the two fixed palettes for anything but the player. I wanted creature colours to be consistent, so I did not want their colour to depend on the state of the player. The exception here is the white colour in the skin palette; this is always white (for the lizard's eye), but creatures may use this one as well (e.g. a white bird).
If you've spent any time playing NES games, I'm sure you're familiar with the sprite flickering phenomenon.
What may surprise you is that the flickering is not a hardware feature of the NES; this is something that developers had to program into the game's software. It is actually a coping mechanism to avoid an even worse problem.
The NES renders the screen row by row, synchronized with the television. These rows are known as scanlines. The NES has a hardware limit of only 8 sprite tiles on any given scanline. This is one of the most oppressive limitations the system has; if you ever try to put more than 8 tiles on a single line, it will just drop whichever ones were drawn last. This is the primary reason that it is easier to make tall characters than wide ones on the NES. In a platform game, where action tends to occur on a level plane, it's very hard to ensure you won't have too many characters on a single line.
Double Dragon is one of the few games that does not implement a software flickering technique. In the screenshot above, notice how you can only see part of a Linda enemy lying on the ground, and part of a whip. In this particular moment, these sprites are simply missing pieces until I move out of the way.
What most games do to cope with this is simply to change the order things are drawn. By switching the order every frame, the last character to get drawn will always be different, so every character will be seen for at least part of the time. They flicker, or appear somewhat transparent, but at least they're appearing often enough that you can still see them. On a CRT television, fast flickering tends to look like transparency, though on a modern TV that is converting the NES' signal as 480i, you might see alternating lines instead.
NES games are notorious for having flickering sprites disappear when the framerate of the video is reduced (e.g. for YouTube at 30fps). This is because games often intentonally hide a sprite every second frame to make it appear 50% transparent to indicate damage, or in other situations. Because I expect Lizard to be played in modern conditions, I make sure not to flicker on every second frame, but instead use a randomized cycle.
The scanline limit is also a big reason why 8x8 sprites seem to be favoured. Transparent sprites still count toward the limit of 8, so wasted transparent space at the top or bottom of an 8x16 sprite tile increases the chance of overlap. Using the smaller sprite tiles allows tighter control of the problem.
Between the 8-sprite limit, and the overall limit of 64 tiles, it's difficult to make large characters on the NES out of sprites. For this reason, it's common to see large characters like bosses built out of a combination of background tiles and sprites.
When these are used together, generally there is not very much animation in the part of the character made from background tiles. The animated parts of the character are still done with sprites.
Often the background will consist of nothing but the boss character, leaving black or a sky colour surrounding it. This allows the large character to be moved around with the hardware's background scrolling feature.
Another strange problem the NES has is how sprites behave at the edges of the screen. A sprite tile's location is specified by two 8-bit values, for an X and Y coordinate. This means X or Y can be in the range 0-255. The NES' screen is 256 pixels wide, and 240 pixels tall, which may not sound like a problem at first, but because a sprite is 8 pixels wide we need to think about what happens if part of it goes over the edge of the screen.
When characters are entering or leaving the screen, which happens constantly in any game with scrolling, you have to deal half a character being off the edge of the screen. The X,Y coordinate of a sprite tile actually specifies the top left pixel of the tile. On the right side, this is fine: if you put a sprite too close to the edge, part of it will just be offscreen. What if you want to put a partial sprite on the left side, though? What you really need is X values from -7 to -1, but the lowest you've got is 0. At X of 0 the tile is already fully onscreen, so you can't do it!
Instead of trying to come up with some way to extend the range of X into the negative, Nintendo created a hardware solution to work around the problem. There is an option to blank the left 8 columns of the screen. This makes it so X from 1 to 7 acts kind of like -7 to -1 would, with a partial tile being shown on the left side. Many games used this option.
As you can see, Super Mario Bros. 3 had no problem showing partial characters scrolling in from either the right or the left. (There are some background colour issues visible on the right, but that's a different topic, worth an article of its own.)
I find it a tough call whether this is a good solution or not. On some older TVs, this blanked edge might have been hidden under a bezel, but if you can see it the whole picture looks off centre. You're also missing out on a bit of screen the game could be showing you.
For Lizard, I thought having that extra space on the screen was too valuable. I wanted to be able to show just a little bit more of every room to the left, so I chose to live with the left-edge problem on my sprites instead.
Problems at the edge of the screen are typical of NES games anyway; many games don't deal with sprites at the edge very well at all, and it's not uncommon to see a character bleed over to the wrong side of the screen. At least this won't happen in Lizard!
The NES has the same problem at the top edge as the left edge, but they did not build a hardware blanking solution for it. On NTSC televisions, the top and bottom 8 lines tend to be hidden anyway, though it can be a visible problem on PAL systems.
That's most of it. There are a hundred other minor details, like placing sprites behind the background, or using them to time raster effects, hardware glitches, strange software techniques, etc. but I thought this article was already too long.
I came into NES development with previous professional experience in modern graphics programming. At first NES rendering seemed simple by comparison, but the more I dug into it, the more strange and subtle details I found. I think it took me about a year of working with the system before I felt I understood the "correct" way to do a lot of things on the NES.
I hope this at least leaves you with an understanding of what's essential to an NES sprite.
If you'd like to take a look at what's going on in NES games, you can use an emulator with a good debugger. FCEUX has a debug menu, and in particular the "PPU Viewer" option will let you see sprite tiles and palettes. There is also the NESDev Wiki and NESDev Forum, where you can find all sorts of technical information about the NES, and lots of helpful people to talk to.
This topic had been on my mind lately, because as I'm finishing up the bosses, I ended up doing an overhaul of my sprite drawing code. This wasn't the first time I needed to revise this stuff, but I am pretty certain it will be the last for this project. ;) In particular I wanted more graceful handling of the edge problems mentioned above. I've had to do a lot of planning around palettes, too, and I realized I hadn't quite covered this topic previously. There are a few cases where I've gone to great lengths to squeeze out another colour from my palettes; stuff you wouldn't know about while playing, but dealing with the palette problem is where I think the NES makes its biggest mark on my game. It really would be designed differently if I didn't have to worry about them. (Sometimes I want to do murder for a fourth colour!!!)
Anyhow, sorry it's not much of a progress update, more of a technical article, but I've been working steady on the remaining bosses and there's not too much farther to go. I hope to have the game ready for beta testing soon!