Hi there. I've dedicated this post of the series to the mode 13h palette. In my opinion, the mode deserves to be explored in its own. Or maybe, I'm just being nostalgic and therefore biased when it comes to mode 13h. I'll handle the topics in this post by viewing some files using the BMP Viewer, I mentioned in my previous post. I'll additionally highlight some more details about the palette here.
First of all, almost everything I explained so far about the palette of other display modes in the first article also applies to mode 13h. To summarize: The VGA DAC can display only 16 of 262 144 colors in text mode as well as mode 12h, and 256 of them in mode 13h simultaneously. Each palette color has an index and an 18-bit RGB value consisting of 6-bit per channel. After the palette index is written to the port 3C8h, the color values of each channel are written to the port 3C9h sequentially with byte-length. Here is the loop of the BMP Viewer, which loads the palette.
outportb(0x3C8, i); // Palette index
outportb(0x3C9, VGApalette.color[i].B >> 2); // Blue
outportb(0x3C9, VGApalette.color[i].G >> 2); // Green
outportb(0x3C9, VGApalette.color[i].R >> 2); // Red
}
The palette of mode 13h is simpler than other modes because, even though it is still possible to assign values to attribute register in this mode, there is no point in assigning a color to another index which can already be displayed on the screen, since all colors in the DAC (256 colors) can be displayed anyway without any trick. Therefore the attribute register has no use in this mode.
As a base example, I'll use the three parrots image from the VGA article on Wikipedia. As this image contains all 256 colors, it's quite useful for demonstrating VGA's capabilities.
![]() |
| Source: Wikipedia [2] |
I first resized this image to 320x200. The original image is 1280x960, therefore the aspect ratio changed, but apart from that, I did not change anything on the existing colors or the palette. Here is a screenshot of the image from DOSBox.
There is no noticeable difference when comparing the two images visually. To show the effect of the palette better, let's comment out the setPalette function on line 208, and see how it would look with the default mode 13h palette:
As you can clearly see, the absence of the palette makes a significant difference.
Back in the 90s, when RAM in computers was measured in MBs and therefore software optimization was the primary concern, I wondered, "(How) Can I rearrange the colors in the image palette to fit the default VGA palette?". That way, I could get rid of both setPalette(...) function, which is around 400 bytes, and the palette, which is 1 KB per image. I'll briefly explain the theory behind this, using the image below, which I cropped and scaled a bit down from the original [1], which has 97 328 colors.
The problem of creating a palette by decreasing the number of colors had been studied long before the question above even came to my mind. First check point is the median cut algorithm from 1982. In this algorithm, the median of all colors in the color space is calculated, and it is assumed that this color could represent all others with the least average error. Depending on the target color depth, the number of colors is decreased to a 2n (usually 16 or 256) colors by recursively calculating the medians of the color space. However, since this algorithm ignores small color deviations in images with a wide range of colors, it causes unnatural color islands. To show this effect, I decreased the number of colors to 16 using median cut (below). The color islands in the background and on the birds belly are clearly noticeable.
For this reason, techniques such as dithering and/or error diffusion are applied to insert pixels with similar colors from the palette, thus adding a small amount of noise to large color islands. This results in an image that is less unpleasant to the human eye.
![]() |
| Good old days 🥲 |
Although median cut is only used for decreasing the number of colors, error diffusion is also used in palette transformations. I won't go into the details of the algorithms in this post. I'll save them for the next post, if there is enough space. Back in the days, I tried and learned these conversions using Paint Shop Pro (PSP) and got quite nice results. Below, I put the image, whose palette I converted, at the top and the original image at the bottom for comparison. Although there are some shiny, flashy colors on the green bird and the road in the background due to error diffusion, the result is still not too bad.
When I display the converted image in DOSBox without setPalette(...):
I also displayed this image without modifying the viewer, and when I overlapped both in GIMP and subtracted the layers, I was left with a black image as expected.
To convert the palette, as I explained in my previous post, first I sent the palette index via port 0x3C7, read the color values from port 0x3C9, then multiplied them by four, and wrote them to a file in JASC (PSP) format. This format is a simple text file consisting of a three line header followed by R, G, B values separated by spaces. And the good thing is, GIMP can also read this format.
PRINT #1, "JASC-PAL"
PRINT #1, "0100"
PRINT #1, "256"
SCREEN 13
FOR I% = 0 TO 255
OUT &H3C7, I%
R% = INP(&H3C9)
G% = INP(&H3C9)
B% = INP(&H3C9)
PRINT #1, LTRIM$(STR$(R% * 4));
PRINT #1, RTRIM$(STR$(G% * 4));
PRINT #1, RTRIM$(STR$(B% * 4))
NEXT I%
CLOSE #1
I downloaded Paint Shop Pro from oldversion.com and could run it with Wine under Linux. I opened the file I wanted to get its palette converted and went to Colors -> Load Palette. Here, I loaded the 13.PAL, I had created in the previous step and selected "Error diffusion dithering" as the conversion algorithm. You can try out different algorithms and compare their results here.

In GIMP, you first need to open Palettes window (Windows -> Dockable Dialogs -> Palettes), then right click on an empty area and import 13.PAL. Then I opened the image, I wanted to convert. In the window, that appeared when I selected Image -> Mode -> Indexed, I checked "Use custom palette" and selected 13.PAL from the list below. No matter which dithering method I chose, GIMP unfortunately couldn't do this conversion any better than PSP.
[1]: https://commons.wikimedia.org/wiki/File:Perched_blue_and_orange_bird_%28Unsplash%29.jpg
[2]: https://en.wikipedia.org/wiki/Video_Graphics_Array#/media/File:Birds_VGA256.png










