Colors and Palettes
We are covering use of colors and customizing Palette in several tutorials because we use them regularly but in order to have a complete picture we will go in some more details in this post.
Let’s summarize the basics first.
The Commander X16 VERA chip is responsible for all the graphics including colors and it supports 256 colors out of the total of 4096 possibilities. Each color is defined from three components Red, Green and Blue and for each we have half byte or 4 bits (also referred to as a nibble) so 16 possible values from 0 to 15. Therefore 16*16*16 = 4096.
After booting the computer (or starting up the emulator) we get 256 predefined colors or default palette which we can customize in any way we want.
The default palette contains a pretty good selection of colors and is usable for many situations. It does lack some colors, for example fully saturated yellow (Red=15,Green=15,Blue=0).
We mentioned that the palette is built out of 4096 possible colors. Below are all the colors that are generated directly in Commander X16 emulator but because we can only show 256 at one time I combined them into one image:
Source code to display all the colors is below. Because we can only show 256 at one time we have to redefine the palette 16 times:
Define custom colors
We can customize colors in the palette very easily. Unfortunately Commander X16 doesn’t allow us to put the palette to any arbitrary location in the memory but it has to be at an exact predefined space in the Video RAM. That location starts at $1FA00. Each color required two bytes (actually one byte and half or 12 bits). First byte contains Green component in high nibble and Blue component in low nibble. Red component is in the low nibble of the second byte. High nibble of second byte is not used - unfortunately we can’t define transparency (usually marked A or Alpha) so that space is wasted. With 256 colors in the palette that means that 512 bytes are needed so in Hexadecimal that means space from $1FA00 to $1FBFF.
The formula to define colors from BASIC is therefore:
VPOKE 1,$FA00+I*2,G*16+B
VPOKE 1,$FA00+I*2+1,R
Where of course I is color index from 0 to 255 and R,G and B are color components with values within 0-15 range.
As an example let’s redefine the mudded yellow color from Commodore 64 palette into clean, fully vibrant yellow.
We know that color index for yellow is 7 and that we have to set Red and Green to maximum and Blue to zero:
VPOKE 1,$FA00+7*2,$F0
VPOKE 1,$FA00+7*2+1,$0F
It is that simple!
Using colors
Commander X16 supports several video modes and hardware sprites that both support different numbers of colors at our disposal. I describe the use and specific of each video mode in separate posts as well as pretty detailed description of sprite usage. Let’s now focus just on colors.
Sprite Colors
Each Sprite can be in either 4bpp or 8bpp mode.
4bpp Sprites
4bpp Sprites use only 4 bits for each pixel so we have 15 colors plus transparent available to us.
Color 0 or in binary %0000 is always transparent. Other colors have values from 1-15 or
In binary %0001 to %1111.
If we look at the Sprite registers we can see that register 8 (or offset 7) reserves 4 lower bits for Palette Offset. You can probably already see how everything comes together nicely.
Four bits per pixel plus 4 bits for palette offset together make 8 bits so we can address (almost) all the colors. To determine what colors we can use in a sprite we can look at the default palette again:
The four bits of palette offset is actually top nibble to address the color. In the above example if the palette offset is $A0 we have to store 10 (or $A or %1010) to the Sprite Palette Offset nibble and then we have colors in that row available for that particular sprite.
The only exception is the first column. Those colors are not available because remember the color 0 is always transparent.
8bpp Sprites
8bpp mode allows us to use every one of 255 colors in the palette except color 0 within a single sprite.
However be aware that Palette Offset still affects the appearance.
If Offset is 0 then each pixel directly translates to color in palette. For example 1 (%00000001) is color 1 from the palette, 2 (%00000010) is color 2 and so on. But if we put 1 into palette offset all colors will be shifted by 16 meaning that 1 will actually be color 17 from palette, 2 will be color 18 from palette and so on.
The colors then wrap around the palette. For example if a pixel in sprite has value $F8 it would show as bright pink from the bottom row of palette above, however if we put 1 in Palette Offset register of sprite definition the color will change to $08 - Commodore Orange, and so on.
This behavior is different from 8bpp tile mode where colors above 15 do not get affected by the Palette Offset value.
Screen colors
Commander X16 supports two layers and color depth is determined per layer.
For Layer 0 that is register 13 at $9F2D of CPU RAM and for Layer 1 it is register 20 at $9F34 of CPU RAM.
Lower two bits have following values:
- 00 - 1 bit per pixel
- 01 - 2 bits per pixel
- 10 - 4 bits per pixel
- 11 - 8 bits per pixel
1bpp Modes
We have two variations of 1bpp mode. 16 color and 256 color one.
More details about these two modes are described here and use of colors in these two modes is very straight forward.
In 16 color mode we have 4 bits for foreground and 4 bits for background so only the first 16 colors from the palette are accessible.
The 256 color mode also uses one byte to define the color but only foreground, however we can pick any of the colors from the palette except color 0, which will always be transparent regardless how we define it.
2bpp/4bpp/8bpp Modes
These modes use a similar approach to the Sprites.
Each tile (character) uses a 4 high bits in attribute for the Palette index which is added as a high nibble to the values of pixels per tile.
2bpp Tiles
With only two bits we can’t address all the colors from the palette. When we combine 4 bits from the palette offset that go to high nibble and 2 bits from the tile definition that go to lowest two bits we clearly only have 6 bits and the remaining two bits are filled with zeros.
Below picture illustrates which of the colors from the default palette we can address:
As always the first color is always transparent so we have three remaining values 01,10 and 11 for colors in columns 2,3 and 4.
If like in above example we use 10 (A in hexadecimal) then the three colors available for our tile are teal shades.
If we plan to use this mode in our programs we have to define our palette very carefully and keep the needed colors in those three columns of the palette.
4bpp Tiles
This mode is very similar to the previous but provides much more freedom because with 4 bits we can address almost all colors except the first column. it is also identical to 4bpp mode for Sprites so we can use the same illustration:
Now each pixel in a tile can have 15 colors plus transparency. This luxury of course comes with a price. Each tile takes twice as much space as the 2bpp tiles. For example 8x8 pixel tile requires 32 bytes and if we want to use a maximum possible 1024 tiles it would take 32K bytes of VRAM which is not too bad considering that we have 128K available.
This is probably the most usable mode for games.
8bpp Tiles
Most colorful tiles use full byte for each pixel so we can easily address the whole palette. The colors are in principle very easy to determine with just few exceptions:
- Color 0 is again transparent, so binary value of %00000000 will simply show the color of the layer below (if there is one)
- Colors 1-15 will be affected by Palette Offset in screen data in the same way as in above example for 4bpp mode which makes sense because they only use 4 lower bits anyway and are simply complemented by top 4 bits from the offset.
- Colors 16-255 are not affected by the Palette Offset and are taken directly from the palette. Note that this is different from the behavior for the 8bpp sprites.
Background/Transparency
We talked about transparent color a lot so what do we actually see when there is no color defined?
Commander X16 video chip VERA supports 2 layers.
Layer 1 is always above Layer 0 so if we use transparent color on layer 1 then we will see whatever is behind on Layer 0.
If we use transparency on Layer 0 then we will see black - at least in this version of Emulator R.38 we can’t change the default background.
In addition to layers of screen we can also define the position of sprites relative to both layers. The depth Z (bit 2 and 3 of Register 6 of sprite definition) can have values
- 00 - disabled
- 01 - behind layer 0 and above black background
- 10 - between layers 1 and 0
- 11 - above layer 1
Sprite with a lower number is above a sprite with a higher number - so sprite 0 will always be above sprite 1 even though they can be set differently relative to layers.
Since both layers can be scrolled independently and we can put sprites above, between and under layers we can create some very nice and relatively “cheap” parallax effects with that.
Happy coloring but remember when using colors sometimes less is more!
Comments
Post a Comment