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:
Normal | Radiation suit | God mode | |
FLOOR5_1 | |||
FLOOR5_2 |