WAD (
Where's All the Data?) is file format used by GoldSource to store textures, fonts and other data required. At this page, I will be writing about
WAD3
version of this file. For WAD2
version, look here.
For testing I will be using this testing wad file which I made myself using Wally (linking to GameBanana.com because I could not found original website).
You can use mine or use wads from Half-Life (and mods like Counter-Strike) if you have rights to do so. You can also create your own using the tool above or data from this page.
I did my testing on zhlt.wad distributed with Valve Hammer Editor (version 3.x from most websites), files from both Half-Life and Counter-Strike (which I have installed but there are other GoldSource games which you can test on) and generated files from Wally.
I found specifications on those pages (and completed them by myself):
- hlbsp.sourceforge.net
- ZDoom Wiki
- Modding Wiki
- fnky's WAD3.bt
- yuraj.ucoz.com
- Valve Developer Community
- DOOM's WAD
Main Structure
All data are Little Endian.WAD Header
Each WAD file starts with 12 bytes header.Size (bytes) | Data Type | Name | Description |
---|---|---|---|
4 |
unsigned int32 or byte[4] |
Version |
WAD3 or 0x57414433 W = 0x57 A = 0x41 D = 0x44 3 = 0x33 |
4 |
int32 or unsigned int32 |
Entries Count | Number of entries inside wad file. |
4 |
int32 or unsigned int32 |
First Entry | Offset to first entry from start of WAD file. |
typedef struct WAD_Header_t
{
uint32_t Version;
uint32_t EntriesCount;
uint32_t FirstEntry;
} WAD_Header;
WAD Entry
Each WAD entry has 32 bytes and all of them follow after the other.Size (bytes) | Data Type | Name | Description |
---|---|---|---|
4 |
int32 or unsigned int32 |
Data Offset | Offset of data (of this subfile) from start of WAD file. |
4 |
int32 or unsigned int32 |
Data Size | Size of data (of this subfile). |
4 |
int32 or unsigned int32 |
Uncompressed Data Size | Size of data (of this subfile) before compression. |
1 | byte | Data Type |
Type of this subfile. 0x40 = Decals 0x42 = Cached 0x43 = Textures 0x46 = Fonts |
1 | byte | Compressed |
Defines whether are the data compressed. 0x00 = false 0x01 = true Other values should be considered true too. |
2 | Dummy |
Dummy bytes. There is no known usage of those bytes but I had some problems with some values. 0x0001 ?
|
|
16 | byte[16] | Name |
Null-terminated string of 16 characters. Name of the subfile. |
typedef struct WAD_Entry
{
uint32_t DataOffset;
uint32_t DataSize;
uint32_t UncompressedDataSize;
uint8_t DataType;
uint8_t Compressed;
uint16_t Dummy;
uint8_t Name[16];
} WAD_Entry;
Data Types
Decals (0x40)
...Cached (0x42)
...Textures (0x43)
Textures are main thing we need from WAD.Size (bytes) | Data Type | Name | Description |
---|---|---|---|
16 | byte[16] | Name |
Null-terminated string of 16 characters. Name of the texture. First char(s): { = transparency ! = water (deforming) + = toggle buttons or animation - = random tiling ~ = emitting light |
4 |
int32 or unsigned int32 |
Width |
Width of the texture. Multiples of 16. |
4 |
int32 or unsigned int32 |
Height |
Height of the texture. Multiples of 16. |
16 |
int32[4] or unsigned int32[4] |
Mipmap Offsets |
Offset of all 4 MipMap relative to start of data of current entry. Index 0 = Width/1 X Height/1 Index 1 = Width/2 X Height/2 Index 2 = Width/4 X Height/4 Index 3 = Width/8 X Height/8 |
typedef struct WAD_Entry_Textures_t
{
uint8_t Name[16];
uint32_t Width;
uint32_t Height;
uint32_t MipMapOffsets[4];
} WAD_Entry_Textures;
Texture data are placed in this order:
- MipMap 0
- MipMap 1
- MipMap 2
- MipMap 3
- Palette
MipMap
Each MipMap iswidth*height
bytes (dimensions of the MipMap) because 1 byte represent position in palette.Palette
Palette are 256 RGB colors (1 color = 3 bytes) in order Red, Green, Blue.To support transparency, you can use last (255th) index as transparent index if you set the color to [0,0,255].
typedef struct Color_24b_t
{
uint8_t Red;
uint8_t Green;
uint8_t Blue;
} Color_24b;
Color_24b Color[256];
Fonts (0x46)
Size (bytes) | Data Type | Name | Description |
---|---|---|---|
4 |
int32 or unsigned int32 |
Width |
Width of Character Bitmap. Always 255. |
4 |
int32 or unsigned int32 |
Height | Height of Character Bitmap. |
4 |
int32 or unsigned int32 |
Row Count | Number of fixed-height character rows. |
4 |
int32 or unsigned int32 |
Row Height | Height of a row. |
1024 | Char Info | Font Info | Information about each character. |
Height * Width | byte[Height][Width] | Color Indices | Image indices. |
2 |
int16 or unsigned int16 |
Used Colors |
Number of used colors (maximum color index + 1). Maximum 256. |
3 * Used Colors | byte[Used Colors][3] | Color Palette | RGB palette data (3 bytes = RGB). |
typedef struct Color_24b_t
{
uint8_t Red;
uint8_t Green;
uint8_t Blue;
} Color_24b;
typedef struct Wad_Entry_Font_t
{
uint32_t Width;
uint32_t Height;
uint32_t Row_count;
uint32_t Row_height;
Char_Info FontInfo[1024];
uint8_t *ColorIndices;
uint16_t Used_colors;
Color_24b *ColorPalette;
} Wad_Entry_Font;
Char Info | |||
---|---|---|---|
Size (bytes) | Data Type | Name | Description |
2 |
int16 or unsigned int16 |
Start Offset | Offset to the character in data. |
2 |
int16 or unsigned int16 |
Character Width | Width of the character. |
typedef struct Char_Info_t
{
uint16_t StartOffset;
uint16_t CharacterWidth;
} Char_Info;