Almost all of the game itraconzole generate color in some of the options for RGB coding.

But these color pixels are often designed for screens that are completely different from those which usually work for emulators. In this article I will talk about the importance of emulating colors, here are a few code examples and screenshots.

The most common today kind of displays are LCD panels (LCD). They are known for having very poor black levels. The differences between TN, PVA and IPS too do not affect it.

Separate fans are playing on CRT monitors, and are becoming more commonplace OLED screens, especially on phones and tablets. But in this article we will review the LCD screens, although this technique is important for displays of any type.

Color accuracy

First important detail: most of the computers operates on a 24-bit color, which provides 8-bit granularity of colors for the channels red, green and blue. But most of the old gaming systems of the colors are not set with such precision.

For example, the Sega Genesis encodes 9-bit color, which gives 3 bits per channel.

The most naive solution would be to put 3 bits in the highest 3 bits of output, low 5 bits are left blank, but the white color gets a little gray.

000 000 000 -> 000'00000 000'00000 000'00000
111 111 111 -> 111'00000 111'00000 111'00000

If you fill them with units that are too bright becomes black.


000 000 000 -> 000'11111 000'11111 000'11111
111 111 111 -> 111'11111 111'11111 111'11111

The solution is to repeat the original bits that they filled all the output bits.


000 -> 000 000 00...
010 -> 010 010 01...
011 -> 011 011 01...
111 -> 111 111 11...

In code:

uint8 red = r << 5 | r << 2 | r >> 1
//rrr00000 | 000rrr00 | 000000rr -> rrrrrrrr

Emulation screen

Game netrosystem was not designed to work on modern LCD computer monitors. Usually home console was designed for CRT screens, and portable consoles were used much older and less accurate of the LCD panel.

In this article we will not consider the artifacts of the screens, such as the curvature of the screen, the scan lines, chromatic aberration, interframe blending, aperture grille, etc.: we focus only on the colors of the individual pixels.

Monitors PC

In monitors there is quite a wide range of colors, because only some of them are professionally calibrated to standards such as SRGB, but in General, the best we can achieve is to try to emulate the colors as if we use a properly calibrated SRGB monitor.

Emulation of CRT: Super Nintendo

The main difference between CRT screens and LCD computer monitors is greatly reduced black levels that can only be slightly compensated by using curve gamma correction:

//SNES colors are in RGB555 format, so there are 32 levels for each channel
static const uint8 gammaRamp[32] = { 0x00, 0x01, 0x03, 0x06, 0x0a, 0x0f, 0x15, 0x1c, 0x24, 0x2d, 0x37, 0x42, 0x4e, 0x5b, 0x69, 0x78, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8, 0xff,

This table is borrowed from the Overload of Super Sleuth / Kindred. It shades the lower half of the color palette, leaving the upper part unchanged.

This has a tremendous impact on the image under emulation: top shows the original, the bottom image with applied gamma correction:

LCD emulation: Game Boy Advance

Game Boy Advance had one of the worst LCD screens with completely faded flowers. Clever developers realized that greatly exaggerated the colors, you can get real equipment and a more pleasant results.

Of course, if you use these colors on a standard LCD monitor, the result will be a colorful nightmare. Fortunately, we can compensate for this by creating a fairly natural colors:

double lcdGamma = 4.0, outGamma = 2.2;
double lb = pow(B / 31.0, lcdGamma);
double lg = pow(G / 31.0, lcdGamma);
double lr = pow(R / 31.0, lcdGamma);
r = pow(( 0 * lb + 50 * lg + 255 * lr) / 255, 1 / outGamma) * (0xffff * 255 / 280);
g = pow(( 30 * lb + 230 * lg + 10 * lr) / 255, 1 / outGamma) * (0xffff * 255 / 280);
b = pow((220 * lb + 10 * lg + 50 * lr) / 255, 1 / outGamma) * (0xffff * 255 / 280);

This code snippet is written Talarubi.

A much more striking contrast compared with CRT — on top of the original, the bottom version with color correction:

LCD emulation: Game Boy Color

Screen Game Boy Color was surprisingly better in color reproduction and end the picture can only be a slight blurring of colors.

In emulators Game Boy Color is quite popular this algorithm:

R = (r * 26 + g * 4 + b * 2);
G = ( g * 24 + b * 8);
B = (r * 6 + g * 4 + b * 22);
R = min(960, R) >> 2;
G = min(960, G) >> 2;
B = min(960, B) >> 2;

Unfortunately, I don’t know who wrote the algorithm. If you know let me know so I can give credit!

As before, the original on the left, the version with color correction — right:

This example was chosen on purpose: although the original looks more alive and is more preferable if to get accustomed, it is visible checkerboard pattern around the character, which is lighter than the background.

Most likely, it was an oversight by the developers, because in a real Game
Boy Color blurred shades of white and two different shades of color merge with each other almost flawlessly.

In conclusion

There are many systems that still lack a good filter emulation colors.
They are very difficult to configure. The most important examples you can specify and Does the Neo Geo Pocket, which at the time of this writing was not good filters of approximation colors.

With the portable console is still more complicated, because they often lack the background (and sometimes the front lighting!) and there are ways to change the contrast, whereby there is no true meaning of “colors” for specific RGB values.

Particularly interesting edge case is Does Color, which is programmatically set the flag to increase the contrast of the displayed image.
While we do not know how to reliably emulate this behavior, and it is unclear if we can.

Emulation of colors is an area that requires more attention, so if you are an expert in mathematics and the analysis of colors, your help would be very useful to the emulation scene!