Palette Tricks by Zkman 05.09.99

The Palette is (in Screen 13 atleast) the group of 256 colors that you have to use when you're drawing tiles, making special effects, whatever. The values of those colors can be whatever you want (by value, I mean whether the color is yellow, red, a strange mix of green and orange, etc.). This article will discuss what it takes to make a good palette (using our handy-dandy palette creator or whatever you wish to use), how to speed up color changes, PSET's, etc., and palette manipulation.

Download my palette editor

Choosing your palette editor
Provided for your use here in this article is my not-so-user-friendly palette editor. It gets the job done, but you should really try and use one linked to the tile editor you use; most big tile-eds (like SpriteShop) will have a palette editor included. Here's what you need to look for:
  • Can it do gradients?

Gradients are a range of colors in increasing or decreasing magnitude. For example, say colors 1 through fifteen of you palette were grey. Color 1 would be dark grey, and color 15 almost white, with 2-14 filling in the rest of the gradient. Doing these by hand is not a good idea, and will cause you to waste hours of time. Most palettes can be done in less than an hour.

  • What format does it save to?

There are literally hundreds of ways to save a palette. Wafn's program Palpitation has over 10 different format loads, such as BSAVE, dqbString, numerical list, etc. Try and find a palette editor whose save and load make sense to you (i.e., you can pretty much understand the code), and make sure it will work with your tile editor of choice.

Other than that, you shouldn't have to worry much about your editor. Making the palette work for your game is the hard part.

Making your palette work
There are many ideas about how to optimise a 256 color palette for best viewing, but we're going to present the most common one here. First, consider divinding the 256 colors into "background" 128 and "character" 128. Use only the 128 background colors on the bg, and the 128 characters colors only on the character. Doing this will make special effects like fadeouts, etc., much easier.

You also want to figure out what colors you'll be using in your game. Unless you're making QBarbie, you won't need 15 pinks, so don't use that many! If you're doing a futuristic game, think about a lot of greys, some black, silver, etc. If you want a fantasy rpg, green and brown are important background colors.

The most important thing, though, is to do a gradient palette. Almost all of your special effects will be much easier with such. Say you want fire in your game: make a 15 color gradient starting at red and ending with yellow. When it comes to some of the special effects, this will help you a lot. Also, for "main" colors, and colors that you think might be used translucently, make a 16 color long gradient. Why? Look below...

What the hell is this RGB you talk of?
Aaah...RGB stands for Red Green Blue. Y'know the color wheel with Red, Blue, and Yellow from grade school? Computers use a similar thing, except Green is primary instead of blue. This is because computer screens work on firing light at you, instead of reflecting it like normal objects. So, if you remember that red and yellow equals orange on a color wheel, the equations below will help you find the color you're looking for.

RGB colors in VGA (256 color mode or SCREEN 13 or Mode 13h, among other names) are stored as a red number from 0 to 63, a green from 0 to 63, and a blue from 0 to 63. 0 means there is none of that color, and 63 means there is all of that color. So, an rgb of 0,0,0 would be black, 63,0,0 would be bright red, and 63,63,63 would be white.

Here are some equations to help you find a color: (When I say 1 part, I mean in relation to the other colors. For instance, 1 part green and 2 parts red means anything from 2,1,0 to 63,31,0)

  • Blue: RGB of 0,0,4 to 0,0,63
  • Green: RGB of 0,4,0 to 0,63,0
  • Red: RGB of 4,0,0 to 63,0,0
  • Grey: 1 part Red, 1 part Green, 1 part Blue
  • Yellowish Green (like Secret of Mana's grass): Green of 63, Blue 0, and Red of anything from 0 to 63
  • Brown: 2 red, 1 green, 0 blue. Red should be below 31.
  • Better Brown: 2.5 red, 1 green, 0 blue. Red should be below 49.
  • "Grassy" green: 1 red, 1 green. Red should be below 50.
  • "Water" blue: 0 red, 1 green, 2 blue.
  • Purple: 1 red, 0 green, 1 blue.
  • Bright Purple: Blue of 63, Green of 45, and red of anything from 31 to 63.
  • Orange: Red of 63, Green of 16 to 31.

Hope that's not *too* confusing ^_^.

The fast PSET you should already know

Because some of the palette tricks below can't be done fast enough without these speedups, I'll show them to you anyway. Most already know these tricks, so just skip down to the next section.

Here's the fast way of doing PSET:

DEF SEG = &HA000
POKE y * 320& + x, colour

The DEF SEG switches the segment over to the graphics buffer, and the POKE places the pixel of color "colour" at position x,y. This is up to twice as fast as PSET.

Another trick is to BSAVE the entire screen at once, so once you apply an effect, you can bring back the screen to whatever it looked like before the effect without having to redraw the screen. That's done as follows:

DEF SEG = &HA000
BSAVE "name.tmp", 0, 64000: DEF SEG

This will save the screen into a file of about 64000 bytes named "name.tmp". Of course, the name can be "goat.goa", "", or even "".

Then, after you've messed up the screen, you can get back the screen you'd saved in a millisecond with the following:

DEF SEG = &HA000
BLOAD "name.tmp", 0: DEF SEG

Just make sure you call back the same file name. These tricks will be called "Fast PSET" and "BSAVE Screen" below, so remember...or else!

Back in the day, translucency was a mind-boggling and mind-blowing event. But now, we can do it very quickly with a 256 byte array! What is translucency, you ask? It's like, you can "see thru" a color, such as the behind that dying enemy, you can sorta see the background. The picture below gives an example.


Translucent White

So how do we do translucency? Rather than waste a lot of memory on something like alpha blending, we can simply use a look-up table. Here's how it works, and why gradients are so important.

DIM SHARED transluc(256)

Create the array for the look up table

FOR i = 0 TO 255
boog = 0

Start the FOR/NEXT to go through all the colors. "boog" is just a sloppy placeholder to know if we've already got something in the array. There are better ways to code this =).

OUT &H3C7, i
rd = INP(&H3C9)
gr = INP(&H3C9)
bl = INP(&H3C9)

&H3C7 gives me access to the palette at number i (which is specified in the loop as something from 0 to 255). rd, gr, and bl are the RGB values for the said number.

IF rd >= bl AND rd >= gr THEN
transluc(i) = FIX(rd / 4)
boog = 1

Is the value for Red the highest of the three RGB's? We're trying to find the highest RGB value. If it is, we add the Red value to the array, and set boog to 1 so it's not overwritten.

IF bl >= AND boog <> 1 THEN
transluc(i) = FIX(bl / 4)
boog = 1

Is blue the highest? Then add it to the array.

ELSE IF boog <> 1 THEN transluc(i) = FIX(gr / 4)

If green is highest, add it to the array, and go to the next color.

You only need to do this once, at the start of your program. The number in the array for each color now is from 0 to 15 (16 colors, which is why I said to divide your palette's main colors into blocks of 16). So now, we need to decide what the "translucent color" will be. The picture above used white, but you can make it blue, green, brown, whatever. Here's how:

transcol = POINT(x,y)
DEF SEG = &HA000
POKE y * 320& + x, transluc(transcol + start_of_col)

So, what are we doing here? We're simply getting the color of a point we want to put the translucency over, then poke psetting from the array we created earlier a new color. So, for instance, let's say colors 30 to 45 were dark grey to white. We'd simply use 30 as "start_of_col" and there we go! Translucency for 256 bytes!

Night and Day
The final thing we'll touch on is how to quickly darken and lighten the palette (i.e., for night and day fades, or for fade-out's, etc.). This effect is even easier than the translucency. All we have to do is raise each of the RGB the desired amount (or lower them to darken) then make any values over 63 or under 0 to 63 and 0. Here's the code in action:

DEF SEG = &HA000
va = value_to_change
tr = 0
tg = 0
tb = 0
i = 0

Set up the preliminary variables in case they weren't clear. Value to change is the amount to change the variables: for instance, -20 to lower the rgb 20 (make it a lot darker) or 3 to make it a little lighter.

FOR c = 0 TO 255
OUT &H3C8, c

Get the palette register ready to go thru the colors

IF PEEK(i) + va > 63 THEN tr = 63 ELSE tr = PEEK(i) + va
IF PEEK(i + 1) + va > 63 THEN tg = 63 ELSE tg = PEEK(i) + va
IF PEEK(i + 2) + va > 63 THEN tb = 63 ELSE tb = PEEK(i) + va
IF tr <= 0 THEN tr="0"
IF tg <= 0 THEN tg="0"
IF tb <= 0 THEN tb="0"

For each RGB, increase it by said value, and if that value is over 63 or under 0, keep it at 63 or 0.

i = i + 4 NEXT DEF SEG

Increase variable "i" so the next pass will go up one color value, and then close out the FOR/NEXT.

A smooth way of doing day night is make your day/night "variable" start at 0. Every few seconds, make day/night 1 higher and pass the value to a sub with the above code. Once the number is 10 (high noon) start decreasing the number until it reaches -10 (night). A value of -10 of most palettes is almost enough to make it very hard to see! Using the above code, you can do effects like shadows, lanters, etc.

I hope you've learned enough about palette manipulation through this article, and have fun developing your own routines (both of the above were developed by me, but I'm sure they've been done before by someone). And don't forget to share your experience!