This page hosts a formal specification of .wad file format of id Tech 1 using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
All parsing code for C++98/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.
For C++, the easiest way is to clone the runtime library sources and build them along with your project.
Using Kaitai Struct in C++/STL usually consists of 3 steps.
std::istream
). One can open local file for that, or use existing std::string
or char*
buffer.
#include <fstream>
std::ifstream is("path/to/local/file.wad", std::ifstream::binary);
#include <sstream>
std::istringstream is(str);
#include <sstream>
const char buf[] = { ... };
std::string str(buf, sizeof buf);
std::istringstream is(str);
#include "kaitai/kaitaistream.h"
kaitai::kstream ks(&is);
doom_wad_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.num_index_entries() // => Number of entries in the lump index
#ifndef DOOM_WAD_H_
#define DOOM_WAD_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include <vector>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
class doom_wad_t : public kaitai::kstruct {
public:
class sectors_t;
class vertex_t;
class texture12_t;
class linedef_t;
class pnames_t;
class thing_t;
class sector_t;
class vertexes_t;
class sidedef_t;
class things_t;
class linedefs_t;
class index_entry_t;
class sidedefs_t;
class blockmap_t;
doom_wad_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~doom_wad_t();
class sectors_t : public kaitai::kstruct {
public:
sectors_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~sectors_t();
private:
std::vector<sector_t*>* m_entries;
doom_wad_t* m__root;
doom_wad_t::index_entry_t* m__parent;
public:
std::vector<sector_t*>* entries() const { return m_entries; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::index_entry_t* _parent() const { return m__parent; }
};
class vertex_t : public kaitai::kstruct {
public:
vertex_t(kaitai::kstream* p__io, doom_wad_t::vertexes_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~vertex_t();
private:
int16_t m_x;
int16_t m_y;
doom_wad_t* m__root;
doom_wad_t::vertexes_t* m__parent;
public:
int16_t x() const { return m_x; }
int16_t y() const { return m_y; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::vertexes_t* _parent() const { return m__parent; }
};
/**
* Used for TEXTURE1 and TEXTURE2 lumps, which designate how to
* combine wall patches to make wall textures. This essentially
* provides a very simple form of image compression, allowing
* certain elements ("patches") to be reused / recombined on
* different textures for more variety in the game.
* \sa https://doom.fandom.com/wiki/TEXTURE1_and_TEXTURE2 Source
*/
class texture12_t : public kaitai::kstruct {
public:
class texture_index_t;
class texture_body_t;
class patch_t;
texture12_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~texture12_t();
class texture_index_t : public kaitai::kstruct {
public:
texture_index_t(kaitai::kstream* p__io, doom_wad_t::texture12_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~texture_index_t();
private:
bool f_body;
texture_body_t* m_body;
public:
texture_body_t* body();
private:
int32_t m_offset;
doom_wad_t* m__root;
doom_wad_t::texture12_t* m__parent;
public:
int32_t offset() const { return m_offset; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::texture12_t* _parent() const { return m__parent; }
};
class texture_body_t : public kaitai::kstruct {
public:
texture_body_t(kaitai::kstream* p__io, doom_wad_t::texture12_t::texture_index_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~texture_body_t();
private:
std::string m_name;
uint32_t m_masked;
uint16_t m_width;
uint16_t m_height;
uint32_t m_column_directory;
uint16_t m_num_patches;
std::vector<patch_t*>* m_patches;
doom_wad_t* m__root;
doom_wad_t::texture12_t::texture_index_t* m__parent;
public:
/**
* Name of a texture, only `A-Z`, `0-9`, `[]_-` are valid
*/
std::string name() const { return m_name; }
uint32_t masked() const { return m_masked; }
uint16_t width() const { return m_width; }
uint16_t height() const { return m_height; }
/**
* Obsolete, ignored by all DOOM versions
*/
uint32_t column_directory() const { return m_column_directory; }
/**
* Number of patches that are used in a texture
*/
uint16_t num_patches() const { return m_num_patches; }
std::vector<patch_t*>* patches() const { return m_patches; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::texture12_t::texture_index_t* _parent() const { return m__parent; }
};
class patch_t : public kaitai::kstruct {
public:
patch_t(kaitai::kstream* p__io, doom_wad_t::texture12_t::texture_body_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~patch_t();
private:
int16_t m_origin_x;
int16_t m_origin_y;
uint16_t m_patch_id;
uint16_t m_step_dir;
uint16_t m_colormap;
doom_wad_t* m__root;
doom_wad_t::texture12_t::texture_body_t* m__parent;
public:
/**
* X offset to draw a patch at (pixels from left boundary of a texture)
*/
int16_t origin_x() const { return m_origin_x; }
/**
* Y offset to draw a patch at (pixels from upper boundary of a texture)
*/
int16_t origin_y() const { return m_origin_y; }
/**
* Identifier of a patch (as listed in PNAMES lump) to draw
*/
uint16_t patch_id() const { return m_patch_id; }
uint16_t step_dir() const { return m_step_dir; }
uint16_t colormap() const { return m_colormap; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::texture12_t::texture_body_t* _parent() const { return m__parent; }
};
private:
int32_t m_num_textures;
std::vector<texture_index_t*>* m_textures;
doom_wad_t* m__root;
doom_wad_t::index_entry_t* m__parent;
public:
/**
* Number of wall textures
*/
int32_t num_textures() const { return m_num_textures; }
std::vector<texture_index_t*>* textures() const { return m_textures; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::index_entry_t* _parent() const { return m__parent; }
};
class linedef_t : public kaitai::kstruct {
public:
linedef_t(kaitai::kstream* p__io, doom_wad_t::linedefs_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~linedef_t();
private:
uint16_t m_vertex_start_idx;
uint16_t m_vertex_end_idx;
uint16_t m_flags;
uint16_t m_line_type;
uint16_t m_sector_tag;
uint16_t m_sidedef_right_idx;
uint16_t m_sidedef_left_idx;
doom_wad_t* m__root;
doom_wad_t::linedefs_t* m__parent;
public:
uint16_t vertex_start_idx() const { return m_vertex_start_idx; }
uint16_t vertex_end_idx() const { return m_vertex_end_idx; }
uint16_t flags() const { return m_flags; }
uint16_t line_type() const { return m_line_type; }
uint16_t sector_tag() const { return m_sector_tag; }
uint16_t sidedef_right_idx() const { return m_sidedef_right_idx; }
uint16_t sidedef_left_idx() const { return m_sidedef_left_idx; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::linedefs_t* _parent() const { return m__parent; }
};
/**
* \sa https://doom.fandom.com/wiki/PNAMES Source
*/
class pnames_t : public kaitai::kstruct {
public:
pnames_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~pnames_t();
private:
uint32_t m_num_patches;
std::vector<std::string>* m_names;
doom_wad_t* m__root;
doom_wad_t::index_entry_t* m__parent;
public:
/**
* Number of patches registered in this global game directory
*/
uint32_t num_patches() const { return m_num_patches; }
std::vector<std::string>* names() const { return m_names; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::index_entry_t* _parent() const { return m__parent; }
};
class thing_t : public kaitai::kstruct {
public:
thing_t(kaitai::kstream* p__io, doom_wad_t::things_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~thing_t();
private:
int16_t m_x;
int16_t m_y;
uint16_t m_angle;
uint16_t m_type;
uint16_t m_flags;
doom_wad_t* m__root;
doom_wad_t::things_t* m__parent;
public:
int16_t x() const { return m_x; }
int16_t y() const { return m_y; }
uint16_t angle() const { return m_angle; }
uint16_t type() const { return m_type; }
uint16_t flags() const { return m_flags; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::things_t* _parent() const { return m__parent; }
};
class sector_t : public kaitai::kstruct {
public:
enum special_sector_t {
SPECIAL_SECTOR_NORMAL = 0,
SPECIAL_SECTOR_D_LIGHT_FLICKER = 1,
SPECIAL_SECTOR_D_LIGHT_STROBE_FAST = 2,
SPECIAL_SECTOR_D_LIGHT_STROBE_SLOW = 3,
SPECIAL_SECTOR_D_LIGHT_STROBE_HURT = 4,
SPECIAL_SECTOR_D_DAMAGE_HELLSLIME = 5,
SPECIAL_SECTOR_D_DAMAGE_NUKAGE = 7,
SPECIAL_SECTOR_D_LIGHT_GLOW = 8,
SPECIAL_SECTOR_SECRET = 9,
SPECIAL_SECTOR_D_SECTOR_DOOR_CLOSE_IN_30 = 10,
SPECIAL_SECTOR_D_DAMAGE_END = 11,
SPECIAL_SECTOR_D_LIGHT_STROBE_SLOW_SYNC = 12,
SPECIAL_SECTOR_D_LIGHT_STROBE_FAST_SYNC = 13,
SPECIAL_SECTOR_D_SECTOR_DOOR_RAISE_IN_5_MINS = 14,
SPECIAL_SECTOR_D_FRICTION_LOW = 15,
SPECIAL_SECTOR_D_DAMAGE_SUPER_HELLSLIME = 16,
SPECIAL_SECTOR_D_LIGHT_FIRE_FLICKER = 17,
SPECIAL_SECTOR_D_DAMAGE_LAVA_WIMPY = 18,
SPECIAL_SECTOR_D_DAMAGE_LAVA_HEFTY = 19,
SPECIAL_SECTOR_D_SCROLL_EAST_LAVA_DAMAGE = 20,
SPECIAL_SECTOR_LIGHT_PHASED = 21,
SPECIAL_SECTOR_LIGHT_SEQUENCE_START = 22,
SPECIAL_SECTOR_LIGHT_SEQUENCE_SPECIAL1 = 23,
SPECIAL_SECTOR_LIGHT_SEQUENCE_SPECIAL2 = 24
};
sector_t(kaitai::kstream* p__io, doom_wad_t::sectors_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~sector_t();
private:
int16_t m_floor_z;
int16_t m_ceil_z;
std::string m_floor_flat;
std::string m_ceil_flat;
int16_t m_light;
special_sector_t m_special_type;
uint16_t m_tag;
doom_wad_t* m__root;
doom_wad_t::sectors_t* m__parent;
public:
int16_t floor_z() const { return m_floor_z; }
int16_t ceil_z() const { return m_ceil_z; }
std::string floor_flat() const { return m_floor_flat; }
std::string ceil_flat() const { return m_ceil_flat; }
/**
* Light level of the sector [0..255]. Original engine uses
* COLORMAP to render lighting, so only 32 actual levels are
* available (i.e. 0..7, 8..15, etc).
*/
int16_t light() const { return m_light; }
special_sector_t special_type() const { return m_special_type; }
/**
* Tag number. When the linedef with the same tag number is
* activated, some effect will be triggered in this sector.
*/
uint16_t tag() const { return m_tag; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::sectors_t* _parent() const { return m__parent; }
};
class vertexes_t : public kaitai::kstruct {
public:
vertexes_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~vertexes_t();
private:
std::vector<vertex_t*>* m_entries;
doom_wad_t* m__root;
doom_wad_t::index_entry_t* m__parent;
public:
std::vector<vertex_t*>* entries() const { return m_entries; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::index_entry_t* _parent() const { return m__parent; }
};
class sidedef_t : public kaitai::kstruct {
public:
sidedef_t(kaitai::kstream* p__io, doom_wad_t::sidedefs_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~sidedef_t();
private:
int16_t m_offset_x;
int16_t m_offset_y;
std::string m_upper_texture_name;
std::string m_lower_texture_name;
std::string m_normal_texture_name;
int16_t m_sector_id;
doom_wad_t* m__root;
doom_wad_t::sidedefs_t* m__parent;
public:
int16_t offset_x() const { return m_offset_x; }
int16_t offset_y() const { return m_offset_y; }
std::string upper_texture_name() const { return m_upper_texture_name; }
std::string lower_texture_name() const { return m_lower_texture_name; }
std::string normal_texture_name() const { return m_normal_texture_name; }
int16_t sector_id() const { return m_sector_id; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::sidedefs_t* _parent() const { return m__parent; }
};
class things_t : public kaitai::kstruct {
public:
things_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~things_t();
private:
std::vector<thing_t*>* m_entries;
doom_wad_t* m__root;
doom_wad_t::index_entry_t* m__parent;
public:
std::vector<thing_t*>* entries() const { return m_entries; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::index_entry_t* _parent() const { return m__parent; }
};
class linedefs_t : public kaitai::kstruct {
public:
linedefs_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~linedefs_t();
private:
std::vector<linedef_t*>* m_entries;
doom_wad_t* m__root;
doom_wad_t::index_entry_t* m__parent;
public:
std::vector<linedef_t*>* entries() const { return m_entries; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::index_entry_t* _parent() const { return m__parent; }
};
class index_entry_t : public kaitai::kstruct {
public:
index_entry_t(kaitai::kstream* p__io, doom_wad_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~index_entry_t();
private:
bool f_contents;
kaitai::kstruct* m_contents;
bool n_contents;
public:
bool _is_null_contents() { contents(); return n_contents; };
private:
public:
kaitai::kstruct* contents();
private:
int32_t m_offset;
int32_t m_size;
std::string m_name;
doom_wad_t* m__root;
doom_wad_t* m__parent;
std::string m__raw_contents;
kaitai::kstream* m__io__raw_contents;
public:
int32_t offset() const { return m_offset; }
int32_t size() const { return m_size; }
std::string name() const { return m_name; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t* _parent() const { return m__parent; }
std::string _raw_contents() const { return m__raw_contents; }
kaitai::kstream* _io__raw_contents() const { return m__io__raw_contents; }
};
class sidedefs_t : public kaitai::kstruct {
public:
sidedefs_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~sidedefs_t();
private:
std::vector<sidedef_t*>* m_entries;
doom_wad_t* m__root;
doom_wad_t::index_entry_t* m__parent;
public:
std::vector<sidedef_t*>* entries() const { return m_entries; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::index_entry_t* _parent() const { return m__parent; }
};
class blockmap_t : public kaitai::kstruct {
public:
class blocklist_t;
blockmap_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~blockmap_t();
class blocklist_t : public kaitai::kstruct {
public:
blocklist_t(kaitai::kstream* p__io, doom_wad_t::blockmap_t* p__parent = 0, doom_wad_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~blocklist_t();
private:
bool f_linedefs;
std::vector<int16_t>* m_linedefs;
public:
/**
* List of linedefs found in this block
*/
std::vector<int16_t>* linedefs();
private:
uint16_t m_offset;
doom_wad_t* m__root;
doom_wad_t::blockmap_t* m__parent;
public:
/**
* Offset to the list of linedefs
*/
uint16_t offset() const { return m_offset; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::blockmap_t* _parent() const { return m__parent; }
};
private:
int16_t m_origin_x;
int16_t m_origin_y;
int16_t m_num_cols;
int16_t m_num_rows;
std::vector<blocklist_t*>* m_linedefs_in_block;
doom_wad_t* m__root;
doom_wad_t::index_entry_t* m__parent;
public:
/**
* Grid origin, X coord
*/
int16_t origin_x() const { return m_origin_x; }
/**
* Grid origin, Y coord
*/
int16_t origin_y() const { return m_origin_y; }
/**
* Number of columns
*/
int16_t num_cols() const { return m_num_cols; }
/**
* Number of rows
*/
int16_t num_rows() const { return m_num_rows; }
/**
* Lists of linedefs for every block
*/
std::vector<blocklist_t*>* linedefs_in_block() const { return m_linedefs_in_block; }
doom_wad_t* _root() const { return m__root; }
doom_wad_t::index_entry_t* _parent() const { return m__parent; }
};
private:
bool f_index;
std::vector<index_entry_t*>* m_index;
public:
std::vector<index_entry_t*>* index();
private:
std::string m_magic;
int32_t m_num_index_entries;
int32_t m_index_offset;
doom_wad_t* m__root;
kaitai::kstruct* m__parent;
public:
std::string magic() const { return m_magic; }
/**
* Number of entries in the lump index
*/
int32_t num_index_entries() const { return m_num_index_entries; }
/**
* Offset to the start of the index
*/
int32_t index_offset() const { return m_index_offset; }
doom_wad_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
#endif // DOOM_WAD_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "doom_wad.h"
doom_wad_t::doom_wad_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_index = 0;
f_index = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::_read() {
m_magic = kaitai::kstream::bytes_to_str(m__io->read_bytes(4), std::string("ASCII"));
m_num_index_entries = m__io->read_s4le();
m_index_offset = m__io->read_s4le();
}
doom_wad_t::~doom_wad_t() {
_clean_up();
}
void doom_wad_t::_clean_up() {
if (f_index) {
if (m_index) {
for (std::vector<index_entry_t*>::iterator it = m_index->begin(); it != m_index->end(); ++it) {
delete *it;
}
delete m_index; m_index = 0;
}
}
}
doom_wad_t::sectors_t::sectors_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::sectors_t::_read() {
m_entries = new std::vector<sector_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(new sector_t(m__io, this, m__root));
i++;
}
}
}
doom_wad_t::sectors_t::~sectors_t() {
_clean_up();
}
void doom_wad_t::sectors_t::_clean_up() {
if (m_entries) {
for (std::vector<sector_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
delete *it;
}
delete m_entries; m_entries = 0;
}
}
doom_wad_t::vertex_t::vertex_t(kaitai::kstream* p__io, doom_wad_t::vertexes_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::vertex_t::_read() {
m_x = m__io->read_s2le();
m_y = m__io->read_s2le();
}
doom_wad_t::vertex_t::~vertex_t() {
_clean_up();
}
void doom_wad_t::vertex_t::_clean_up() {
}
doom_wad_t::texture12_t::texture12_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_textures = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::texture12_t::_read() {
m_num_textures = m__io->read_s4le();
m_textures = new std::vector<texture_index_t*>();
const int l_textures = num_textures();
for (int i = 0; i < l_textures; i++) {
m_textures->push_back(new texture_index_t(m__io, this, m__root));
}
}
doom_wad_t::texture12_t::~texture12_t() {
_clean_up();
}
void doom_wad_t::texture12_t::_clean_up() {
if (m_textures) {
for (std::vector<texture_index_t*>::iterator it = m_textures->begin(); it != m_textures->end(); ++it) {
delete *it;
}
delete m_textures; m_textures = 0;
}
}
doom_wad_t::texture12_t::texture_index_t::texture_index_t(kaitai::kstream* p__io, doom_wad_t::texture12_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_body = 0;
f_body = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::texture12_t::texture_index_t::_read() {
m_offset = m__io->read_s4le();
}
doom_wad_t::texture12_t::texture_index_t::~texture_index_t() {
_clean_up();
}
void doom_wad_t::texture12_t::texture_index_t::_clean_up() {
if (f_body) {
if (m_body) {
delete m_body; m_body = 0;
}
}
}
doom_wad_t::texture12_t::texture_body_t* doom_wad_t::texture12_t::texture_index_t::body() {
if (f_body)
return m_body;
std::streampos _pos = m__io->pos();
m__io->seek(offset());
m_body = new texture_body_t(m__io, this, m__root);
m__io->seek(_pos);
f_body = true;
return m_body;
}
doom_wad_t::texture12_t::texture_body_t::texture_body_t(kaitai::kstream* p__io, doom_wad_t::texture12_t::texture_index_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_patches = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::texture12_t::texture_body_t::_read() {
m_name = kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_strip_right(m__io->read_bytes(8), 0), std::string("ASCII"));
m_masked = m__io->read_u4le();
m_width = m__io->read_u2le();
m_height = m__io->read_u2le();
m_column_directory = m__io->read_u4le();
m_num_patches = m__io->read_u2le();
m_patches = new std::vector<patch_t*>();
const int l_patches = num_patches();
for (int i = 0; i < l_patches; i++) {
m_patches->push_back(new patch_t(m__io, this, m__root));
}
}
doom_wad_t::texture12_t::texture_body_t::~texture_body_t() {
_clean_up();
}
void doom_wad_t::texture12_t::texture_body_t::_clean_up() {
if (m_patches) {
for (std::vector<patch_t*>::iterator it = m_patches->begin(); it != m_patches->end(); ++it) {
delete *it;
}
delete m_patches; m_patches = 0;
}
}
doom_wad_t::texture12_t::patch_t::patch_t(kaitai::kstream* p__io, doom_wad_t::texture12_t::texture_body_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::texture12_t::patch_t::_read() {
m_origin_x = m__io->read_s2le();
m_origin_y = m__io->read_s2le();
m_patch_id = m__io->read_u2le();
m_step_dir = m__io->read_u2le();
m_colormap = m__io->read_u2le();
}
doom_wad_t::texture12_t::patch_t::~patch_t() {
_clean_up();
}
void doom_wad_t::texture12_t::patch_t::_clean_up() {
}
doom_wad_t::linedef_t::linedef_t(kaitai::kstream* p__io, doom_wad_t::linedefs_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::linedef_t::_read() {
m_vertex_start_idx = m__io->read_u2le();
m_vertex_end_idx = m__io->read_u2le();
m_flags = m__io->read_u2le();
m_line_type = m__io->read_u2le();
m_sector_tag = m__io->read_u2le();
m_sidedef_right_idx = m__io->read_u2le();
m_sidedef_left_idx = m__io->read_u2le();
}
doom_wad_t::linedef_t::~linedef_t() {
_clean_up();
}
void doom_wad_t::linedef_t::_clean_up() {
}
doom_wad_t::pnames_t::pnames_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_names = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::pnames_t::_read() {
m_num_patches = m__io->read_u4le();
m_names = new std::vector<std::string>();
const int l_names = num_patches();
for (int i = 0; i < l_names; i++) {
m_names->push_back(kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_strip_right(m__io->read_bytes(8), 0), std::string("ASCII")));
}
}
doom_wad_t::pnames_t::~pnames_t() {
_clean_up();
}
void doom_wad_t::pnames_t::_clean_up() {
if (m_names) {
delete m_names; m_names = 0;
}
}
doom_wad_t::thing_t::thing_t(kaitai::kstream* p__io, doom_wad_t::things_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::thing_t::_read() {
m_x = m__io->read_s2le();
m_y = m__io->read_s2le();
m_angle = m__io->read_u2le();
m_type = m__io->read_u2le();
m_flags = m__io->read_u2le();
}
doom_wad_t::thing_t::~thing_t() {
_clean_up();
}
void doom_wad_t::thing_t::_clean_up() {
}
doom_wad_t::sector_t::sector_t(kaitai::kstream* p__io, doom_wad_t::sectors_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::sector_t::_read() {
m_floor_z = m__io->read_s2le();
m_ceil_z = m__io->read_s2le();
m_floor_flat = kaitai::kstream::bytes_to_str(m__io->read_bytes(8), std::string("ASCII"));
m_ceil_flat = kaitai::kstream::bytes_to_str(m__io->read_bytes(8), std::string("ASCII"));
m_light = m__io->read_s2le();
m_special_type = static_cast<doom_wad_t::sector_t::special_sector_t>(m__io->read_u2le());
m_tag = m__io->read_u2le();
}
doom_wad_t::sector_t::~sector_t() {
_clean_up();
}
void doom_wad_t::sector_t::_clean_up() {
}
doom_wad_t::vertexes_t::vertexes_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::vertexes_t::_read() {
m_entries = new std::vector<vertex_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(new vertex_t(m__io, this, m__root));
i++;
}
}
}
doom_wad_t::vertexes_t::~vertexes_t() {
_clean_up();
}
void doom_wad_t::vertexes_t::_clean_up() {
if (m_entries) {
for (std::vector<vertex_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
delete *it;
}
delete m_entries; m_entries = 0;
}
}
doom_wad_t::sidedef_t::sidedef_t(kaitai::kstream* p__io, doom_wad_t::sidedefs_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::sidedef_t::_read() {
m_offset_x = m__io->read_s2le();
m_offset_y = m__io->read_s2le();
m_upper_texture_name = kaitai::kstream::bytes_to_str(m__io->read_bytes(8), std::string("ASCII"));
m_lower_texture_name = kaitai::kstream::bytes_to_str(m__io->read_bytes(8), std::string("ASCII"));
m_normal_texture_name = kaitai::kstream::bytes_to_str(m__io->read_bytes(8), std::string("ASCII"));
m_sector_id = m__io->read_s2le();
}
doom_wad_t::sidedef_t::~sidedef_t() {
_clean_up();
}
void doom_wad_t::sidedef_t::_clean_up() {
}
doom_wad_t::things_t::things_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::things_t::_read() {
m_entries = new std::vector<thing_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(new thing_t(m__io, this, m__root));
i++;
}
}
}
doom_wad_t::things_t::~things_t() {
_clean_up();
}
void doom_wad_t::things_t::_clean_up() {
if (m_entries) {
for (std::vector<thing_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
delete *it;
}
delete m_entries; m_entries = 0;
}
}
doom_wad_t::linedefs_t::linedefs_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::linedefs_t::_read() {
m_entries = new std::vector<linedef_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(new linedef_t(m__io, this, m__root));
i++;
}
}
}
doom_wad_t::linedefs_t::~linedefs_t() {
_clean_up();
}
void doom_wad_t::linedefs_t::_clean_up() {
if (m_entries) {
for (std::vector<linedef_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
delete *it;
}
delete m_entries; m_entries = 0;
}
}
doom_wad_t::index_entry_t::index_entry_t(kaitai::kstream* p__io, doom_wad_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m__io__raw_contents = 0;
f_contents = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::index_entry_t::_read() {
m_offset = m__io->read_s4le();
m_size = m__io->read_s4le();
m_name = kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_strip_right(m__io->read_bytes(8), 0), std::string("ASCII"));
}
doom_wad_t::index_entry_t::~index_entry_t() {
_clean_up();
}
void doom_wad_t::index_entry_t::_clean_up() {
if (f_contents && !n_contents) {
if (m__io__raw_contents) {
delete m__io__raw_contents; m__io__raw_contents = 0;
}
if (m_contents) {
delete m_contents; m_contents = 0;
}
}
}
kaitai::kstruct* doom_wad_t::index_entry_t::contents() {
if (f_contents)
return m_contents;
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek(offset());
n_contents = true;
{
std::string on = name();
if (on == std::string("SECTORS")) {
n_contents = false;
m__raw_contents = io->read_bytes(size());
m__io__raw_contents = new kaitai::kstream(m__raw_contents);
m_contents = new sectors_t(m__io__raw_contents, this, m__root);
}
else if (on == std::string("TEXTURE1")) {
n_contents = false;
m__raw_contents = io->read_bytes(size());
m__io__raw_contents = new kaitai::kstream(m__raw_contents);
m_contents = new texture12_t(m__io__raw_contents, this, m__root);
}
else if (on == std::string("VERTEXES")) {
n_contents = false;
m__raw_contents = io->read_bytes(size());
m__io__raw_contents = new kaitai::kstream(m__raw_contents);
m_contents = new vertexes_t(m__io__raw_contents, this, m__root);
}
else if (on == std::string("BLOCKMAP")) {
n_contents = false;
m__raw_contents = io->read_bytes(size());
m__io__raw_contents = new kaitai::kstream(m__raw_contents);
m_contents = new blockmap_t(m__io__raw_contents, this, m__root);
}
else if (on == std::string("PNAMES")) {
n_contents = false;
m__raw_contents = io->read_bytes(size());
m__io__raw_contents = new kaitai::kstream(m__raw_contents);
m_contents = new pnames_t(m__io__raw_contents, this, m__root);
}
else if (on == std::string("TEXTURE2")) {
n_contents = false;
m__raw_contents = io->read_bytes(size());
m__io__raw_contents = new kaitai::kstream(m__raw_contents);
m_contents = new texture12_t(m__io__raw_contents, this, m__root);
}
else if (on == std::string("THINGS")) {
n_contents = false;
m__raw_contents = io->read_bytes(size());
m__io__raw_contents = new kaitai::kstream(m__raw_contents);
m_contents = new things_t(m__io__raw_contents, this, m__root);
}
else if (on == std::string("LINEDEFS")) {
n_contents = false;
m__raw_contents = io->read_bytes(size());
m__io__raw_contents = new kaitai::kstream(m__raw_contents);
m_contents = new linedefs_t(m__io__raw_contents, this, m__root);
}
else if (on == std::string("SIDEDEFS")) {
n_contents = false;
m__raw_contents = io->read_bytes(size());
m__io__raw_contents = new kaitai::kstream(m__raw_contents);
m_contents = new sidedefs_t(m__io__raw_contents, this, m__root);
}
else {
m__raw_contents = io->read_bytes(size());
}
}
io->seek(_pos);
f_contents = true;
return m_contents;
}
doom_wad_t::sidedefs_t::sidedefs_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::sidedefs_t::_read() {
m_entries = new std::vector<sidedef_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(new sidedef_t(m__io, this, m__root));
i++;
}
}
}
doom_wad_t::sidedefs_t::~sidedefs_t() {
_clean_up();
}
void doom_wad_t::sidedefs_t::_clean_up() {
if (m_entries) {
for (std::vector<sidedef_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
delete *it;
}
delete m_entries; m_entries = 0;
}
}
doom_wad_t::blockmap_t::blockmap_t(kaitai::kstream* p__io, doom_wad_t::index_entry_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_linedefs_in_block = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::blockmap_t::_read() {
m_origin_x = m__io->read_s2le();
m_origin_y = m__io->read_s2le();
m_num_cols = m__io->read_s2le();
m_num_rows = m__io->read_s2le();
m_linedefs_in_block = new std::vector<blocklist_t*>();
const int l_linedefs_in_block = (num_cols() * num_rows());
for (int i = 0; i < l_linedefs_in_block; i++) {
m_linedefs_in_block->push_back(new blocklist_t(m__io, this, m__root));
}
}
doom_wad_t::blockmap_t::~blockmap_t() {
_clean_up();
}
void doom_wad_t::blockmap_t::_clean_up() {
if (m_linedefs_in_block) {
for (std::vector<blocklist_t*>::iterator it = m_linedefs_in_block->begin(); it != m_linedefs_in_block->end(); ++it) {
delete *it;
}
delete m_linedefs_in_block; m_linedefs_in_block = 0;
}
}
doom_wad_t::blockmap_t::blocklist_t::blocklist_t(kaitai::kstream* p__io, doom_wad_t::blockmap_t* p__parent, doom_wad_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_linedefs = 0;
f_linedefs = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void doom_wad_t::blockmap_t::blocklist_t::_read() {
m_offset = m__io->read_u2le();
}
doom_wad_t::blockmap_t::blocklist_t::~blocklist_t() {
_clean_up();
}
void doom_wad_t::blockmap_t::blocklist_t::_clean_up() {
if (f_linedefs) {
if (m_linedefs) {
delete m_linedefs; m_linedefs = 0;
}
}
}
std::vector<int16_t>* doom_wad_t::blockmap_t::blocklist_t::linedefs() {
if (f_linedefs)
return m_linedefs;
std::streampos _pos = m__io->pos();
m__io->seek((offset() * 2));
m_linedefs = new std::vector<int16_t>();
{
int i = 0;
int16_t _;
do {
_ = m__io->read_s2le();
m_linedefs->push_back(_);
i++;
} while (!(_ == -1));
}
m__io->seek(_pos);
f_linedefs = true;
return m_linedefs;
}
std::vector<doom_wad_t::index_entry_t*>* doom_wad_t::index() {
if (f_index)
return m_index;
std::streampos _pos = m__io->pos();
m__io->seek(index_offset());
m_index = new std::vector<index_entry_t*>();
const int l_index = num_index_entries();
for (int i = 0; i < l_index; i++) {
m_index->push_back(new index_entry_t(m__io, this, m__root));
}
m__io->seek(_pos);
f_index = true;
return m_index;
}