Raw CGA Data
This page describes a number of generic arrangements for storing CGA graphics data. The graphics in many CGA games are stored based on one of these formats.
Linear CGA data
For CGA tiles, one byte stores the color information for four pixels. Since the tile has 64 pixels (8×8), each tile takes up 16 bytes.
There are four possible combinations of 2 bits (2^2). The actual colors for each pixel depend on the active CGA palette, of which there are three basic ones. See wp:Color Graphics Adapter for details. Every game can use the four color palette differently. Catacomb uses color palette 1 with high intensity.
This data represents one tile from Catacomb:
FF FF FF FF FD 7F F6 9F F6 9F FD 7F FF FF FF FF
Expanded into bits for an 8×8 tile:
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 01 01 11 11 11 11 11 01 10 10 01 11 11 11 11 01 10 10 01 11 11 11 11 11 01 01 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
With color palette 1i, each pair of bits represents a different color:
Resulting Image (actual size):
Resulting Image (8× the size):
Interlaced CGA Data
|Line (Y)||Plane||Column (X)|
This arrangement stores the image data in two halves - even lines and odd lines.
It is essentially two black-and-white (1bpp) images one after the other, each half the height of the total picture. The first image is drawn on lines 0, 2, 4, etc. and the second image is drawn on lines 1, 3, 5, etc. to produce the final picture. Each row of data is in the same arrangement as #Linear CGA data above.
A 16×8 image in this arrangement is described in the table on the right. The byte at index 00 contains the first eight-pixels in the image, and the byte at offset 15 contains the second four pixels on the fourth line.
|0x0000||0x1F40||Pixel data (even lines)|
|0x2000||0x1F40||Pixel data (odd lines)|
Many full screen CGA images store their data in interlaced format, so that they can be loaded directly into video memory without any additional processing. In some of these cases however, the data is loaded in one operation for the entire image rather than two operations (one per plane.)
This is significant because in 320×200 mode, each plane occupies 8000 bytes of memory, leading to 16000 bytes for the entire image. However because the planes are aligned in CGA memory, the second plane actually starts at offset 8192 into memory, not at offset 8000.
This means that file formats which load an image in a single operation will have 192 bytes of padding between the planes (and possibly 192 bytes after the last plane), which should be ignored when processing the image.
A quick way to tell is to look at the image size. If it is 16000 bytes, it contains two planes with no padding, and if it is 16192 or 16384 bytes then it contains padding between planes.
The actual RGB values that correspond to each colour value depend on the palette in use by the game. This table lists the RGB values for all the CGA palettes.
|0||Application-specific (default #000000)|
For more detailed information, see the CGA Palette article.
This FreeBASIC program will render a full-screen CGA graphic which uses linear encoding.
' Renders a full-screen CGA graphic using linear encoding. ' Put the full file path to the necessary graphic here. Open "H:\DOS\Ultima\castle.4" For Binary As #1 ' Choose the appropriate CGA color palette. ' 0 - Green, Red, Brown ' 1 - Cyan, Magenta, Gray ' 2 - Lt. Green, Lt. Red, Yellow ' 3 - Lt. Cyan, Lt. Magenta, White Dim As UByte CGAPalette = 1 Screen 1 Color 0, CGAPalette Dim As UByte X Dim As UByte Y Dim As UByte Pixels Dim As UByte ColorBlock Dim As UByte Pixel Dim As UByte Offset Y = 0 Do For X = 0 To 79 Get #1, , Pixels ColorBlock = 7 For Offset = 0 To 3 If Bit(Pixels, ColorBlock) = -1 Then If Bit(Pixels, ColorBlock - 1) = -1 Then Pixel = 3 Else Pixel = 2 End If Else If Bit(Pixels, ColorBlock - 1) = -1 Then Pixel = 1 Else Pixel = 0 End If End If PSet(Offset + (X * 4), Y), Pixel ColorBlock = ColorBlock - 2 Next Offset Next X ' The CGA image is interlaced, so we skip a line as we read. When we ' reach the bottom of the screen, we will wrap back up to the top. Y = Y + 2 If Y = 200 Then ' When we reach the end of the first pass, there are 192 bytes ' (768 pixels worth) of data that isn't displayed. This is just ' filler to match the size of the CGA card's memory. The ' following code reads the data and throws it away before ' back up to line 1 to draw all the odd lines. For Y = 0 To 191 Get #1, , Pixels Next Y Y = 1 End If Loop Until Y = 201 Close #1 Sleep