Flats

Launching the doom-gfx extractor, by
2019-01-15

Of the different image formats in Doom, flats are the simplest. Now, all images in Doom are flat, but flats are what they decided to call the textures that go on the floors and ceilings. I'll save the wall textures and sprites for another time.

Flats have predefined dimensions of 64 by 64 pixels. With 8 bits per pixel and no compression or other fancy encoding, this works out to 4096 bytes, and indeed all flats in doom.wad are 4096 bytes. The pattern is clear when looking at the entries between F_START and F_END with wad-ls:

1206 0 F_START
1207 0 F1_START
1208 4096 FLOOR0_1
1209 4096 FLOOR0_3
1210 4096 FLOOR0_6
1211 4096 FLOOR1_1
1212 4096 FLOOR1_7
1213 4096 FLOOR3_3
1214 4096 FLOOR4_1

According to the Unofficial Doom Specs,

Each flat is 4096 raw bytes, making a square 64 by 64 pixels. This is pasted onto a floor or ceiling with the same orientation as the automap would imply, i.e. the first byte is the color at the NW corner, the 64th byte (byte 63, 0x3f) is the NE corner, etc.

So, it is perfectly simple to read in a flat.

Due to the way the flats are projected into the scene in the game, they even get to have a square pixel aspect ratio. It seems unlikely that it would be anything else, but be advised that the other images have a pixel aspect ratio of 5:6. More on that when we get to those.

The only complication we have here is how to map the color indices in the image to RGB color values. We are obviously working with indexed colors here, so each byte in the flat is an index into a palette, but which palette? Looking into doom.wad, there are two likely suspects: PLAYPAL and COLORMAP. And both are indeed relevant.

PLAYPAL is 10,752 bytes large, but we are looking for 256 entries of 3 channels each, reasonably expecting one byte per channel. One palette should take 768 bytes. Well, 768 divides 10,752 perfectly in 14, and it turns out that Doom uses these different palettes for various full-screen effects. (Source: Game Engine Black Book Doom, chapter 5.13) Palette 0 is the standard. Palettes 1 through 8 are for the various intensities of red when you get hurt. Palettes 9 through 12 are for the bright flash when you pick up an item and palette 13 is for when you are wearing the radiation suit.

COLORMAP, as fits with the name, is used for mapping color indices to other indices in the same palette. This is used for mapping the graphics during painting to darker color tones. The lump is 8,704 bytes which gives room for 34 maps of 256 colors each. The 32 first maps are used for increasingly dark color tones. The value here is that this allows for a measure of computational colors even in an idexed coloring scheme. I understand that this was mostly unheard of at the time. Colormap 32 is used for the god mode effect with inverted white colors and colormap 33 is entirely black.

I've written doom-gfx to extract graphics with support for both these subtleties, and I plan to extend it with support for sprites and textures as well. Let's see what it can do:

NormalRadiation suitGod mode
FLOOR5_1 FLOOR5_1 FLOOR5_1 radiation suit FLOOR5_1 god mode
FLOOR5_2 FLOOR5_2 FLOOR5_2 radiation suit FLOOR5_2 god mode
, 2019