Dangerous Dave EGA Tileset Format - sopoforic/cgrr-dangerousdave GitHub Wiki

Dangerous Dave EGA Tileset Format

The EGA tiles are stored uncompressed in EGADAVE.DAV, which has the following format. Integers are little-endian.

Overall Format:

Addr. Type Description
0x00 Uint32 count
0x04 Uint32[count] offsets
0x648 Other tiles

At 0x00, count tells how many tiles are in the file. It should be 401.

Beginning at 0x04, offsets is a sequence of count 32-bit unsigned integers. Each is the offset of the start of a tile.

Image Chunk Format (16x16 tile):

Addr. Type Description
0x00 Other image

Image Chunk Format (other tiles, relative offsets):

Addr. Type Description
0x00 Uint16 width
0x02 Uint16 height
0x04 Other image

Beginning at 0x648 are the tile chunks. If the length of a tile's chunk is 128, the tile is 16x16 pixels, and the entire chunk is the image data. If not, then the chunk will begin with a four byte header, consisting of two 16-bit unsigned integers, representing first the width and then the height of the tile. The remaining bytes are the image data.

If the width of the tile is not a multiple of 8, it will be stored in EGADAVE.DAV with blank columns at the right, to round up its width to a multiple of 8. For example, a tile with any width from 9 to 16 pixels will be 16 pixels wide in EGADAVE.DAV, and its 'true' width will be listed in its header.

The non-16x16 tiles have one row of 'junk' image data (often black or dark cyan) that is not displayed in-game. So a tile that should be 9 rows high will have 10 rows of image data. Just throw the last row away if you want the image as it is displayed in-game. I don't know what it's for.

The image data contains the EGA color of each pixel, separated by color channel (intensity, red, green, blue), one row at a time. Each byte of the image data corresponds to 8 pixels of one channel of the image. Therefore, a single row of a 16 pixel wide image is represented by 8 bytes in the file--half a byte per pixel.

Format
Row 1 Channel I
Row 1 Channel R
Row 1 Channel G
Row 1 Channel B
Row 2 Channel I
Row 2 Channel R
. . .

For each row, if the highest bit is 1, that channel is 'on' for the first pixel; if the second-highest bit is 1, that channel is on for the second pixel, and so on.

EGA to RGB conversion table:

| (R, G, B) | Color

-----|--------------------|----------- 0 | (0x00, 0x00, 0x00) | Black 1 | (0x00, 0x00, 0xAA) | Dark Blue 2 | (0x00, 0xAA, 0x00) | Dark Green 3 | (0x00, 0xAA, 0xAA) | Dark Cyan 4 | (0xAA, 0x00, 0x00) | Dark Red 5 | (0xAA, 0x00, 0xAA) | Purple 6 | (0xAA, 0xAA, 0x00) | Brown 7 | (0xAA, 0xAA, 0xAA) | Grey 8 | (0x55, 0x55, 0x55) | Dark Grey 9 | (0x55, 0x55, 0xFF) | Blue 10 | (0x55, 0xFF, 0x55) | Green 11 | (0x55, 0xFF, 0xFF) | Cyan 12 | (0xFF, 0x55, 0x55) | Red 13 | (0xFF, 0x55, 0xFF) | Pink 14 | (0xFF, 0xFF, 0x55) | Yellow 15 | (0xFF, 0xFF, 0xFF) | White

You can see that the effect of the intensity channel is to switch between the 'dark' (when intensity is off) and 'light' (when intensity is on) versions of the colors.

An example 16-pixel row:

0x00 0x00 0xFE 0xEF 0xFE 0xEF 0x02 0x21

Each two bytes represent one channel (intensity, red, green, blue) of that row. To understand how they contribute to the pixels' colors, look at the binary form of those numbers, arranged two bytes per row:

0123456789ABCDEF column
0000000000000000 intensity
1111111011101111 red
1111111011101111 green
0000001000100001 blue

Each pixel in this row corresponds to one column. Columns 0-5 each have red and green 'on' and the other channels off. So the first six pixels have the second and third bits on, for color number 0110b = 6. Looking that up in the table, we see that Color #6 is Brown.

Column 6 additionally has the blue channel on, so it has color 0111b = 7. If we look it up, we find that Color #7 is Grey.

By performing this conversion on the entire data portion of the image chunk, the color values for every pixel can be determined. Once the pixel colors have all been set, crop the image to the real width, if necessary.

Credits: I could not have done this without the prior work of Levellass and K1n9 Duk3 on the DOS Game Modding Wiki. Thanks to both of them for working on this format and making their findings available.