Original NES Zelda - 8 bit palette question

Started by
6 comments, last by renman29 17 years, 6 months ago
Hello, I'm reprogramming the original Zelda for NES in C using the Allegro library for fun and programming practice. I intend to program it as close to the original as I can, with many of the technical limitations. However, I've been having problems from the very start with the graphics. I'm using the tile and spriteset from Zelda Classic, which is a well made remake of the original that supports customization. The bitmaps are in 4 different colors, which forces me to use palettes to switch the colors as needed. I'm not sure how to do this though, as it seems many of the colors in the original game are different, but in the bitmaps I have they are just one. Will I need to modify the bitmaps I have, or is there simply something I'm missing? Just to clarify what I'm asking, for example the color of link's hat and a heart is green in the image I have, but in the original game link's hat is green and a heart is red. If I will have to modify it, I wonder how they programmed it in Zelda Classic to work?
Advertisement
You need to build a palette (at well-choosen times), that contain all the colors you are possibly using in the render.
For exemple, if link is wearing a green heart, and you dont use elsewhere the red color, don't insert it in your palette.

EDIT: There's a more complicated case of this algorithm. If the colors count is greater than 256, then you must try to reduce it to 256. This is a hard work.
If you have it, take a look at the Quake2 (in software) transparency. Yes this is a 8bits renderer. =)
Another solution to this sort of problem (which is what I use), is you can:

-create a palette that consists of a nice distribution of shades for every common color (for example: 8 shades or red, 8 shades or orange, 8 shades of brown/skin, 8 shades of grey, 8 shades of blue, 8 shades of purple/pink, and so on...) This can be done algorithmically.
-when loading an image, for each pixel, it replaces that pixel with the closest matching color in the blended palette (ie: min_red_diff, min_green_diff, min_blue_diff)

Usually this solution produces very nice results and you never have to worry about palettes.
The original NES didn't have an 8bit palette, nor a fixed palette.

To begin with, the NES had between 52 and 64 colors to choose from (a few more under specialized conditions through clever hacks, plus the emphasis bits). No R/G/B palette setup here.

Graphics data (sprites and background tiles, stored as 8x8 pieces) where stored at 2 bits per pixel, however color does not yet come into the equation. Next to the graphics data you have 28 bytes of color data, representing 4 palettes for sprites and 4 palettes for tiles. Each palette lists 3 colors from the master palette of available colors, with the 4th color assumed to be transparent.

When it comes time to display a sprite on the screen, you write an entry to the sprite table (the nes could support up to 64 sprites in the OAM table, though at most 8 per scanline [you could get around this by flickering sprites]). Each sprite entry contains space for the X and Y coordinates of the sprite, whether the sprite is flipped horizontally or vertically, whether it should be drawn in front of or behind the background tiles, what graphics entry to use, and what palette to color the graphics entry with.

Because of this, a green shelled koopa moving left, and a red shelled koopa moving right, both used exactly the same bitmap in graphics memory. Only the 4 byte sprite entry differs.

To get to your specific case, "green" is not the literally color of the sprite data - it is simply saying that all pixels that are "green" should be colored with palette entry "2" (or what whatever number), with palette entry twos color determined by what palette is being used to draw that particular instance of the sprite.
Quote:Original post by Michalson
The original NES didn't have an 8bit palette, nor a fixed palette.

To begin with, the NES had between 52 and 64 colors to choose from (a few more under specialized conditions through clever hacks, plus the emphasis bits). No R/G/B palette setup here.

Graphics data (sprites and background tiles, stored as 8x8 pieces) where stored at 2 bits per pixel, however color does not yet come into the equation. Next to the graphics data you have 28 bytes of color data, representing 4 palettes for sprites and 4 palettes for tiles. Each palette lists 3 colors from the master palette of available colors, with the 4th color assumed to be transparent.

When it comes time to display a sprite on the screen, you write an entry to the sprite table (the nes could support up to 64 sprites in the OAM table, though at most 8 per scanline [you could get around this by flickering sprites]). Each sprite entry contains space for the X and Y coordinates of the sprite, whether the sprite is flipped horizontally or vertically, whether it should be drawn in front of or behind the background tiles, what graphics entry to use, and what palette to color the graphics entry with.

Because of this, a green shelled koopa moving left, and a red shelled koopa moving right, both used exactly the same bitmap in graphics memory. Only the 4 byte sprite entry differs.

To get to your specific case, "green" is not the literally color of the sprite data - it is simply saying that all pixels that are "green" should be colored with palette entry "2" (or what whatever number), with palette entry twos color determined by what palette is being used to draw that particular instance of the sprite.


interested project. i remember the Zelda project on here ,3-D Zelda or something and nehe got a C&D email/letter. dunno why though i mean why is Nintendo so afraid of someone created a 3-D zelda game?

anyway not to be OT, but i like your avatar Michaelson.. great video, love A-ha in this one.
heh
Thank you Michalson, that was very informative. Now that I know exactly how the NES accomplished this task, I see that it will be much more difficult or beyond the limitations of my skill and the game library that I'm using. In 8 bit mode, it can only display a single 256 color palette on screen at one time. If I use the current graphic data I have now, I don't see any way that I could do this. I can't grab a sprite from the bitmap and set a specific palette to it. Do you have any ideas on what I can do, or am I stuck modifying the bitmaps I have to include more color data so I can just set a global palette to it?
Quote:Original post by Michalson
The original NES didn't have an 8bit palette, nor a fixed palette.

To begin with, the NES had between 52 and 64 colors to choose from (a few more under specialized conditions through clever hacks, plus the emphasis bits). No R/G/B palette setup here.

Graphics data (sprites and background tiles, stored as 8x8 pieces) where stored at 2 bits per pixel, however color does not yet come into the equation. Next to the graphics data you have 28 bytes of color data, representing 4 palettes for sprites and 4 palettes for tiles. Each palette lists 3 colors from the master palette of available colors, with the 4th color assumed to be transparent.

When it comes time to display a sprite on the screen, you write an entry to the sprite table (the nes could support up to 64 sprites in the OAM table, though at most 8 per scanline [you could get around this by flickering sprites]). Each sprite entry contains space for the X and Y coordinates of the sprite, whether the sprite is flipped horizontally or vertically, whether it should be drawn in front of or behind the background tiles, what graphics entry to use, and what palette to color the graphics entry with.

Because of this, a green shelled koopa moving left, and a red shelled koopa moving right, both used exactly the same bitmap in graphics memory. Only the 4 byte sprite entry differs.

To get to your specific case, "green" is not the literally color of the sprite data - it is simply saying that all pixels that are "green" should be colored with palette entry "2" (or what whatever number), with palette entry twos color determined by what palette is being used to draw that particular instance of the sprite.


A good source of information for you would be old game development books, the kind of dos-based books Andre' LaMothe used to write. They've usually got a wellspring of information on 256 color, palletized modes, including stuff on manageing your pallete and old-school tricks like pallete swapping and pallete rotation. Both of these techniques are common in many games all the way through the 16bit era.

Michalson lays it out pretty well here. The NES didn't even have the luxury of 256 colors, or a single pallette! In fact, there were a total of about 28 usable colors + transparancy at any given time (4x4 background + 4x3 sprite + transparancy.) There were tricks to change the pallette during the screen draw to eek out a few more colors, but they weren't always practical depending on the graphical layout of the screen.

You'll definately learn a lot about how the NES GPU works by tring to simulate it's style, you may even want to read some of the available documents about how it functions just to help you understand what effects were in play and how they work so that you can better replicate them.

I wrote a NES/GENESIS inspired GPU emulator awhile back then ported the first level of Super Mario Brothers to it. Its amazing what you miss until you exam it on a technical level. For example, The bushes in SMB are just the tops of pallette swapped clouds. Also, because the NES had a 256 pixel wide resolution you'll notice that sprite tiles don't clip against the left edge of the screen (if any part of the tile goes off the left edge, the entire tile disappears.) This is because the sprite data only allows an 8bit position for onscreen sprites, and the designers chose to sacrifice the left edge because most games move towards the right. NES programmers had to be pretty clever to make some of those great looking old school games.

I'm actually thinking about creating a virtual console, pairing my simulated GPU with my simulated CPU now that the design of the CPU is coming together. It would be sorta like a fully documented homebrew system that would let people experience something close to retro console programming, but with a lot more official information and help. As a long term goal, I'd like to impliment it in hardware some day, since my other hobby is hardware.

throw table_exception("(? ???)? ? ???");

I had another thought/idea. If doing an exact process simulation isn't your goal you could maybe for example, load up a bitmap, make the other colored versions and mirrors of the bitmap (since memory isn't really an issue anymore), and then when you want to create the same kind of behavior, use a tag to select the correct bitmap(s).
Just an idea.
I wouldn't mind checking it out once your done. :)

This topic is closed to new replies.

Advertisement