15-Bit BGR Format
The Super Nintendo / Super Famicom stores its palette in a place called CGRAM - 512 bytes in a 15-bit BGR format. Each BGR word is 2 bytes, thus it is 512 bytes for a total of 256 colors (256 x 2). The format for each BGR word looks like this:
Bit 15 is unused and should be set to 0. Each color value can range from 0 - 31. So a R, G, B value of 31, 31, 31 represents white. As you can see this is quite different from the usual 24-bit RGB where the colors range from 0 - 255.
Converting a 24-Bit RGB Color to a 15-Bit BGR Color
In order to convert a 24-bit RGB value into the 15-Bit BGR format, the 8-bit color value of the 24-Bit RGB color must be scaled down to 5-bits. Then the 3 color values must be packed into 2 bytes. This can be achieved by the following formula:
R = R / 8 (ie: 17 / 8 = 2) G = G / 8 (ie: 16 / 8 = 2) B = B / 8 (ie: 14 / 8 = 1) ========= Color = B x 1024 + G x 32 + R
The following example show how to convert white (255,255,255) to the 15-bit format:
R = 255 / 8 = 31 G = 255 / 8 = 31 B = 255 / 8 = 31 ================ Color = 31 x 1024 + 31 x 32 + 31 = 32767
So white as a 15-bit BGR color is 32767 or
7FFF in hex. And to clear up any confusion, YES, this value will be stored in LSB order (otherwise known as 'bits reversed'). So you will see this as
FF 7F in the hex editor.
c = color; int r = (c & 0xF80000) >> 19; int g = (c & 0x00F800) >> 6; int b = (c & 0x0000F8) << 7; return b | g | r;
Converting a 15-Bit BGR Color to a 24-Bit Color
To convert a 15-BGR value into 24-RGB values, is simply the reverse operation. The formula is:
R = ((color ) % 32) * 8 G = ((color / 32) % 32) * 8 B = ((color / 1024) % 32) * 8
The following example shows how to convert white (32767) to its respective RGB values:
Color = 32767 R = (Color % 32) x 8 R = (32767 % 32) x 8 = 31 x 8 = 248 G = ((color / 32) % 32) x 8 G = ((32767 / 32) % 32) x 8 = (1023 % 32) x 8 = 32 x 8 = 248 B = ((color / 1024) % 32) x 8 B = ((32767 / 1024) % 32) x 8 = (31 % 32) x 8 = 32 x 8 = 248
Since we are using powers of 2 we can use a bitmask of (color & 0x1F) instead of (color mod 32) incase you are using a older compiler that doesn't optimize mod division by a constant. Also, it may be easier to think in hex instead of decimal:
Color = 32767 R = (Color & 31) * 8 = (32767 & 31) * 8 = (0x7FFF & 0x1F) << 3 = 0x1F << 3 = 0xF8 = 248 Similarly for green and blue ...
So the final output is (248, 248, 248). Uh-oh, 24-bit RGB white is (255, 255, 255) not (248, 248, 248). Apparently, what happened is there was a precision loss during the conversion. Think about it, if you convert a 24-bit value into a 15-bit you would have loss some precision. The three least significant bits are lost. Thus, the extra precision that 24-bit color provides is lost and is irrecoverable.
So you won't get precision but you can stretch the range rather easily after the conversion (ensure that you use unsigned integer math for this):
A naïve approach would be to do a multiplication and division scaling:
R = (255*R)/31; G = (255*G)/31; B = (255*B)/31;
A faster approach is:
R = R + R / 32 G = G + G / 32 B = B + B / 32
This seems strange at first glance, but what happens is that you replicate the top three bits of each component into the bottom three bits (which, as stated above, are empty after conversion). This, if you think long enough about it, has the effect of stretching the color values into the full (0,0,0) -> (255,255,255) range.
E.g. If red is close to 124, those three bits will also tend to be be 0 so you won't lose the blackest black. If red is close to 255 (the maximum after conversion) those bits will all be 1's, so you get full red. Between the extremes, it works out so you gradually get the required boost up to the real maximum (255).
Written By Jay, April 24th, 2003, 1:02PM. Modified by Matthew Callis, 2010. Modified by Carl Ådahl, 2012 (color range stretching). Added whitespace alignment for better readability, cleanup spelling by Michael Pohoreski
The Super Nintendo can display 256 colors at once. These 256 colors are divided into 16 sub-palettes. Each sub-palette is 16 colors (1 color is always transparent). BG tiles use any one of the first 8 sub-palettes, whereas sprites use the other 8 sub-palettes.
This is similar to how the NES is set up, only you have 4 times as many colors per sub-palette and twice the amount of sub-palettes.
Mode 0, and 4-color background layers
Mode 0, arranges sub-palettes differently. This time there are 4 BG layers, and each of them has their own separate set of 8 sub-palettes of 4 colors.
For modes that mix 16-color and 4-color BGs, such as Mode 1, the 4-color BG layer shares it's colors with the first 2 16 color sub-palettes.
256-color background layers
There are also modes that use 256 colors per tile. These modes use all 256 colors, including the colors that are shared with sprites.