diff options
| author | Andrew Lamoureux <andrew@vector35.com> | 2019-03-18 17:34:09 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2019-03-20 13:00:17 -0400 |
| commit | 815f5485eb50eff3b483a6bcc0c3d3d11569f8ca (patch) | |
| tree | 5128136ac86971ed8729e8c19cb00bcf8f220acc /python/examples/kaitai/kaitai_struct_formats/game | |
| parent | 8e9322ed8b5826dd62bc931d83e0828d42f7969f (diff) | |
kaitai: all formats compiled and included
Diffstat (limited to 'python/examples/kaitai/kaitai_struct_formats/game')
16 files changed, 3941 insertions, 0 deletions
diff --git a/python/examples/kaitai/kaitai_struct_formats/game/__init__.py b/python/examples/kaitai/kaitai_struct_formats/game/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/__init__.py diff --git a/python/examples/kaitai/kaitai_struct_formats/game/allegro_dat.py b/python/examples/kaitai/kaitai_struct_formats/game/allegro_dat.py new file mode 100644 index 00000000..0078bf45 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/allegro_dat.py @@ -0,0 +1,365 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +from enum import Enum +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class AllegroDat(KaitaiStruct): + """Allegro library for C (mostly used for game and multimedia apps + programming) used its own container file format. + + In general, it allows storage of arbitrary binary data blocks + bundled together with some simple key-value style metadata + ("properties") for every block. Allegro also pre-defines some simple + formats for bitmaps, fonts, MIDI music, sound samples and + palettes. Allegro library v4.0+ also support LZSS compression. + + This spec applies to Allegro data files for library versions 2.2 up + to 4.4. + + .. seealso:: + Source - https://liballeg.org/stabledocs/en/datafile.html + """ + + class PackEnum(Enum): + unpacked = 1936484398 + SEQ_FIELDS = ["pack_magic", "dat_magic", "num_objects", "objects"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['pack_magic']['start'] = self._io.pos() + self.pack_magic = KaitaiStream.resolve_enum(self._root.PackEnum, self._io.read_u4be()) + self._debug['pack_magic']['end'] = self._io.pos() + self._debug['dat_magic']['start'] = self._io.pos() + self.dat_magic = self._io.ensure_fixed_contents(b"\x41\x4C\x4C\x2E") + self._debug['dat_magic']['end'] = self._io.pos() + self._debug['num_objects']['start'] = self._io.pos() + self.num_objects = self._io.read_u4be() + self._debug['num_objects']['end'] = self._io.pos() + self._debug['objects']['start'] = self._io.pos() + self.objects = [None] * (self.num_objects) + for i in range(self.num_objects): + if not 'arr' in self._debug['objects']: + self._debug['objects']['arr'] = [] + self._debug['objects']['arr'].append({'start': self._io.pos()}) + _t_objects = self._root.DatObject(self._io, self, self._root) + _t_objects._read() + self.objects[i] = _t_objects + self._debug['objects']['arr'][i]['end'] = self._io.pos() + + self._debug['objects']['end'] = self._io.pos() + + class DatFont16(KaitaiStruct): + """Simple monochrome monospaced font, 95 characters, 8x16 px + characters. + """ + SEQ_FIELDS = ["chars"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['chars']['start'] = self._io.pos() + self.chars = [None] * (95) + for i in range(95): + if not 'arr' in self._debug['chars']: + self._debug['chars']['arr'] = [] + self._debug['chars']['arr'].append({'start': self._io.pos()}) + self.chars[i] = self._io.read_bytes(16) + self._debug['chars']['arr'][i]['end'] = self._io.pos() + + self._debug['chars']['end'] = self._io.pos() + + + class DatBitmap(KaitaiStruct): + SEQ_FIELDS = ["bits_per_pixel", "width", "height", "image"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['bits_per_pixel']['start'] = self._io.pos() + self.bits_per_pixel = self._io.read_s2be() + self._debug['bits_per_pixel']['end'] = self._io.pos() + self._debug['width']['start'] = self._io.pos() + self.width = self._io.read_u2be() + self._debug['width']['end'] = self._io.pos() + self._debug['height']['start'] = self._io.pos() + self.height = self._io.read_u2be() + self._debug['height']['end'] = self._io.pos() + self._debug['image']['start'] = self._io.pos() + self.image = self._io.read_bytes_full() + self._debug['image']['end'] = self._io.pos() + + + class DatFont(KaitaiStruct): + SEQ_FIELDS = ["font_size", "body"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['font_size']['start'] = self._io.pos() + self.font_size = self._io.read_s2be() + self._debug['font_size']['end'] = self._io.pos() + self._debug['body']['start'] = self._io.pos() + _on = self.font_size + if _on == 8: + self.body = self._root.DatFont8(self._io, self, self._root) + self.body._read() + elif _on == 16: + self.body = self._root.DatFont16(self._io, self, self._root) + self.body._read() + elif _on == 0: + self.body = self._root.DatFont39(self._io, self, self._root) + self.body._read() + self._debug['body']['end'] = self._io.pos() + + + class DatFont8(KaitaiStruct): + """Simple monochrome monospaced font, 95 characters, 8x8 px + characters. + """ + SEQ_FIELDS = ["chars"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['chars']['start'] = self._io.pos() + self.chars = [None] * (95) + for i in range(95): + if not 'arr' in self._debug['chars']: + self._debug['chars']['arr'] = [] + self._debug['chars']['arr'].append({'start': self._io.pos()}) + self.chars[i] = self._io.read_bytes(8) + self._debug['chars']['arr'][i]['end'] = self._io.pos() + + self._debug['chars']['end'] = self._io.pos() + + + class DatObject(KaitaiStruct): + SEQ_FIELDS = ["properties", "len_compressed", "len_uncompressed", "body"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['properties']['start'] = self._io.pos() + self.properties = [] + i = 0 + while True: + if not 'arr' in self._debug['properties']: + self._debug['properties']['arr'] = [] + self._debug['properties']['arr'].append({'start': self._io.pos()}) + _t_properties = self._root.Property(self._io, self, self._root) + _t_properties._read() + _ = _t_properties + self.properties.append(_) + self._debug['properties']['arr'][len(self.properties) - 1]['end'] = self._io.pos() + if not (_.is_valid): + break + i += 1 + self._debug['properties']['end'] = self._io.pos() + self._debug['len_compressed']['start'] = self._io.pos() + self.len_compressed = self._io.read_s4be() + self._debug['len_compressed']['end'] = self._io.pos() + self._debug['len_uncompressed']['start'] = self._io.pos() + self.len_uncompressed = self._io.read_s4be() + self._debug['len_uncompressed']['end'] = self._io.pos() + self._debug['body']['start'] = self._io.pos() + _on = self.type + if _on == u"BMP ": + self._raw_body = self._io.read_bytes(self.len_compressed) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.DatBitmap(io, self, self._root) + self.body._read() + elif _on == u"RLE ": + self._raw_body = self._io.read_bytes(self.len_compressed) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.DatRleSprite(io, self, self._root) + self.body._read() + elif _on == u"FONT": + self._raw_body = self._io.read_bytes(self.len_compressed) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.DatFont(io, self, self._root) + self.body._read() + else: + self.body = self._io.read_bytes(self.len_compressed) + self._debug['body']['end'] = self._io.pos() + + @property + def type(self): + if hasattr(self, '_m_type'): + return self._m_type if hasattr(self, '_m_type') else None + + self._m_type = self.properties[-1].magic + return self._m_type if hasattr(self, '_m_type') else None + + + class DatFont39(KaitaiStruct): + """New bitmap font format introduced since Allegro 3.9: allows + flexible designation of character ranges, 8-bit colored + characters, etc. + """ + SEQ_FIELDS = ["num_ranges", "ranges"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['num_ranges']['start'] = self._io.pos() + self.num_ranges = self._io.read_s2be() + self._debug['num_ranges']['end'] = self._io.pos() + self._debug['ranges']['start'] = self._io.pos() + self.ranges = [None] * (self.num_ranges) + for i in range(self.num_ranges): + if not 'arr' in self._debug['ranges']: + self._debug['ranges']['arr'] = [] + self._debug['ranges']['arr'].append({'start': self._io.pos()}) + _t_ranges = self._root.DatFont39.Range(self._io, self, self._root) + _t_ranges._read() + self.ranges[i] = _t_ranges + self._debug['ranges']['arr'][i]['end'] = self._io.pos() + + self._debug['ranges']['end'] = self._io.pos() + + class Range(KaitaiStruct): + SEQ_FIELDS = ["mono", "start_char", "end_char", "chars"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['mono']['start'] = self._io.pos() + self.mono = self._io.read_u1() + self._debug['mono']['end'] = self._io.pos() + self._debug['start_char']['start'] = self._io.pos() + self.start_char = self._io.read_u4be() + self._debug['start_char']['end'] = self._io.pos() + self._debug['end_char']['start'] = self._io.pos() + self.end_char = self._io.read_u4be() + self._debug['end_char']['end'] = self._io.pos() + self._debug['chars']['start'] = self._io.pos() + self.chars = [None] * (((self.end_char - self.start_char) + 1)) + for i in range(((self.end_char - self.start_char) + 1)): + if not 'arr' in self._debug['chars']: + self._debug['chars']['arr'] = [] + self._debug['chars']['arr'].append({'start': self._io.pos()}) + _t_chars = self._root.DatFont39.FontChar(self._io, self, self._root) + _t_chars._read() + self.chars[i] = _t_chars + self._debug['chars']['arr'][i]['end'] = self._io.pos() + + self._debug['chars']['end'] = self._io.pos() + + + class FontChar(KaitaiStruct): + SEQ_FIELDS = ["width", "height", "body"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['width']['start'] = self._io.pos() + self.width = self._io.read_u2be() + self._debug['width']['end'] = self._io.pos() + self._debug['height']['start'] = self._io.pos() + self.height = self._io.read_u2be() + self._debug['height']['end'] = self._io.pos() + self._debug['body']['start'] = self._io.pos() + self.body = self._io.read_bytes((self.width * self.height)) + self._debug['body']['end'] = self._io.pos() + + + + class Property(KaitaiStruct): + SEQ_FIELDS = ["magic", "type", "len_body", "body"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['magic']['start'] = self._io.pos() + self.magic = (self._io.read_bytes(4)).decode(u"UTF-8") + self._debug['magic']['end'] = self._io.pos() + if self.is_valid: + self._debug['type']['start'] = self._io.pos() + self.type = (self._io.read_bytes(4)).decode(u"UTF-8") + self._debug['type']['end'] = self._io.pos() + + if self.is_valid: + self._debug['len_body']['start'] = self._io.pos() + self.len_body = self._io.read_u4be() + self._debug['len_body']['end'] = self._io.pos() + + if self.is_valid: + self._debug['body']['start'] = self._io.pos() + self.body = (self._io.read_bytes(self.len_body)).decode(u"UTF-8") + self._debug['body']['end'] = self._io.pos() + + + @property + def is_valid(self): + if hasattr(self, '_m_is_valid'): + return self._m_is_valid if hasattr(self, '_m_is_valid') else None + + self._m_is_valid = self.magic == u"prop" + return self._m_is_valid if hasattr(self, '_m_is_valid') else None + + + class DatRleSprite(KaitaiStruct): + SEQ_FIELDS = ["bits_per_pixel", "width", "height", "len_image", "image"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['bits_per_pixel']['start'] = self._io.pos() + self.bits_per_pixel = self._io.read_s2be() + self._debug['bits_per_pixel']['end'] = self._io.pos() + self._debug['width']['start'] = self._io.pos() + self.width = self._io.read_u2be() + self._debug['width']['end'] = self._io.pos() + self._debug['height']['start'] = self._io.pos() + self.height = self._io.read_u2be() + self._debug['height']['end'] = self._io.pos() + self._debug['len_image']['start'] = self._io.pos() + self.len_image = self._io.read_u4be() + self._debug['len_image']['end'] = self._io.pos() + self._debug['image']['start'] = self._io.pos() + self.image = self._io.read_bytes_full() + self._debug['image']['end'] = self._io.pos() + + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/doom_wad.py b/python/examples/kaitai/kaitai_struct_formats/game/doom_wad.py new file mode 100644 index 00000000..b5705ae9 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/doom_wad.py @@ -0,0 +1,654 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +import collections +from enum import Enum + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class DoomWad(KaitaiStruct): + SEQ_FIELDS = ["magic", "num_index_entries", "index_offset"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['magic']['start'] = self._io.pos() + self.magic = (self._io.read_bytes(4)).decode(u"ASCII") + self._debug['magic']['end'] = self._io.pos() + self._debug['num_index_entries']['start'] = self._io.pos() + self.num_index_entries = self._io.read_s4le() + self._debug['num_index_entries']['end'] = self._io.pos() + self._debug['index_offset']['start'] = self._io.pos() + self.index_offset = self._io.read_s4le() + self._debug['index_offset']['end'] = self._io.pos() + + class Sectors(KaitaiStruct): + SEQ_FIELDS = ["entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['entries']['start'] = self._io.pos() + self.entries = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = self._root.Sector(self._io, self, self._root) + _t_entries._read() + self.entries.append(_t_entries) + self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['entries']['end'] = self._io.pos() + + + class Vertex(KaitaiStruct): + SEQ_FIELDS = ["x", "y"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['x']['start'] = self._io.pos() + self.x = self._io.read_s2le() + self._debug['x']['end'] = self._io.pos() + self._debug['y']['start'] = self._io.pos() + self.y = self._io.read_s2le() + self._debug['y']['end'] = self._io.pos() + + + class Texture12(KaitaiStruct): + """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. + + .. seealso:: + Source - http://doom.wikia.com/wiki/TEXTURE1 + """ + SEQ_FIELDS = ["num_textures", "textures"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['num_textures']['start'] = self._io.pos() + self.num_textures = self._io.read_s4le() + self._debug['num_textures']['end'] = self._io.pos() + self._debug['textures']['start'] = self._io.pos() + self.textures = [None] * (self.num_textures) + for i in range(self.num_textures): + if not 'arr' in self._debug['textures']: + self._debug['textures']['arr'] = [] + self._debug['textures']['arr'].append({'start': self._io.pos()}) + _t_textures = self._root.Texture12.TextureIndex(self._io, self, self._root) + _t_textures._read() + self.textures[i] = _t_textures + self._debug['textures']['arr'][i]['end'] = self._io.pos() + + self._debug['textures']['end'] = self._io.pos() + + class TextureIndex(KaitaiStruct): + SEQ_FIELDS = ["offset"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['offset']['start'] = self._io.pos() + self.offset = self._io.read_s4le() + self._debug['offset']['end'] = self._io.pos() + + @property + def body(self): + if hasattr(self, '_m_body'): + return self._m_body if hasattr(self, '_m_body') else None + + _pos = self._io.pos() + self._io.seek(self.offset) + self._debug['_m_body']['start'] = self._io.pos() + self._m_body = self._root.Texture12.TextureBody(self._io, self, self._root) + self._m_body._read() + self._debug['_m_body']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_body if hasattr(self, '_m_body') else None + + + class TextureBody(KaitaiStruct): + SEQ_FIELDS = ["name", "masked", "width", "height", "column_directory", "num_patches", "patches"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['name']['start'] = self._io.pos() + self.name = (KaitaiStream.bytes_strip_right(self._io.read_bytes(8), 0)).decode(u"ASCII") + self._debug['name']['end'] = self._io.pos() + self._debug['masked']['start'] = self._io.pos() + self.masked = self._io.read_u4le() + self._debug['masked']['end'] = self._io.pos() + self._debug['width']['start'] = self._io.pos() + self.width = self._io.read_u2le() + self._debug['width']['end'] = self._io.pos() + self._debug['height']['start'] = self._io.pos() + self.height = self._io.read_u2le() + self._debug['height']['end'] = self._io.pos() + self._debug['column_directory']['start'] = self._io.pos() + self.column_directory = self._io.read_u4le() + self._debug['column_directory']['end'] = self._io.pos() + self._debug['num_patches']['start'] = self._io.pos() + self.num_patches = self._io.read_u2le() + self._debug['num_patches']['end'] = self._io.pos() + self._debug['patches']['start'] = self._io.pos() + self.patches = [None] * (self.num_patches) + for i in range(self.num_patches): + if not 'arr' in self._debug['patches']: + self._debug['patches']['arr'] = [] + self._debug['patches']['arr'].append({'start': self._io.pos()}) + _t_patches = self._root.Texture12.Patch(self._io, self, self._root) + _t_patches._read() + self.patches[i] = _t_patches + self._debug['patches']['arr'][i]['end'] = self._io.pos() + + self._debug['patches']['end'] = self._io.pos() + + + class Patch(KaitaiStruct): + SEQ_FIELDS = ["origin_x", "origin_y", "patch_id", "step_dir", "colormap"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['origin_x']['start'] = self._io.pos() + self.origin_x = self._io.read_s2le() + self._debug['origin_x']['end'] = self._io.pos() + self._debug['origin_y']['start'] = self._io.pos() + self.origin_y = self._io.read_s2le() + self._debug['origin_y']['end'] = self._io.pos() + self._debug['patch_id']['start'] = self._io.pos() + self.patch_id = self._io.read_u2le() + self._debug['patch_id']['end'] = self._io.pos() + self._debug['step_dir']['start'] = self._io.pos() + self.step_dir = self._io.read_u2le() + self._debug['step_dir']['end'] = self._io.pos() + self._debug['colormap']['start'] = self._io.pos() + self.colormap = self._io.read_u2le() + self._debug['colormap']['end'] = self._io.pos() + + + + class Linedef(KaitaiStruct): + SEQ_FIELDS = ["vertex_start_idx", "vertex_end_idx", "flags", "line_type", "sector_tag", "sidedef_right_idx", "sidedef_left_idx"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['vertex_start_idx']['start'] = self._io.pos() + self.vertex_start_idx = self._io.read_u2le() + self._debug['vertex_start_idx']['end'] = self._io.pos() + self._debug['vertex_end_idx']['start'] = self._io.pos() + self.vertex_end_idx = self._io.read_u2le() + self._debug['vertex_end_idx']['end'] = self._io.pos() + self._debug['flags']['start'] = self._io.pos() + self.flags = self._io.read_u2le() + self._debug['flags']['end'] = self._io.pos() + self._debug['line_type']['start'] = self._io.pos() + self.line_type = self._io.read_u2le() + self._debug['line_type']['end'] = self._io.pos() + self._debug['sector_tag']['start'] = self._io.pos() + self.sector_tag = self._io.read_u2le() + self._debug['sector_tag']['end'] = self._io.pos() + self._debug['sidedef_right_idx']['start'] = self._io.pos() + self.sidedef_right_idx = self._io.read_u2le() + self._debug['sidedef_right_idx']['end'] = self._io.pos() + self._debug['sidedef_left_idx']['start'] = self._io.pos() + self.sidedef_left_idx = self._io.read_u2le() + self._debug['sidedef_left_idx']['end'] = self._io.pos() + + + class Pnames(KaitaiStruct): + """ + .. seealso:: + Source - http://doom.wikia.com/wiki/PNAMES + """ + SEQ_FIELDS = ["num_patches", "names"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['num_patches']['start'] = self._io.pos() + self.num_patches = self._io.read_u4le() + self._debug['num_patches']['end'] = self._io.pos() + self._debug['names']['start'] = self._io.pos() + self.names = [None] * (self.num_patches) + for i in range(self.num_patches): + if not 'arr' in self._debug['names']: + self._debug['names']['arr'] = [] + self._debug['names']['arr'].append({'start': self._io.pos()}) + self.names[i] = (KaitaiStream.bytes_strip_right(self._io.read_bytes(8), 0)).decode(u"ASCII") + self._debug['names']['arr'][i]['end'] = self._io.pos() + + self._debug['names']['end'] = self._io.pos() + + + class Thing(KaitaiStruct): + SEQ_FIELDS = ["x", "y", "angle", "type", "flags"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['x']['start'] = self._io.pos() + self.x = self._io.read_s2le() + self._debug['x']['end'] = self._io.pos() + self._debug['y']['start'] = self._io.pos() + self.y = self._io.read_s2le() + self._debug['y']['end'] = self._io.pos() + self._debug['angle']['start'] = self._io.pos() + self.angle = self._io.read_u2le() + self._debug['angle']['end'] = self._io.pos() + self._debug['type']['start'] = self._io.pos() + self.type = self._io.read_u2le() + self._debug['type']['end'] = self._io.pos() + self._debug['flags']['start'] = self._io.pos() + self.flags = self._io.read_u2le() + self._debug['flags']['end'] = self._io.pos() + + + class Sector(KaitaiStruct): + + class SpecialSector(Enum): + normal = 0 + d_light_flicker = 1 + d_light_strobe_fast = 2 + d_light_strobe_slow = 3 + d_light_strobe_hurt = 4 + d_damage_hellslime = 5 + d_damage_nukage = 7 + d_light_glow = 8 + secret = 9 + d_sector_door_close_in_30 = 10 + d_damage_end = 11 + d_light_strobe_slow_sync = 12 + d_light_strobe_fast_sync = 13 + d_sector_door_raise_in_5_mins = 14 + d_friction_low = 15 + d_damage_super_hellslime = 16 + d_light_fire_flicker = 17 + d_damage_lava_wimpy = 18 + d_damage_lava_hefty = 19 + d_scroll_east_lava_damage = 20 + light_phased = 21 + light_sequence_start = 22 + light_sequence_special1 = 23 + light_sequence_special2 = 24 + SEQ_FIELDS = ["floor_z", "ceil_z", "floor_flat", "ceil_flat", "light", "special_type", "tag"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['floor_z']['start'] = self._io.pos() + self.floor_z = self._io.read_s2le() + self._debug['floor_z']['end'] = self._io.pos() + self._debug['ceil_z']['start'] = self._io.pos() + self.ceil_z = self._io.read_s2le() + self._debug['ceil_z']['end'] = self._io.pos() + self._debug['floor_flat']['start'] = self._io.pos() + self.floor_flat = (self._io.read_bytes(8)).decode(u"ASCII") + self._debug['floor_flat']['end'] = self._io.pos() + self._debug['ceil_flat']['start'] = self._io.pos() + self.ceil_flat = (self._io.read_bytes(8)).decode(u"ASCII") + self._debug['ceil_flat']['end'] = self._io.pos() + self._debug['light']['start'] = self._io.pos() + self.light = self._io.read_s2le() + self._debug['light']['end'] = self._io.pos() + self._debug['special_type']['start'] = self._io.pos() + self.special_type = KaitaiStream.resolve_enum(self._root.Sector.SpecialSector, self._io.read_u2le()) + self._debug['special_type']['end'] = self._io.pos() + self._debug['tag']['start'] = self._io.pos() + self.tag = self._io.read_u2le() + self._debug['tag']['end'] = self._io.pos() + + + class Vertexes(KaitaiStruct): + SEQ_FIELDS = ["entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['entries']['start'] = self._io.pos() + self.entries = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = self._root.Vertex(self._io, self, self._root) + _t_entries._read() + self.entries.append(_t_entries) + self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['entries']['end'] = self._io.pos() + + + class Sidedef(KaitaiStruct): + SEQ_FIELDS = ["offset_x", "offset_y", "upper_texture_name", "lower_texture_name", "normal_texture_name", "sector_id"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['offset_x']['start'] = self._io.pos() + self.offset_x = self._io.read_s2le() + self._debug['offset_x']['end'] = self._io.pos() + self._debug['offset_y']['start'] = self._io.pos() + self.offset_y = self._io.read_s2le() + self._debug['offset_y']['end'] = self._io.pos() + self._debug['upper_texture_name']['start'] = self._io.pos() + self.upper_texture_name = (self._io.read_bytes(8)).decode(u"ASCII") + self._debug['upper_texture_name']['end'] = self._io.pos() + self._debug['lower_texture_name']['start'] = self._io.pos() + self.lower_texture_name = (self._io.read_bytes(8)).decode(u"ASCII") + self._debug['lower_texture_name']['end'] = self._io.pos() + self._debug['normal_texture_name']['start'] = self._io.pos() + self.normal_texture_name = (self._io.read_bytes(8)).decode(u"ASCII") + self._debug['normal_texture_name']['end'] = self._io.pos() + self._debug['sector_id']['start'] = self._io.pos() + self.sector_id = self._io.read_s2le() + self._debug['sector_id']['end'] = self._io.pos() + + + class Things(KaitaiStruct): + SEQ_FIELDS = ["entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['entries']['start'] = self._io.pos() + self.entries = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = self._root.Thing(self._io, self, self._root) + _t_entries._read() + self.entries.append(_t_entries) + self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['entries']['end'] = self._io.pos() + + + class Linedefs(KaitaiStruct): + SEQ_FIELDS = ["entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['entries']['start'] = self._io.pos() + self.entries = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = self._root.Linedef(self._io, self, self._root) + _t_entries._read() + self.entries.append(_t_entries) + self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['entries']['end'] = self._io.pos() + + + class IndexEntry(KaitaiStruct): + SEQ_FIELDS = ["offset", "size", "name"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['offset']['start'] = self._io.pos() + self.offset = self._io.read_s4le() + self._debug['offset']['end'] = self._io.pos() + self._debug['size']['start'] = self._io.pos() + self.size = self._io.read_s4le() + self._debug['size']['end'] = self._io.pos() + self._debug['name']['start'] = self._io.pos() + self.name = (KaitaiStream.bytes_strip_right(self._io.read_bytes(8), 0)).decode(u"ASCII") + self._debug['name']['end'] = self._io.pos() + + @property + def contents(self): + if hasattr(self, '_m_contents'): + return self._m_contents if hasattr(self, '_m_contents') else None + + io = self._root._io + _pos = io.pos() + io.seek(self.offset) + self._debug['_m_contents']['start'] = io.pos() + _on = self.name + if _on == u"SECTORS": + self._raw__m_contents = io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw__m_contents)) + self._m_contents = self._root.Sectors(io, self, self._root) + self._m_contents._read() + elif _on == u"TEXTURE1": + self._raw__m_contents = io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw__m_contents)) + self._m_contents = self._root.Texture12(io, self, self._root) + self._m_contents._read() + elif _on == u"VERTEXES": + self._raw__m_contents = io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw__m_contents)) + self._m_contents = self._root.Vertexes(io, self, self._root) + self._m_contents._read() + elif _on == u"BLOCKMAP": + self._raw__m_contents = io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw__m_contents)) + self._m_contents = self._root.Blockmap(io, self, self._root) + self._m_contents._read() + elif _on == u"PNAMES": + self._raw__m_contents = io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw__m_contents)) + self._m_contents = self._root.Pnames(io, self, self._root) + self._m_contents._read() + elif _on == u"TEXTURE2": + self._raw__m_contents = io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw__m_contents)) + self._m_contents = self._root.Texture12(io, self, self._root) + self._m_contents._read() + elif _on == u"THINGS": + self._raw__m_contents = io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw__m_contents)) + self._m_contents = self._root.Things(io, self, self._root) + self._m_contents._read() + elif _on == u"LINEDEFS": + self._raw__m_contents = io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw__m_contents)) + self._m_contents = self._root.Linedefs(io, self, self._root) + self._m_contents._read() + elif _on == u"SIDEDEFS": + self._raw__m_contents = io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw__m_contents)) + self._m_contents = self._root.Sidedefs(io, self, self._root) + self._m_contents._read() + else: + self._m_contents = io.read_bytes(self.size) + self._debug['_m_contents']['end'] = io.pos() + io.seek(_pos) + return self._m_contents if hasattr(self, '_m_contents') else None + + + class Sidedefs(KaitaiStruct): + SEQ_FIELDS = ["entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['entries']['start'] = self._io.pos() + self.entries = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = self._root.Sidedef(self._io, self, self._root) + _t_entries._read() + self.entries.append(_t_entries) + self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['entries']['end'] = self._io.pos() + + + class Blockmap(KaitaiStruct): + SEQ_FIELDS = ["origin_x", "origin_y", "num_cols", "num_rows", "linedefs_in_block"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['origin_x']['start'] = self._io.pos() + self.origin_x = self._io.read_s2le() + self._debug['origin_x']['end'] = self._io.pos() + self._debug['origin_y']['start'] = self._io.pos() + self.origin_y = self._io.read_s2le() + self._debug['origin_y']['end'] = self._io.pos() + self._debug['num_cols']['start'] = self._io.pos() + self.num_cols = self._io.read_s2le() + self._debug['num_cols']['end'] = self._io.pos() + self._debug['num_rows']['start'] = self._io.pos() + self.num_rows = self._io.read_s2le() + self._debug['num_rows']['end'] = self._io.pos() + self._debug['linedefs_in_block']['start'] = self._io.pos() + self.linedefs_in_block = [None] * ((self.num_cols * self.num_rows)) + for i in range((self.num_cols * self.num_rows)): + if not 'arr' in self._debug['linedefs_in_block']: + self._debug['linedefs_in_block']['arr'] = [] + self._debug['linedefs_in_block']['arr'].append({'start': self._io.pos()}) + _t_linedefs_in_block = self._root.Blockmap.Blocklist(self._io, self, self._root) + _t_linedefs_in_block._read() + self.linedefs_in_block[i] = _t_linedefs_in_block + self._debug['linedefs_in_block']['arr'][i]['end'] = self._io.pos() + + self._debug['linedefs_in_block']['end'] = self._io.pos() + + class Blocklist(KaitaiStruct): + SEQ_FIELDS = ["offset"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['offset']['start'] = self._io.pos() + self.offset = self._io.read_u2le() + self._debug['offset']['end'] = self._io.pos() + + @property + def linedefs(self): + """List of linedefs found in this block.""" + if hasattr(self, '_m_linedefs'): + return self._m_linedefs if hasattr(self, '_m_linedefs') else None + + _pos = self._io.pos() + self._io.seek((self.offset * 2)) + self._debug['_m_linedefs']['start'] = self._io.pos() + self._m_linedefs = [] + i = 0 + while True: + if not 'arr' in self._debug['_m_linedefs']: + self._debug['_m_linedefs']['arr'] = [] + self._debug['_m_linedefs']['arr'].append({'start': self._io.pos()}) + _ = self._io.read_s2le() + self._m_linedefs.append(_) + self._debug['_m_linedefs']['arr'][len(self._m_linedefs) - 1]['end'] = self._io.pos() + if _ == -1: + break + i += 1 + self._debug['_m_linedefs']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_linedefs if hasattr(self, '_m_linedefs') else None + + + + @property + def index(self): + if hasattr(self, '_m_index'): + return self._m_index if hasattr(self, '_m_index') else None + + _pos = self._io.pos() + self._io.seek(self.index_offset) + self._debug['_m_index']['start'] = self._io.pos() + self._m_index = [None] * (self.num_index_entries) + for i in range(self.num_index_entries): + if not 'arr' in self._debug['_m_index']: + self._debug['_m_index']['arr'] = [] + self._debug['_m_index']['arr'].append({'start': self._io.pos()}) + _t__m_index = self._root.IndexEntry(self._io, self, self._root) + _t__m_index._read() + self._m_index[i] = _t__m_index + self._debug['_m_index']['arr'][i]['end'] = self._io.pos() + + self._debug['_m_index']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_index if hasattr(self, '_m_index') else None + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/dune_2_pak.py b/python/examples/kaitai/kaitai_struct_formats/game/dune_2_pak.py new file mode 100644 index 00000000..e074b018 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/dune_2_pak.py @@ -0,0 +1,122 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class Dune2Pak(KaitaiStruct): + SEQ_FIELDS = ["dir"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['dir']['start'] = self._io.pos() + self._raw_dir = self._io.read_bytes(self.dir_size) + io = KaitaiStream(BytesIO(self._raw_dir)) + self.dir = self._root.Files(io, self, self._root) + self.dir._read() + self._debug['dir']['end'] = self._io.pos() + + class Files(KaitaiStruct): + SEQ_FIELDS = ["files"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['files']['start'] = self._io.pos() + self.files = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['files']: + self._debug['files']['arr'] = [] + self._debug['files']['arr'].append({'start': self._io.pos()}) + _t_files = self._root.File(i, self._io, self, self._root) + _t_files._read() + self.files.append(_t_files) + self._debug['files']['arr'][len(self.files) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['files']['end'] = self._io.pos() + + + class File(KaitaiStruct): + SEQ_FIELDS = ["ofs", "file_name"] + def __init__(self, idx, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.idx = idx + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['ofs']['start'] = self._io.pos() + self.ofs = self._io.read_u4le() + self._debug['ofs']['end'] = self._io.pos() + if self.ofs != 0: + self._debug['file_name']['start'] = self._io.pos() + self.file_name = (self._io.read_bytes_term(0, False, True, True)).decode(u"ASCII") + self._debug['file_name']['end'] = self._io.pos() + + + @property + def next_ofs0(self): + if hasattr(self, '_m_next_ofs0'): + return self._m_next_ofs0 if hasattr(self, '_m_next_ofs0') else None + + if self.ofs != 0: + self._m_next_ofs0 = self._root.dir.files[(self.idx + 1)].ofs + + return self._m_next_ofs0 if hasattr(self, '_m_next_ofs0') else None + + @property + def next_ofs(self): + if hasattr(self, '_m_next_ofs'): + return self._m_next_ofs if hasattr(self, '_m_next_ofs') else None + + if self.ofs != 0: + self._m_next_ofs = (self._root._io.size() if self.next_ofs0 == 0 else self.next_ofs0) + + return self._m_next_ofs if hasattr(self, '_m_next_ofs') else None + + @property + def body(self): + if hasattr(self, '_m_body'): + return self._m_body if hasattr(self, '_m_body') else None + + if self.ofs != 0: + io = self._root._io + _pos = io.pos() + io.seek(self.ofs) + self._debug['_m_body']['start'] = io.pos() + self._m_body = io.read_bytes((self.next_ofs - self.ofs)) + self._debug['_m_body']['end'] = io.pos() + io.seek(_pos) + + return self._m_body if hasattr(self, '_m_body') else None + + + @property + def dir_size(self): + if hasattr(self, '_m_dir_size'): + return self._m_dir_size if hasattr(self, '_m_dir_size') else None + + _pos = self._io.pos() + self._io.seek(0) + self._debug['_m_dir_size']['start'] = self._io.pos() + self._m_dir_size = self._io.read_u4le() + self._debug['_m_dir_size']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_dir_size if hasattr(self, '_m_dir_size') else None + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/fallout2_dat.py b/python/examples/kaitai/kaitai_struct_formats/game/fallout2_dat.py new file mode 100644 index 00000000..e22fc0d5 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/fallout2_dat.py @@ -0,0 +1,161 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +from enum import Enum +import collections +import zlib + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class Fallout2Dat(KaitaiStruct): + + class Compression(Enum): + none = 0 + zlib = 1 + SEQ_FIELDS = [] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + pass + + class Pstr(KaitaiStruct): + SEQ_FIELDS = ["size", "str"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['size']['start'] = self._io.pos() + self.size = self._io.read_u4le() + self._debug['size']['end'] = self._io.pos() + self._debug['str']['start'] = self._io.pos() + self.str = (self._io.read_bytes(self.size)).decode(u"ASCII") + self._debug['str']['end'] = self._io.pos() + + + class Footer(KaitaiStruct): + SEQ_FIELDS = ["index_size", "file_size"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['index_size']['start'] = self._io.pos() + self.index_size = self._io.read_u4le() + self._debug['index_size']['end'] = self._io.pos() + self._debug['file_size']['start'] = self._io.pos() + self.file_size = self._io.read_u4le() + self._debug['file_size']['end'] = self._io.pos() + + + class Index(KaitaiStruct): + SEQ_FIELDS = ["file_count", "files"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['file_count']['start'] = self._io.pos() + self.file_count = self._io.read_u4le() + self._debug['file_count']['end'] = self._io.pos() + self._debug['files']['start'] = self._io.pos() + self.files = [None] * (self.file_count) + for i in range(self.file_count): + if not 'arr' in self._debug['files']: + self._debug['files']['arr'] = [] + self._debug['files']['arr'].append({'start': self._io.pos()}) + _t_files = self._root.File(self._io, self, self._root) + _t_files._read() + self.files[i] = _t_files + self._debug['files']['arr'][i]['end'] = self._io.pos() + + self._debug['files']['end'] = self._io.pos() + + + class File(KaitaiStruct): + SEQ_FIELDS = ["name", "flags", "size_unpacked", "size_packed", "offset"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['name']['start'] = self._io.pos() + self.name = self._root.Pstr(self._io, self, self._root) + self.name._read() + self._debug['name']['end'] = self._io.pos() + self._debug['flags']['start'] = self._io.pos() + self.flags = KaitaiStream.resolve_enum(self._root.Compression, self._io.read_u1()) + self._debug['flags']['end'] = self._io.pos() + self._debug['size_unpacked']['start'] = self._io.pos() + self.size_unpacked = self._io.read_u4le() + self._debug['size_unpacked']['end'] = self._io.pos() + self._debug['size_packed']['start'] = self._io.pos() + self.size_packed = self._io.read_u4le() + self._debug['size_packed']['end'] = self._io.pos() + self._debug['offset']['start'] = self._io.pos() + self.offset = self._io.read_u4le() + self._debug['offset']['end'] = self._io.pos() + + @property + def contents(self): + if hasattr(self, '_m_contents'): + return self._m_contents if hasattr(self, '_m_contents') else None + + if self.flags == self._root.Compression.zlib: + io = self._root._io + _pos = io.pos() + io.seek(self.offset) + self._debug['_m_contents']['start'] = io.pos() + self._raw__m_contents = io.read_bytes(self.size_packed) + self._m_contents = zlib.decompress(self._raw__m_contents) + self._debug['_m_contents']['end'] = io.pos() + io.seek(_pos) + + return self._m_contents if hasattr(self, '_m_contents') else None + + + @property + def footer(self): + if hasattr(self, '_m_footer'): + return self._m_footer if hasattr(self, '_m_footer') else None + + _pos = self._io.pos() + self._io.seek((self._io.size() - 8)) + self._debug['_m_footer']['start'] = self._io.pos() + self._m_footer = self._root.Footer(self._io, self, self._root) + self._m_footer._read() + self._debug['_m_footer']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_footer if hasattr(self, '_m_footer') else None + + @property + def index(self): + if hasattr(self, '_m_index'): + return self._m_index if hasattr(self, '_m_index') else None + + _pos = self._io.pos() + self._io.seek(((self._io.size() - 8) - self.footer.index_size)) + self._debug['_m_index']['start'] = self._io.pos() + self._m_index = self._root.Index(self._io, self, self._root) + self._m_index._read() + self._debug['_m_index']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_index if hasattr(self, '_m_index') else None + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/fallout_dat.py b/python/examples/kaitai/kaitai_struct_formats/game/fallout_dat.py new file mode 100644 index 00000000..4ce06191 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/fallout_dat.py @@ -0,0 +1,156 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +from enum import Enum +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class FalloutDat(KaitaiStruct): + + class Compression(Enum): + none = 32 + lzss = 64 + SEQ_FIELDS = ["folder_count", "unknown1", "unknown2", "timestamp", "folder_names", "folders"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['folder_count']['start'] = self._io.pos() + self.folder_count = self._io.read_u4be() + self._debug['folder_count']['end'] = self._io.pos() + self._debug['unknown1']['start'] = self._io.pos() + self.unknown1 = self._io.read_u4be() + self._debug['unknown1']['end'] = self._io.pos() + self._debug['unknown2']['start'] = self._io.pos() + self.unknown2 = self._io.read_u4be() + self._debug['unknown2']['end'] = self._io.pos() + self._debug['timestamp']['start'] = self._io.pos() + self.timestamp = self._io.read_u4be() + self._debug['timestamp']['end'] = self._io.pos() + self._debug['folder_names']['start'] = self._io.pos() + self.folder_names = [None] * (self.folder_count) + for i in range(self.folder_count): + if not 'arr' in self._debug['folder_names']: + self._debug['folder_names']['arr'] = [] + self._debug['folder_names']['arr'].append({'start': self._io.pos()}) + _t_folder_names = self._root.Pstr(self._io, self, self._root) + _t_folder_names._read() + self.folder_names[i] = _t_folder_names + self._debug['folder_names']['arr'][i]['end'] = self._io.pos() + + self._debug['folder_names']['end'] = self._io.pos() + self._debug['folders']['start'] = self._io.pos() + self.folders = [None] * (self.folder_count) + for i in range(self.folder_count): + if not 'arr' in self._debug['folders']: + self._debug['folders']['arr'] = [] + self._debug['folders']['arr'].append({'start': self._io.pos()}) + _t_folders = self._root.Folder(self._io, self, self._root) + _t_folders._read() + self.folders[i] = _t_folders + self._debug['folders']['arr'][i]['end'] = self._io.pos() + + self._debug['folders']['end'] = self._io.pos() + + class Pstr(KaitaiStruct): + SEQ_FIELDS = ["size", "str"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['size']['start'] = self._io.pos() + self.size = self._io.read_u1() + self._debug['size']['end'] = self._io.pos() + self._debug['str']['start'] = self._io.pos() + self.str = (self._io.read_bytes(self.size)).decode(u"ASCII") + self._debug['str']['end'] = self._io.pos() + + + class Folder(KaitaiStruct): + SEQ_FIELDS = ["file_count", "unknown", "flags", "timestamp", "files"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['file_count']['start'] = self._io.pos() + self.file_count = self._io.read_u4be() + self._debug['file_count']['end'] = self._io.pos() + self._debug['unknown']['start'] = self._io.pos() + self.unknown = self._io.read_u4be() + self._debug['unknown']['end'] = self._io.pos() + self._debug['flags']['start'] = self._io.pos() + self.flags = self._io.read_u4be() + self._debug['flags']['end'] = self._io.pos() + self._debug['timestamp']['start'] = self._io.pos() + self.timestamp = self._io.read_u4be() + self._debug['timestamp']['end'] = self._io.pos() + self._debug['files']['start'] = self._io.pos() + self.files = [None] * (self.file_count) + for i in range(self.file_count): + if not 'arr' in self._debug['files']: + self._debug['files']['arr'] = [] + self._debug['files']['arr'].append({'start': self._io.pos()}) + _t_files = self._root.File(self._io, self, self._root) + _t_files._read() + self.files[i] = _t_files + self._debug['files']['arr'][i]['end'] = self._io.pos() + + self._debug['files']['end'] = self._io.pos() + + + class File(KaitaiStruct): + SEQ_FIELDS = ["name", "flags", "offset", "size_unpacked", "size_packed"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['name']['start'] = self._io.pos() + self.name = self._root.Pstr(self._io, self, self._root) + self.name._read() + self._debug['name']['end'] = self._io.pos() + self._debug['flags']['start'] = self._io.pos() + self.flags = KaitaiStream.resolve_enum(self._root.Compression, self._io.read_u4be()) + self._debug['flags']['end'] = self._io.pos() + self._debug['offset']['start'] = self._io.pos() + self.offset = self._io.read_u4be() + self._debug['offset']['end'] = self._io.pos() + self._debug['size_unpacked']['start'] = self._io.pos() + self.size_unpacked = self._io.read_u4be() + self._debug['size_unpacked']['end'] = self._io.pos() + self._debug['size_packed']['start'] = self._io.pos() + self.size_packed = self._io.read_u4be() + self._debug['size_packed']['end'] = self._io.pos() + + @property + def contents(self): + if hasattr(self, '_m_contents'): + return self._m_contents if hasattr(self, '_m_contents') else None + + io = self._root._io + _pos = io.pos() + io.seek(self.offset) + self._debug['_m_contents']['start'] = io.pos() + self._m_contents = io.read_bytes((self.size_unpacked if self.flags == self._root.Compression.none else self.size_packed)) + self._debug['_m_contents']['end'] = io.pos() + io.seek(_pos) + return self._m_contents if hasattr(self, '_m_contents') else None + + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/ftl_dat.py b/python/examples/kaitai/kaitai_struct_formats/game/ftl_dat.py new file mode 100644 index 00000000..d56d478a --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/ftl_dat.py @@ -0,0 +1,90 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class FtlDat(KaitaiStruct): + SEQ_FIELDS = ["num_files", "files"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['num_files']['start'] = self._io.pos() + self.num_files = self._io.read_u4le() + self._debug['num_files']['end'] = self._io.pos() + self._debug['files']['start'] = self._io.pos() + self.files = [None] * (self.num_files) + for i in range(self.num_files): + if not 'arr' in self._debug['files']: + self._debug['files']['arr'] = [] + self._debug['files']['arr'].append({'start': self._io.pos()}) + _t_files = self._root.File(self._io, self, self._root) + _t_files._read() + self.files[i] = _t_files + self._debug['files']['arr'][i]['end'] = self._io.pos() + + self._debug['files']['end'] = self._io.pos() + + class File(KaitaiStruct): + SEQ_FIELDS = ["ofs_meta"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['ofs_meta']['start'] = self._io.pos() + self.ofs_meta = self._io.read_u4le() + self._debug['ofs_meta']['end'] = self._io.pos() + + @property + def meta(self): + if hasattr(self, '_m_meta'): + return self._m_meta if hasattr(self, '_m_meta') else None + + if self.ofs_meta != 0: + _pos = self._io.pos() + self._io.seek(self.ofs_meta) + self._debug['_m_meta']['start'] = self._io.pos() + self._m_meta = self._root.Meta(self._io, self, self._root) + self._m_meta._read() + self._debug['_m_meta']['end'] = self._io.pos() + self._io.seek(_pos) + + return self._m_meta if hasattr(self, '_m_meta') else None + + + class Meta(KaitaiStruct): + SEQ_FIELDS = ["len_file", "len_filename", "filename", "body"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['len_file']['start'] = self._io.pos() + self.len_file = self._io.read_u4le() + self._debug['len_file']['end'] = self._io.pos() + self._debug['len_filename']['start'] = self._io.pos() + self.len_filename = self._io.read_u4le() + self._debug['len_filename']['end'] = self._io.pos() + self._debug['filename']['start'] = self._io.pos() + self.filename = (self._io.read_bytes(self.len_filename)).decode(u"UTF-8") + self._debug['filename']['end'] = self._io.pos() + self._debug['body']['start'] = self._io.pos() + self.body = self._io.read_bytes(self.len_file) + self._debug['body']['end'] = self._io.pos() + + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/gran_turismo_vol.py b/python/examples/kaitai/kaitai_struct_formats/game/gran_turismo_vol.py new file mode 100644 index 00000000..1b76c226 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/gran_turismo_vol.py @@ -0,0 +1,136 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class GranTurismoVol(KaitaiStruct): + SEQ_FIELDS = ["magic", "num_files", "num_entries", "reserved", "offsets"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['magic']['start'] = self._io.pos() + self.magic = self._io.ensure_fixed_contents(b"\x47\x54\x46\x53\x00\x00\x00\x00") + self._debug['magic']['end'] = self._io.pos() + self._debug['num_files']['start'] = self._io.pos() + self.num_files = self._io.read_u2le() + self._debug['num_files']['end'] = self._io.pos() + self._debug['num_entries']['start'] = self._io.pos() + self.num_entries = self._io.read_u2le() + self._debug['num_entries']['end'] = self._io.pos() + self._debug['reserved']['start'] = self._io.pos() + self.reserved = self._io.ensure_fixed_contents(b"\x00\x00\x00\x00") + self._debug['reserved']['end'] = self._io.pos() + self._debug['offsets']['start'] = self._io.pos() + self.offsets = [None] * (self.num_files) + for i in range(self.num_files): + if not 'arr' in self._debug['offsets']: + self._debug['offsets']['arr'] = [] + self._debug['offsets']['arr'].append({'start': self._io.pos()}) + self.offsets[i] = self._io.read_u4le() + self._debug['offsets']['arr'][i]['end'] = self._io.pos() + + self._debug['offsets']['end'] = self._io.pos() + + class FileInfo(KaitaiStruct): + SEQ_FIELDS = ["timestamp", "offset_idx", "flags", "name"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['timestamp']['start'] = self._io.pos() + self.timestamp = self._io.read_u4le() + self._debug['timestamp']['end'] = self._io.pos() + self._debug['offset_idx']['start'] = self._io.pos() + self.offset_idx = self._io.read_u2le() + self._debug['offset_idx']['end'] = self._io.pos() + self._debug['flags']['start'] = self._io.pos() + self.flags = self._io.read_u1() + self._debug['flags']['end'] = self._io.pos() + self._debug['name']['start'] = self._io.pos() + self.name = (KaitaiStream.bytes_terminate(KaitaiStream.bytes_strip_right(self._io.read_bytes(25), 0), 0, False)).decode(u"ASCII") + self._debug['name']['end'] = self._io.pos() + + @property + def size(self): + if hasattr(self, '_m_size'): + return self._m_size if hasattr(self, '_m_size') else None + + self._m_size = ((self._root.offsets[(self.offset_idx + 1)] & 4294965248) - self._root.offsets[self.offset_idx]) + return self._m_size if hasattr(self, '_m_size') else None + + @property + def body(self): + if hasattr(self, '_m_body'): + return self._m_body if hasattr(self, '_m_body') else None + + if not (self.is_dir): + _pos = self._io.pos() + self._io.seek((self._root.offsets[self.offset_idx] & 4294965248)) + self._debug['_m_body']['start'] = self._io.pos() + self._m_body = self._io.read_bytes(self.size) + self._debug['_m_body']['end'] = self._io.pos() + self._io.seek(_pos) + + return self._m_body if hasattr(self, '_m_body') else None + + @property + def is_dir(self): + if hasattr(self, '_m_is_dir'): + return self._m_is_dir if hasattr(self, '_m_is_dir') else None + + self._m_is_dir = (self.flags & 1) != 0 + return self._m_is_dir if hasattr(self, '_m_is_dir') else None + + @property + def is_last_entry(self): + if hasattr(self, '_m_is_last_entry'): + return self._m_is_last_entry if hasattr(self, '_m_is_last_entry') else None + + self._m_is_last_entry = (self.flags & 128) != 0 + return self._m_is_last_entry if hasattr(self, '_m_is_last_entry') else None + + + @property + def ofs_dir(self): + if hasattr(self, '_m_ofs_dir'): + return self._m_ofs_dir if hasattr(self, '_m_ofs_dir') else None + + self._m_ofs_dir = self.offsets[1] + return self._m_ofs_dir if hasattr(self, '_m_ofs_dir') else None + + @property + def files(self): + if hasattr(self, '_m_files'): + return self._m_files if hasattr(self, '_m_files') else None + + _pos = self._io.pos() + self._io.seek((self.ofs_dir & 4294965248)) + self._debug['_m_files']['start'] = self._io.pos() + self._m_files = [None] * (self._root.num_entries) + for i in range(self._root.num_entries): + if not 'arr' in self._debug['_m_files']: + self._debug['_m_files']['arr'] = [] + self._debug['_m_files']['arr'].append({'start': self._io.pos()}) + _t__m_files = self._root.FileInfo(self._io, self, self._root) + _t__m_files._read() + self._m_files[i] = _t__m_files + self._debug['_m_files']['arr'][i]['end'] = self._io.pos() + + self._debug['_m_files']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_files if hasattr(self, '_m_files') else None + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/heaps_pak.py b/python/examples/kaitai/kaitai_struct_formats/game/heaps_pak.py new file mode 100644 index 00000000..63937a47 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/heaps_pak.py @@ -0,0 +1,173 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class HeapsPak(KaitaiStruct): + """ + .. seealso:: + Source - https://github.com/HeapsIO/heaps/blob/2bbc2b386952dfd8856c04a854bb706a52cb4b58/hxd/fmt/pak/Reader.hx + """ + SEQ_FIELDS = ["header"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['header']['start'] = self._io.pos() + self.header = self._root.Header(self._io, self, self._root) + self.header._read() + self._debug['header']['end'] = self._io.pos() + + class Header(KaitaiStruct): + SEQ_FIELDS = ["magic1", "version", "len_header", "len_data", "root_entry", "magic2"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['magic1']['start'] = self._io.pos() + self.magic1 = self._io.ensure_fixed_contents(b"\x50\x41\x4B") + self._debug['magic1']['end'] = self._io.pos() + self._debug['version']['start'] = self._io.pos() + self.version = self._io.read_u1() + self._debug['version']['end'] = self._io.pos() + self._debug['len_header']['start'] = self._io.pos() + self.len_header = self._io.read_u4le() + self._debug['len_header']['end'] = self._io.pos() + self._debug['len_data']['start'] = self._io.pos() + self.len_data = self._io.read_u4le() + self._debug['len_data']['end'] = self._io.pos() + self._debug['root_entry']['start'] = self._io.pos() + self._raw_root_entry = self._io.read_bytes((self.len_header - 16)) + io = KaitaiStream(BytesIO(self._raw_root_entry)) + self.root_entry = self._root.Header.Entry(io, self, self._root) + self.root_entry._read() + self._debug['root_entry']['end'] = self._io.pos() + self._debug['magic2']['start'] = self._io.pos() + self.magic2 = self._io.ensure_fixed_contents(b"\x44\x41\x54\x41") + self._debug['magic2']['end'] = self._io.pos() + + class Entry(KaitaiStruct): + """ + .. seealso:: + Source - https://github.com/HeapsIO/heaps/blob/2bbc2b386952dfd8856c04a854bb706a52cb4b58/hxd/fmt/pak/Data.hx + """ + SEQ_FIELDS = ["len_name", "name", "flags", "body"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['len_name']['start'] = self._io.pos() + self.len_name = self._io.read_u1() + self._debug['len_name']['end'] = self._io.pos() + self._debug['name']['start'] = self._io.pos() + self.name = (self._io.read_bytes(self.len_name)).decode(u"UTF-8") + self._debug['name']['end'] = self._io.pos() + self._debug['flags']['start'] = self._io.pos() + self.flags = self._root.Header.Entry.Flags(self._io, self, self._root) + self.flags._read() + self._debug['flags']['end'] = self._io.pos() + self._debug['body']['start'] = self._io.pos() + _on = self.flags.is_dir + if _on == True: + self.body = self._root.Header.Dir(self._io, self, self._root) + self.body._read() + elif _on == False: + self.body = self._root.Header.File(self._io, self, self._root) + self.body._read() + self._debug['body']['end'] = self._io.pos() + + class Flags(KaitaiStruct): + SEQ_FIELDS = ["unused", "is_dir"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['unused']['start'] = self._io.pos() + self.unused = self._io.read_bits_int(7) + self._debug['unused']['end'] = self._io.pos() + self._debug['is_dir']['start'] = self._io.pos() + self.is_dir = self._io.read_bits_int(1) != 0 + self._debug['is_dir']['end'] = self._io.pos() + + + + class File(KaitaiStruct): + SEQ_FIELDS = ["ofs_data", "len_data", "checksum"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['ofs_data']['start'] = self._io.pos() + self.ofs_data = self._io.read_u4le() + self._debug['ofs_data']['end'] = self._io.pos() + self._debug['len_data']['start'] = self._io.pos() + self.len_data = self._io.read_u4le() + self._debug['len_data']['end'] = self._io.pos() + self._debug['checksum']['start'] = self._io.pos() + self.checksum = self._io.read_bytes(4) + self._debug['checksum']['end'] = self._io.pos() + + @property + def data(self): + if hasattr(self, '_m_data'): + return self._m_data if hasattr(self, '_m_data') else None + + io = self._root._io + _pos = io.pos() + io.seek((self._root.header.len_header + self.ofs_data)) + self._debug['_m_data']['start'] = io.pos() + self._m_data = io.read_bytes(self.len_data) + self._debug['_m_data']['end'] = io.pos() + io.seek(_pos) + return self._m_data if hasattr(self, '_m_data') else None + + + class Dir(KaitaiStruct): + SEQ_FIELDS = ["num_entries", "entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['num_entries']['start'] = self._io.pos() + self.num_entries = self._io.read_u4le() + self._debug['num_entries']['end'] = self._io.pos() + self._debug['entries']['start'] = self._io.pos() + self.entries = [None] * (self.num_entries) + for i in range(self.num_entries): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = self._root.Header.Entry(self._io, self, self._root) + _t_entries._read() + self.entries[i] = _t_entries + self._debug['entries']['arr'][i]['end'] = self._io.pos() + + self._debug['entries']['end'] = self._io.pos() + + + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/heroes_of_might_and_magic_agg.py b/python/examples/kaitai/kaitai_struct_formats/game/heroes_of_might_and_magic_agg.py new file mode 100644 index 00000000..caff6a27 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/heroes_of_might_and_magic_agg.py @@ -0,0 +1,116 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class HeroesOfMightAndMagicAgg(KaitaiStruct): + """ + .. seealso:: + Source - http://rewiki.regengedanken.de/wiki/.AGG_(Heroes_of_Might_and_Magic) + """ + SEQ_FIELDS = ["num_files", "entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['num_files']['start'] = self._io.pos() + self.num_files = self._io.read_u2le() + self._debug['num_files']['end'] = self._io.pos() + self._debug['entries']['start'] = self._io.pos() + self.entries = [None] * (self.num_files) + for i in range(self.num_files): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = self._root.Entry(self._io, self, self._root) + _t_entries._read() + self.entries[i] = _t_entries + self._debug['entries']['arr'][i]['end'] = self._io.pos() + + self._debug['entries']['end'] = self._io.pos() + + class Entry(KaitaiStruct): + SEQ_FIELDS = ["hash", "offset", "size", "size2"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['hash']['start'] = self._io.pos() + self.hash = self._io.read_u2le() + self._debug['hash']['end'] = self._io.pos() + self._debug['offset']['start'] = self._io.pos() + self.offset = self._io.read_u4le() + self._debug['offset']['end'] = self._io.pos() + self._debug['size']['start'] = self._io.pos() + self.size = self._io.read_u4le() + self._debug['size']['end'] = self._io.pos() + self._debug['size2']['start'] = self._io.pos() + self.size2 = self._io.read_u4le() + self._debug['size2']['end'] = self._io.pos() + + @property + def body(self): + if hasattr(self, '_m_body'): + return self._m_body if hasattr(self, '_m_body') else None + + _pos = self._io.pos() + self._io.seek(self.offset) + self._debug['_m_body']['start'] = self._io.pos() + self._m_body = self._io.read_bytes(self.size) + self._debug['_m_body']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_body if hasattr(self, '_m_body') else None + + + class Filename(KaitaiStruct): + SEQ_FIELDS = ["str"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['str']['start'] = self._io.pos() + self.str = (self._io.read_bytes_term(0, False, True, True)).decode(u"ASCII") + self._debug['str']['end'] = self._io.pos() + + + @property + def filenames(self): + if hasattr(self, '_m_filenames'): + return self._m_filenames if hasattr(self, '_m_filenames') else None + + _pos = self._io.pos() + self._io.seek((self.entries[-1].offset + self.entries[-1].size)) + self._debug['_m_filenames']['start'] = self._io.pos() + self._raw__m_filenames = [None] * (self.num_files) + self._m_filenames = [None] * (self.num_files) + for i in range(self.num_files): + if not 'arr' in self._debug['_m_filenames']: + self._debug['_m_filenames']['arr'] = [] + self._debug['_m_filenames']['arr'].append({'start': self._io.pos()}) + self._raw__m_filenames[i] = self._io.read_bytes(15) + io = KaitaiStream(BytesIO(self._raw__m_filenames[i])) + _t__m_filenames = self._root.Filename(io, self, self._root) + _t__m_filenames._read() + self._m_filenames[i] = _t__m_filenames + self._debug['_m_filenames']['arr'][i]['end'] = self._io.pos() + + self._debug['_m_filenames']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_filenames if hasattr(self, '_m_filenames') else None + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/heroes_of_might_and_magic_bmp.py b/python/examples/kaitai/kaitai_struct_formats/game/heroes_of_might_and_magic_bmp.py new file mode 100644 index 00000000..cc02696a --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/heroes_of_might_and_magic_bmp.py @@ -0,0 +1,34 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class HeroesOfMightAndMagicBmp(KaitaiStruct): + SEQ_FIELDS = ["magic", "width", "height", "data"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['magic']['start'] = self._io.pos() + self.magic = self._io.read_u2le() + self._debug['magic']['end'] = self._io.pos() + self._debug['width']['start'] = self._io.pos() + self.width = self._io.read_u2le() + self._debug['width']['end'] = self._io.pos() + self._debug['height']['start'] = self._io.pos() + self.height = self._io.read_u2le() + self._debug['height']['end'] = self._io.pos() + self._debug['data']['start'] = self._io.pos() + self.data = self._io.read_bytes((self.width * self.height)) + self._debug['data']['end'] = self._io.pos() + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/quake_mdl.py b/python/examples/kaitai/kaitai_struct_formats/game/quake_mdl.py new file mode 100644 index 00000000..7077e8f8 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/quake_mdl.py @@ -0,0 +1,377 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class QuakeMdl(KaitaiStruct): + SEQ_FIELDS = ["header", "skins", "texture_coordinates", "triangles", "frames"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['header']['start'] = self._io.pos() + self.header = self._root.MdlHeader(self._io, self, self._root) + self.header._read() + self._debug['header']['end'] = self._io.pos() + self._debug['skins']['start'] = self._io.pos() + self.skins = [None] * (self.header.num_skins) + for i in range(self.header.num_skins): + if not 'arr' in self._debug['skins']: + self._debug['skins']['arr'] = [] + self._debug['skins']['arr'].append({'start': self._io.pos()}) + _t_skins = self._root.MdlSkin(self._io, self, self._root) + _t_skins._read() + self.skins[i] = _t_skins + self._debug['skins']['arr'][i]['end'] = self._io.pos() + + self._debug['skins']['end'] = self._io.pos() + self._debug['texture_coordinates']['start'] = self._io.pos() + self.texture_coordinates = [None] * (self.header.num_verts) + for i in range(self.header.num_verts): + if not 'arr' in self._debug['texture_coordinates']: + self._debug['texture_coordinates']['arr'] = [] + self._debug['texture_coordinates']['arr'].append({'start': self._io.pos()}) + _t_texture_coordinates = self._root.MdlTexcoord(self._io, self, self._root) + _t_texture_coordinates._read() + self.texture_coordinates[i] = _t_texture_coordinates + self._debug['texture_coordinates']['arr'][i]['end'] = self._io.pos() + + self._debug['texture_coordinates']['end'] = self._io.pos() + self._debug['triangles']['start'] = self._io.pos() + self.triangles = [None] * (self.header.num_tris) + for i in range(self.header.num_tris): + if not 'arr' in self._debug['triangles']: + self._debug['triangles']['arr'] = [] + self._debug['triangles']['arr'].append({'start': self._io.pos()}) + _t_triangles = self._root.MdlTriangle(self._io, self, self._root) + _t_triangles._read() + self.triangles[i] = _t_triangles + self._debug['triangles']['arr'][i]['end'] = self._io.pos() + + self._debug['triangles']['end'] = self._io.pos() + self._debug['frames']['start'] = self._io.pos() + self.frames = [None] * (self.header.num_frames) + for i in range(self.header.num_frames): + if not 'arr' in self._debug['frames']: + self._debug['frames']['arr'] = [] + self._debug['frames']['arr'].append({'start': self._io.pos()}) + _t_frames = self._root.MdlFrame(self._io, self, self._root) + _t_frames._read() + self.frames[i] = _t_frames + self._debug['frames']['arr'][i]['end'] = self._io.pos() + + self._debug['frames']['end'] = self._io.pos() + + class MdlVertex(KaitaiStruct): + SEQ_FIELDS = ["values", "normal_index"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['values']['start'] = self._io.pos() + self.values = [None] * (3) + for i in range(3): + if not 'arr' in self._debug['values']: + self._debug['values']['arr'] = [] + self._debug['values']['arr'].append({'start': self._io.pos()}) + self.values[i] = self._io.read_u1() + self._debug['values']['arr'][i]['end'] = self._io.pos() + + self._debug['values']['end'] = self._io.pos() + self._debug['normal_index']['start'] = self._io.pos() + self.normal_index = self._io.read_u1() + self._debug['normal_index']['end'] = self._io.pos() + + + class MdlTexcoord(KaitaiStruct): + SEQ_FIELDS = ["on_seam", "s", "t"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['on_seam']['start'] = self._io.pos() + self.on_seam = self._io.read_s4le() + self._debug['on_seam']['end'] = self._io.pos() + self._debug['s']['start'] = self._io.pos() + self.s = self._io.read_s4le() + self._debug['s']['end'] = self._io.pos() + self._debug['t']['start'] = self._io.pos() + self.t = self._io.read_s4le() + self._debug['t']['end'] = self._io.pos() + + + class MdlHeader(KaitaiStruct): + SEQ_FIELDS = ["ident", "version_must_be_6", "scale", "origin", "radius", "eye_position", "num_skins", "skin_width", "skin_height", "num_verts", "num_tris", "num_frames", "synctype", "flags", "size"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['ident']['start'] = self._io.pos() + self.ident = self._io.ensure_fixed_contents(b"\x49\x44\x50\x4F") + self._debug['ident']['end'] = self._io.pos() + self._debug['version_must_be_6']['start'] = self._io.pos() + self.version_must_be_6 = self._io.ensure_fixed_contents(b"\x06\x00\x00\x00") + self._debug['version_must_be_6']['end'] = self._io.pos() + self._debug['scale']['start'] = self._io.pos() + self.scale = self._root.Vec3(self._io, self, self._root) + self.scale._read() + self._debug['scale']['end'] = self._io.pos() + self._debug['origin']['start'] = self._io.pos() + self.origin = self._root.Vec3(self._io, self, self._root) + self.origin._read() + self._debug['origin']['end'] = self._io.pos() + self._debug['radius']['start'] = self._io.pos() + self.radius = self._io.read_f4le() + self._debug['radius']['end'] = self._io.pos() + self._debug['eye_position']['start'] = self._io.pos() + self.eye_position = self._root.Vec3(self._io, self, self._root) + self.eye_position._read() + self._debug['eye_position']['end'] = self._io.pos() + self._debug['num_skins']['start'] = self._io.pos() + self.num_skins = self._io.read_s4le() + self._debug['num_skins']['end'] = self._io.pos() + self._debug['skin_width']['start'] = self._io.pos() + self.skin_width = self._io.read_s4le() + self._debug['skin_width']['end'] = self._io.pos() + self._debug['skin_height']['start'] = self._io.pos() + self.skin_height = self._io.read_s4le() + self._debug['skin_height']['end'] = self._io.pos() + self._debug['num_verts']['start'] = self._io.pos() + self.num_verts = self._io.read_s4le() + self._debug['num_verts']['end'] = self._io.pos() + self._debug['num_tris']['start'] = self._io.pos() + self.num_tris = self._io.read_s4le() + self._debug['num_tris']['end'] = self._io.pos() + self._debug['num_frames']['start'] = self._io.pos() + self.num_frames = self._io.read_s4le() + self._debug['num_frames']['end'] = self._io.pos() + self._debug['synctype']['start'] = self._io.pos() + self.synctype = self._io.read_s4le() + self._debug['synctype']['end'] = self._io.pos() + self._debug['flags']['start'] = self._io.pos() + self.flags = self._io.read_s4le() + self._debug['flags']['end'] = self._io.pos() + self._debug['size']['start'] = self._io.pos() + self.size = self._io.read_f4le() + self._debug['size']['end'] = self._io.pos() + + @property + def version(self): + if hasattr(self, '_m_version'): + return self._m_version if hasattr(self, '_m_version') else None + + self._m_version = 6 + return self._m_version if hasattr(self, '_m_version') else None + + @property + def skin_size(self): + if hasattr(self, '_m_skin_size'): + return self._m_skin_size if hasattr(self, '_m_skin_size') else None + + self._m_skin_size = (self.skin_width * self.skin_height) + return self._m_skin_size if hasattr(self, '_m_skin_size') else None + + + class MdlSkin(KaitaiStruct): + SEQ_FIELDS = ["group", "single_texture_data", "num_frames", "frame_times", "group_texture_data"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['group']['start'] = self._io.pos() + self.group = self._io.read_s4le() + self._debug['group']['end'] = self._io.pos() + if self.group == 0: + self._debug['single_texture_data']['start'] = self._io.pos() + self.single_texture_data = self._io.read_bytes(self._root.header.skin_size) + self._debug['single_texture_data']['end'] = self._io.pos() + + if self.group != 0: + self._debug['num_frames']['start'] = self._io.pos() + self.num_frames = self._io.read_u4le() + self._debug['num_frames']['end'] = self._io.pos() + + if self.group != 0: + self._debug['frame_times']['start'] = self._io.pos() + self.frame_times = [None] * (self.num_frames) + for i in range(self.num_frames): + if not 'arr' in self._debug['frame_times']: + self._debug['frame_times']['arr'] = [] + self._debug['frame_times']['arr'].append({'start': self._io.pos()}) + self.frame_times[i] = self._io.read_f4le() + self._debug['frame_times']['arr'][i]['end'] = self._io.pos() + + self._debug['frame_times']['end'] = self._io.pos() + + if self.group != 0: + self._debug['group_texture_data']['start'] = self._io.pos() + self.group_texture_data = [None] * (self.num_frames) + for i in range(self.num_frames): + if not 'arr' in self._debug['group_texture_data']: + self._debug['group_texture_data']['arr'] = [] + self._debug['group_texture_data']['arr'].append({'start': self._io.pos()}) + self.group_texture_data[i] = self._io.read_bytes(self._root.header.skin_size) + self._debug['group_texture_data']['arr'][i]['end'] = self._io.pos() + + self._debug['group_texture_data']['end'] = self._io.pos() + + + + class MdlFrame(KaitaiStruct): + SEQ_FIELDS = ["type", "min", "max", "time", "frames"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['type']['start'] = self._io.pos() + self.type = self._io.read_s4le() + self._debug['type']['end'] = self._io.pos() + if self.type != 0: + self._debug['min']['start'] = self._io.pos() + self.min = self._root.MdlVertex(self._io, self, self._root) + self.min._read() + self._debug['min']['end'] = self._io.pos() + + if self.type != 0: + self._debug['max']['start'] = self._io.pos() + self.max = self._root.MdlVertex(self._io, self, self._root) + self.max._read() + self._debug['max']['end'] = self._io.pos() + + if self.type != 0: + self._debug['time']['start'] = self._io.pos() + self.time = [None] * (self.type) + for i in range(self.type): + if not 'arr' in self._debug['time']: + self._debug['time']['arr'] = [] + self._debug['time']['arr'].append({'start': self._io.pos()}) + self.time[i] = self._io.read_f4le() + self._debug['time']['arr'][i]['end'] = self._io.pos() + + self._debug['time']['end'] = self._io.pos() + + self._debug['frames']['start'] = self._io.pos() + self.frames = [None] * (self.num_simple_frames) + for i in range(self.num_simple_frames): + if not 'arr' in self._debug['frames']: + self._debug['frames']['arr'] = [] + self._debug['frames']['arr'].append({'start': self._io.pos()}) + _t_frames = self._root.MdlSimpleFrame(self._io, self, self._root) + _t_frames._read() + self.frames[i] = _t_frames + self._debug['frames']['arr'][i]['end'] = self._io.pos() + + self._debug['frames']['end'] = self._io.pos() + + @property + def num_simple_frames(self): + if hasattr(self, '_m_num_simple_frames'): + return self._m_num_simple_frames if hasattr(self, '_m_num_simple_frames') else None + + self._m_num_simple_frames = (1 if self.type == 0 else self.type) + return self._m_num_simple_frames if hasattr(self, '_m_num_simple_frames') else None + + + class MdlSimpleFrame(KaitaiStruct): + SEQ_FIELDS = ["bbox_min", "bbox_max", "name", "vertices"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['bbox_min']['start'] = self._io.pos() + self.bbox_min = self._root.MdlVertex(self._io, self, self._root) + self.bbox_min._read() + self._debug['bbox_min']['end'] = self._io.pos() + self._debug['bbox_max']['start'] = self._io.pos() + self.bbox_max = self._root.MdlVertex(self._io, self, self._root) + self.bbox_max._read() + self._debug['bbox_max']['end'] = self._io.pos() + self._debug['name']['start'] = self._io.pos() + self.name = (KaitaiStream.bytes_terminate(KaitaiStream.bytes_strip_right(self._io.read_bytes(16), 0), 0, False)).decode(u"ASCII") + self._debug['name']['end'] = self._io.pos() + self._debug['vertices']['start'] = self._io.pos() + self.vertices = [None] * (self._root.header.num_verts) + for i in range(self._root.header.num_verts): + if not 'arr' in self._debug['vertices']: + self._debug['vertices']['arr'] = [] + self._debug['vertices']['arr'].append({'start': self._io.pos()}) + _t_vertices = self._root.MdlVertex(self._io, self, self._root) + _t_vertices._read() + self.vertices[i] = _t_vertices + self._debug['vertices']['arr'][i]['end'] = self._io.pos() + + self._debug['vertices']['end'] = self._io.pos() + + + class MdlTriangle(KaitaiStruct): + SEQ_FIELDS = ["faces_front", "vertices"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['faces_front']['start'] = self._io.pos() + self.faces_front = self._io.read_s4le() + self._debug['faces_front']['end'] = self._io.pos() + self._debug['vertices']['start'] = self._io.pos() + self.vertices = [None] * (3) + for i in range(3): + if not 'arr' in self._debug['vertices']: + self._debug['vertices']['arr'] = [] + self._debug['vertices']['arr'].append({'start': self._io.pos()}) + self.vertices[i] = self._io.read_s4le() + self._debug['vertices']['arr'][i]['end'] = self._io.pos() + + self._debug['vertices']['end'] = self._io.pos() + + + class Vec3(KaitaiStruct): + SEQ_FIELDS = ["x", "y", "z"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['x']['start'] = self._io.pos() + self.x = self._io.read_f4le() + self._debug['x']['end'] = self._io.pos() + self._debug['y']['start'] = self._io.pos() + self.y = self._io.read_f4le() + self._debug['y']['end'] = self._io.pos() + self._debug['z']['start'] = self._io.pos() + self.z = self._io.read_f4le() + self._debug['z']['end'] = self._io.pos() + + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/quake_pak.py b/python/examples/kaitai/kaitai_struct_formats/game/quake_pak.py new file mode 100644 index 00000000..3b4c0358 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/quake_pak.py @@ -0,0 +1,110 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class QuakePak(KaitaiStruct): + """ + .. seealso:: + Source - https://quakewiki.org/wiki/.pak#Format_specification + """ + SEQ_FIELDS = ["magic", "ofs_index", "len_index"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['magic']['start'] = self._io.pos() + self.magic = self._io.ensure_fixed_contents(b"\x50\x41\x43\x4B") + self._debug['magic']['end'] = self._io.pos() + self._debug['ofs_index']['start'] = self._io.pos() + self.ofs_index = self._io.read_u4le() + self._debug['ofs_index']['end'] = self._io.pos() + self._debug['len_index']['start'] = self._io.pos() + self.len_index = self._io.read_u4le() + self._debug['len_index']['end'] = self._io.pos() + + class IndexStruct(KaitaiStruct): + SEQ_FIELDS = ["entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['entries']['start'] = self._io.pos() + self.entries = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = self._root.IndexEntry(self._io, self, self._root) + _t_entries._read() + self.entries.append(_t_entries) + self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['entries']['end'] = self._io.pos() + + + class IndexEntry(KaitaiStruct): + SEQ_FIELDS = ["name", "ofs", "size"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['name']['start'] = self._io.pos() + self.name = (KaitaiStream.bytes_terminate(KaitaiStream.bytes_strip_right(self._io.read_bytes(56), 0), 0, False)).decode(u"UTF-8") + self._debug['name']['end'] = self._io.pos() + self._debug['ofs']['start'] = self._io.pos() + self.ofs = self._io.read_u4le() + self._debug['ofs']['end'] = self._io.pos() + self._debug['size']['start'] = self._io.pos() + self.size = self._io.read_u4le() + self._debug['size']['end'] = self._io.pos() + + @property + def body(self): + if hasattr(self, '_m_body'): + return self._m_body if hasattr(self, '_m_body') else None + + io = self._root._io + _pos = io.pos() + io.seek(self.ofs) + self._debug['_m_body']['start'] = io.pos() + self._m_body = io.read_bytes(self.size) + self._debug['_m_body']['end'] = io.pos() + io.seek(_pos) + return self._m_body if hasattr(self, '_m_body') else None + + + @property + def index(self): + if hasattr(self, '_m_index'): + return self._m_index if hasattr(self, '_m_index') else None + + _pos = self._io.pos() + self._io.seek(self.ofs_index) + self._debug['_m_index']['start'] = self._io.pos() + self._raw__m_index = self._io.read_bytes(self.len_index) + io = KaitaiStream(BytesIO(self._raw__m_index)) + self._m_index = self._root.IndexStruct(io, self, self._root) + self._m_index._read() + self._debug['_m_index']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_index if hasattr(self, '_m_index') else None + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/renderware_binary_stream.py b/python/examples/kaitai/kaitai_struct_formats/game/renderware_binary_stream.py new file mode 100644 index 00000000..5e27c895 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/renderware_binary_stream.py @@ -0,0 +1,774 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +from enum import Enum +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class RenderwareBinaryStream(KaitaiStruct): + """ + .. seealso:: + Source - https://www.gtamodding.com/wiki/RenderWare_binary_stream_file + """ + + class Sections(Enum): + struct = 1 + string = 2 + extension = 3 + camera = 5 + texture = 6 + material = 7 + material_list = 8 + atomic_section = 9 + plane_section = 10 + world = 11 + spline = 12 + matrix = 13 + frame_list = 14 + geometry = 15 + clump = 16 + light = 18 + unicode_string = 19 + atomic = 20 + texture_native = 21 + texture_dictionary = 22 + animation_database = 23 + image = 24 + skin_animation = 25 + geometry_list = 26 + anim_animation = 27 + team = 28 + crowd = 29 + delta_morph_animation = 30 + right_to_render = 31 + multitexture_effect_native = 32 + multitexture_effect_dictionary = 33 + team_dictionary = 34 + platform_independent_texture_dictionary = 35 + table_of_contents = 36 + particle_standard_global_data = 37 + altpipe = 38 + platform_independent_peds = 39 + patch_mesh = 40 + chunk_group_start = 41 + chunk_group_end = 42 + uv_animation_dictionary = 43 + coll_tree = 44 + metrics_plg = 257 + spline_plg = 258 + stereo_plg = 259 + vrml_plg = 260 + morph_plg = 261 + pvs_plg = 262 + memory_leak_plg = 263 + animation_plg = 264 + gloss_plg = 265 + logo_plg = 266 + memory_info_plg = 267 + random_plg = 268 + png_image_plg = 269 + bone_plg = 270 + vrml_anim_plg = 271 + sky_mipmap_val = 272 + mrm_plg = 273 + lod_atomic_plg = 274 + me_plg = 275 + lightmap_plg = 276 + refine_plg = 277 + skin_plg = 278 + label_plg = 279 + particles_plg = 280 + geomtx_plg = 281 + synth_core_plg = 282 + stqpp_plg = 283 + part_pp_plg = 284 + collision_plg = 285 + hanim_plg = 286 + user_data_plg = 287 + material_effects_plg = 288 + particle_system_plg = 289 + delta_morph_plg = 290 + patch_plg = 291 + team_plg = 292 + crowd_pp_plg = 293 + mip_split_plg = 294 + anisotropy_plg = 295 + gcn_material_plg = 297 + geometric_pvs_plg = 298 + xbox_material_plg = 299 + multi_texture_plg = 300 + chain_plg = 301 + toon_plg = 302 + ptank_plg = 303 + particle_standard_plg = 304 + pds_plg = 305 + prtadv_plg = 306 + normal_map_plg = 307 + adc_plg = 308 + uv_animation_plg = 309 + character_set_plg = 384 + nohs_world_plg = 385 + import_util_plg = 386 + slerp_plg = 387 + optim_plg = 388 + tl_world_plg = 389 + database_plg = 390 + raytrace_plg = 391 + ray_plg = 392 + library_plg = 393 + plg_2d = 400 + tile_render_plg = 401 + jpeg_image_plg = 402 + tga_image_plg = 403 + gif_image_plg = 404 + quat_plg = 405 + spline_pvs_plg = 406 + mipmap_plg = 407 + mipmapk_plg = 408 + font_2d = 409 + intersection_plg = 410 + tiff_image_plg = 411 + pick_plg = 412 + bmp_image_plg = 413 + ras_image_plg = 414 + skin_fx_plg = 415 + vcat_plg = 416 + path_2d = 417 + brush_2d = 418 + object_2d = 419 + shape_2d = 420 + scene_2d = 421 + pick_region_2d = 422 + object_string_2d = 423 + animation_plg_2d = 424 + animation_2d = 425 + keyframe_2d = 432 + maestro_2d = 433 + barycentric = 434 + platform_independent_texture_dictionary_tk = 435 + toc_tk = 436 + tpl_tk = 437 + altpipe_tk = 438 + animation_tk = 439 + skin_split_tookit = 440 + compressed_key_tk = 441 + geometry_conditioning_plg = 442 + wing_plg = 443 + generic_pipeline_tk = 444 + lightmap_conversion_tk = 445 + filesystem_plg = 446 + dictionary_tk = 447 + uv_animation_linear = 448 + uv_animation_parameter = 449 + bin_mesh_plg = 1294 + native_data_plg = 1296 + zmodeler_lock = 61982 + atomic_visibility_distance = 39055872 + clump_visibility_distance = 39055873 + frame_visibility_distance = 39055874 + pipeline_set = 39056115 + unused_5 = 39056116 + texdictionary_link = 39056117 + specular_material = 39056118 + unused_8 = 39056119 + effect_2d = 39056120 + extra_vert_colour = 39056121 + collision_model = 39056122 + gta_hanim = 39056123 + reflection_material = 39056124 + breakable = 39056125 + frame = 39056126 + unused_16 = 39056127 + SEQ_FIELDS = ["code", "size", "version", "body"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['code']['start'] = self._io.pos() + self.code = KaitaiStream.resolve_enum(self._root.Sections, self._io.read_u4le()) + self._debug['code']['end'] = self._io.pos() + self._debug['size']['start'] = self._io.pos() + self.size = self._io.read_u4le() + self._debug['size']['end'] = self._io.pos() + self._debug['version']['start'] = self._io.pos() + self.version = self._io.read_u4le() + self._debug['version']['end'] = self._io.pos() + self._debug['body']['start'] = self._io.pos() + _on = self.code + if _on == self._root.Sections.geometry: + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.ListWithHeader(io, self, self._root) + self.body._read() + elif _on == self._root.Sections.texture_dictionary: + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.ListWithHeader(io, self, self._root) + self.body._read() + elif _on == self._root.Sections.geometry_list: + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.ListWithHeader(io, self, self._root) + self.body._read() + elif _on == self._root.Sections.texture_native: + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.ListWithHeader(io, self, self._root) + self.body._read() + elif _on == self._root.Sections.clump: + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.ListWithHeader(io, self, self._root) + self.body._read() + elif _on == self._root.Sections.frame_list: + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.ListWithHeader(io, self, self._root) + self.body._read() + else: + self.body = self._io.read_bytes(self.size) + self._debug['body']['end'] = self._io.pos() + + class StructClump(KaitaiStruct): + """ + .. seealso:: + Source - https://www.gtamodding.com/wiki/RpClump + """ + SEQ_FIELDS = ["num_atomics", "num_lights", "num_cameras"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['num_atomics']['start'] = self._io.pos() + self.num_atomics = self._io.read_u4le() + self._debug['num_atomics']['end'] = self._io.pos() + if self._parent.version >= 208896: + self._debug['num_lights']['start'] = self._io.pos() + self.num_lights = self._io.read_u4le() + self._debug['num_lights']['end'] = self._io.pos() + + if self._parent.version >= 208896: + self._debug['num_cameras']['start'] = self._io.pos() + self.num_cameras = self._io.read_u4le() + self._debug['num_cameras']['end'] = self._io.pos() + + + + class StructGeometry(KaitaiStruct): + """ + .. seealso:: + Source - https://www.gtamodding.com/wiki/RpGeometry + """ + SEQ_FIELDS = ["format", "num_triangles", "num_vertices", "num_morph_targets", "surf_prop", "geometry", "morph_targets"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['format']['start'] = self._io.pos() + self.format = self._io.read_u4le() + self._debug['format']['end'] = self._io.pos() + self._debug['num_triangles']['start'] = self._io.pos() + self.num_triangles = self._io.read_u4le() + self._debug['num_triangles']['end'] = self._io.pos() + self._debug['num_vertices']['start'] = self._io.pos() + self.num_vertices = self._io.read_u4le() + self._debug['num_vertices']['end'] = self._io.pos() + self._debug['num_morph_targets']['start'] = self._io.pos() + self.num_morph_targets = self._io.read_u4le() + self._debug['num_morph_targets']['end'] = self._io.pos() + if self._parent.version < 212992: + self._debug['surf_prop']['start'] = self._io.pos() + self.surf_prop = self._root.SurfaceProperties(self._io, self, self._root) + self.surf_prop._read() + self._debug['surf_prop']['end'] = self._io.pos() + + if not (self.is_native): + self._debug['geometry']['start'] = self._io.pos() + self.geometry = self._root.GeometryNonNative(self._io, self, self._root) + self.geometry._read() + self._debug['geometry']['end'] = self._io.pos() + + self._debug['morph_targets']['start'] = self._io.pos() + self.morph_targets = [None] * (self.num_morph_targets) + for i in range(self.num_morph_targets): + if not 'arr' in self._debug['morph_targets']: + self._debug['morph_targets']['arr'] = [] + self._debug['morph_targets']['arr'].append({'start': self._io.pos()}) + _t_morph_targets = self._root.MorphTarget(self._io, self, self._root) + _t_morph_targets._read() + self.morph_targets[i] = _t_morph_targets + self._debug['morph_targets']['arr'][i]['end'] = self._io.pos() + + self._debug['morph_targets']['end'] = self._io.pos() + + @property + def is_textured(self): + if hasattr(self, '_m_is_textured'): + return self._m_is_textured if hasattr(self, '_m_is_textured') else None + + self._m_is_textured = (self.format & 4) != 0 + return self._m_is_textured if hasattr(self, '_m_is_textured') else None + + @property + def is_prelit(self): + if hasattr(self, '_m_is_prelit'): + return self._m_is_prelit if hasattr(self, '_m_is_prelit') else None + + self._m_is_prelit = (self.format & 8) != 0 + return self._m_is_prelit if hasattr(self, '_m_is_prelit') else None + + @property + def is_textured2(self): + if hasattr(self, '_m_is_textured2'): + return self._m_is_textured2 if hasattr(self, '_m_is_textured2') else None + + self._m_is_textured2 = (self.format & 128) != 0 + return self._m_is_textured2 if hasattr(self, '_m_is_textured2') else None + + @property + def is_native(self): + if hasattr(self, '_m_is_native'): + return self._m_is_native if hasattr(self, '_m_is_native') else None + + self._m_is_native = (self.format & 16777216) != 0 + return self._m_is_native if hasattr(self, '_m_is_native') else None + + + class GeometryNonNative(KaitaiStruct): + SEQ_FIELDS = ["prelit_colors", "tex_coords", "triangles"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + if self._parent.is_prelit: + self._debug['prelit_colors']['start'] = self._io.pos() + self.prelit_colors = [None] * (self._parent.num_vertices) + for i in range(self._parent.num_vertices): + if not 'arr' in self._debug['prelit_colors']: + self._debug['prelit_colors']['arr'] = [] + self._debug['prelit_colors']['arr'].append({'start': self._io.pos()}) + _t_prelit_colors = self._root.Rgba(self._io, self, self._root) + _t_prelit_colors._read() + self.prelit_colors[i] = _t_prelit_colors + self._debug['prelit_colors']['arr'][i]['end'] = self._io.pos() + + self._debug['prelit_colors']['end'] = self._io.pos() + + if ((self._parent.is_textured) or (self._parent.is_textured2)) : + self._debug['tex_coords']['start'] = self._io.pos() + self.tex_coords = [None] * (self._parent.num_vertices) + for i in range(self._parent.num_vertices): + if not 'arr' in self._debug['tex_coords']: + self._debug['tex_coords']['arr'] = [] + self._debug['tex_coords']['arr'].append({'start': self._io.pos()}) + _t_tex_coords = self._root.TexCoord(self._io, self, self._root) + _t_tex_coords._read() + self.tex_coords[i] = _t_tex_coords + self._debug['tex_coords']['arr'][i]['end'] = self._io.pos() + + self._debug['tex_coords']['end'] = self._io.pos() + + self._debug['triangles']['start'] = self._io.pos() + self.triangles = [None] * (self._parent.num_triangles) + for i in range(self._parent.num_triangles): + if not 'arr' in self._debug['triangles']: + self._debug['triangles']['arr'] = [] + self._debug['triangles']['arr'].append({'start': self._io.pos()}) + _t_triangles = self._root.Triangle(self._io, self, self._root) + _t_triangles._read() + self.triangles[i] = _t_triangles + self._debug['triangles']['arr'][i]['end'] = self._io.pos() + + self._debug['triangles']['end'] = self._io.pos() + + + class StructGeometryList(KaitaiStruct): + """ + .. seealso:: + Source - https://www.gtamodding.com/wiki/Geometry_List_(RW_Section)#Structure + """ + SEQ_FIELDS = ["num_geometries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['num_geometries']['start'] = self._io.pos() + self.num_geometries = self._io.read_u4le() + self._debug['num_geometries']['end'] = self._io.pos() + + + class Rgba(KaitaiStruct): + SEQ_FIELDS = ["r", "g", "b", "a"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['r']['start'] = self._io.pos() + self.r = self._io.read_u1() + self._debug['r']['end'] = self._io.pos() + self._debug['g']['start'] = self._io.pos() + self.g = self._io.read_u1() + self._debug['g']['end'] = self._io.pos() + self._debug['b']['start'] = self._io.pos() + self.b = self._io.read_u1() + self._debug['b']['end'] = self._io.pos() + self._debug['a']['start'] = self._io.pos() + self.a = self._io.read_u1() + self._debug['a']['end'] = self._io.pos() + + + class Sphere(KaitaiStruct): + SEQ_FIELDS = ["x", "y", "z", "radius"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['x']['start'] = self._io.pos() + self.x = self._io.read_f4le() + self._debug['x']['end'] = self._io.pos() + self._debug['y']['start'] = self._io.pos() + self.y = self._io.read_f4le() + self._debug['y']['end'] = self._io.pos() + self._debug['z']['start'] = self._io.pos() + self.z = self._io.read_f4le() + self._debug['z']['end'] = self._io.pos() + self._debug['radius']['start'] = self._io.pos() + self.radius = self._io.read_f4le() + self._debug['radius']['end'] = self._io.pos() + + + class MorphTarget(KaitaiStruct): + SEQ_FIELDS = ["bounding_sphere", "has_vertices", "has_normals", "vertices", "normals"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['bounding_sphere']['start'] = self._io.pos() + self.bounding_sphere = self._root.Sphere(self._io, self, self._root) + self.bounding_sphere._read() + self._debug['bounding_sphere']['end'] = self._io.pos() + self._debug['has_vertices']['start'] = self._io.pos() + self.has_vertices = self._io.read_u4le() + self._debug['has_vertices']['end'] = self._io.pos() + self._debug['has_normals']['start'] = self._io.pos() + self.has_normals = self._io.read_u4le() + self._debug['has_normals']['end'] = self._io.pos() + if self.has_vertices != 0: + self._debug['vertices']['start'] = self._io.pos() + self.vertices = [None] * (self._parent.num_vertices) + for i in range(self._parent.num_vertices): + if not 'arr' in self._debug['vertices']: + self._debug['vertices']['arr'] = [] + self._debug['vertices']['arr'].append({'start': self._io.pos()}) + _t_vertices = self._root.Vector3d(self._io, self, self._root) + _t_vertices._read() + self.vertices[i] = _t_vertices + self._debug['vertices']['arr'][i]['end'] = self._io.pos() + + self._debug['vertices']['end'] = self._io.pos() + + if self.has_normals != 0: + self._debug['normals']['start'] = self._io.pos() + self.normals = [None] * (self._parent.num_vertices) + for i in range(self._parent.num_vertices): + if not 'arr' in self._debug['normals']: + self._debug['normals']['arr'] = [] + self._debug['normals']['arr'].append({'start': self._io.pos()}) + _t_normals = self._root.Vector3d(self._io, self, self._root) + _t_normals._read() + self.normals[i] = _t_normals + self._debug['normals']['arr'][i]['end'] = self._io.pos() + + self._debug['normals']['end'] = self._io.pos() + + + + class SurfaceProperties(KaitaiStruct): + """ + .. seealso:: + Source - https://www.gtamodding.com/wiki/RpGeometry + """ + SEQ_FIELDS = ["ambient", "specular", "diffuse"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['ambient']['start'] = self._io.pos() + self.ambient = self._io.read_f4le() + self._debug['ambient']['end'] = self._io.pos() + self._debug['specular']['start'] = self._io.pos() + self.specular = self._io.read_f4le() + self._debug['specular']['end'] = self._io.pos() + self._debug['diffuse']['start'] = self._io.pos() + self.diffuse = self._io.read_f4le() + self._debug['diffuse']['end'] = self._io.pos() + + + class StructFrameList(KaitaiStruct): + """ + .. seealso:: + Source - https://www.gtamodding.com/wiki/Frame_List_(RW_Section)#Structure + """ + SEQ_FIELDS = ["num_frames", "frames"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['num_frames']['start'] = self._io.pos() + self.num_frames = self._io.read_u4le() + self._debug['num_frames']['end'] = self._io.pos() + self._debug['frames']['start'] = self._io.pos() + self.frames = [None] * (self.num_frames) + for i in range(self.num_frames): + if not 'arr' in self._debug['frames']: + self._debug['frames']['arr'] = [] + self._debug['frames']['arr'].append({'start': self._io.pos()}) + _t_frames = self._root.Frame(self._io, self, self._root) + _t_frames._read() + self.frames[i] = _t_frames + self._debug['frames']['arr'][i]['end'] = self._io.pos() + + self._debug['frames']['end'] = self._io.pos() + + + class Matrix(KaitaiStruct): + """ + .. seealso:: + Source - https://www.gtamodding.com/wiki/Frame_List_(RW_Section)#Structure + """ + SEQ_FIELDS = ["entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['entries']['start'] = self._io.pos() + self.entries = [None] * (3) + for i in range(3): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = self._root.Vector3d(self._io, self, self._root) + _t_entries._read() + self.entries[i] = _t_entries + self._debug['entries']['arr'][i]['end'] = self._io.pos() + + self._debug['entries']['end'] = self._io.pos() + + + class Vector3d(KaitaiStruct): + """ + .. seealso:: + Source - https://www.gtamodding.com/wiki/Frame_List_(RW_Section)#Structure + """ + SEQ_FIELDS = ["x", "y", "z"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['x']['start'] = self._io.pos() + self.x = self._io.read_f4le() + self._debug['x']['end'] = self._io.pos() + self._debug['y']['start'] = self._io.pos() + self.y = self._io.read_f4le() + self._debug['y']['end'] = self._io.pos() + self._debug['z']['start'] = self._io.pos() + self.z = self._io.read_f4le() + self._debug['z']['end'] = self._io.pos() + + + class ListWithHeader(KaitaiStruct): + """Typical structure used by many data types in RenderWare binary + stream. Substream contains a list of binary stream entries, + first entry always has type "struct" and carries some specific + binary data it in, determined by the type of parent. All other + entries, beside the first one, are normal, self-describing + records. + """ + SEQ_FIELDS = ["code", "header_size", "version", "header", "entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['code']['start'] = self._io.pos() + self.code = self._io.ensure_fixed_contents(b"\x01\x00\x00\x00") + self._debug['code']['end'] = self._io.pos() + self._debug['header_size']['start'] = self._io.pos() + self.header_size = self._io.read_u4le() + self._debug['header_size']['end'] = self._io.pos() + self._debug['version']['start'] = self._io.pos() + self.version = self._io.read_u4le() + self._debug['version']['end'] = self._io.pos() + self._debug['header']['start'] = self._io.pos() + _on = self._parent.code + if _on == self._root.Sections.geometry: + self._raw_header = self._io.read_bytes(self.header_size) + io = KaitaiStream(BytesIO(self._raw_header)) + self.header = self._root.StructGeometry(io, self, self._root) + self.header._read() + elif _on == self._root.Sections.texture_dictionary: + self._raw_header = self._io.read_bytes(self.header_size) + io = KaitaiStream(BytesIO(self._raw_header)) + self.header = self._root.StructTextureDictionary(io, self, self._root) + self.header._read() + elif _on == self._root.Sections.geometry_list: + self._raw_header = self._io.read_bytes(self.header_size) + io = KaitaiStream(BytesIO(self._raw_header)) + self.header = self._root.StructGeometryList(io, self, self._root) + self.header._read() + elif _on == self._root.Sections.clump: + self._raw_header = self._io.read_bytes(self.header_size) + io = KaitaiStream(BytesIO(self._raw_header)) + self.header = self._root.StructClump(io, self, self._root) + self.header._read() + elif _on == self._root.Sections.frame_list: + self._raw_header = self._io.read_bytes(self.header_size) + io = KaitaiStream(BytesIO(self._raw_header)) + self.header = self._root.StructFrameList(io, self, self._root) + self.header._read() + else: + self.header = self._io.read_bytes(self.header_size) + self._debug['header']['end'] = self._io.pos() + self._debug['entries']['start'] = self._io.pos() + self.entries = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = RenderwareBinaryStream(self._io) + _t_entries._read() + self.entries.append(_t_entries) + self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['entries']['end'] = self._io.pos() + + + class Triangle(KaitaiStruct): + SEQ_FIELDS = ["vertex2", "vertex1", "material_id", "vertex3"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['vertex2']['start'] = self._io.pos() + self.vertex2 = self._io.read_u2le() + self._debug['vertex2']['end'] = self._io.pos() + self._debug['vertex1']['start'] = self._io.pos() + self.vertex1 = self._io.read_u2le() + self._debug['vertex1']['end'] = self._io.pos() + self._debug['material_id']['start'] = self._io.pos() + self.material_id = self._io.read_u2le() + self._debug['material_id']['end'] = self._io.pos() + self._debug['vertex3']['start'] = self._io.pos() + self.vertex3 = self._io.read_u2le() + self._debug['vertex3']['end'] = self._io.pos() + + + class Frame(KaitaiStruct): + """ + .. seealso:: + Source - https://www.gtamodding.com/wiki/Frame_List_(RW_Section)#Structure + """ + SEQ_FIELDS = ["rotation_matrix", "position", "cur_frame_idx", "matrix_creation_flags"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['rotation_matrix']['start'] = self._io.pos() + self.rotation_matrix = self._root.Matrix(self._io, self, self._root) + self.rotation_matrix._read() + self._debug['rotation_matrix']['end'] = self._io.pos() + self._debug['position']['start'] = self._io.pos() + self.position = self._root.Vector3d(self._io, self, self._root) + self.position._read() + self._debug['position']['end'] = self._io.pos() + self._debug['cur_frame_idx']['start'] = self._io.pos() + self.cur_frame_idx = self._io.read_s4le() + self._debug['cur_frame_idx']['end'] = self._io.pos() + self._debug['matrix_creation_flags']['start'] = self._io.pos() + self.matrix_creation_flags = self._io.read_u4le() + self._debug['matrix_creation_flags']['end'] = self._io.pos() + + + class TexCoord(KaitaiStruct): + SEQ_FIELDS = ["u", "v"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['u']['start'] = self._io.pos() + self.u = self._io.read_f4le() + self._debug['u']['end'] = self._io.pos() + self._debug['v']['start'] = self._io.pos() + self.v = self._io.read_f4le() + self._debug['v']['end'] = self._io.pos() + + + class StructTextureDictionary(KaitaiStruct): + SEQ_FIELDS = ["num_textures"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['num_textures']['start'] = self._io.pos() + self.num_textures = self._io.read_u4le() + self._debug['num_textures']['end'] = self._io.pos() + + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/saints_row_2_vpp_pc.py b/python/examples/kaitai/kaitai_struct_formats/game/saints_row_2_vpp_pc.py new file mode 100644 index 00000000..91be64ea --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/saints_row_2_vpp_pc.py @@ -0,0 +1,252 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class SaintsRow2VppPc(KaitaiStruct): + SEQ_FIELDS = ["magic", "pad1", "num_files", "container_size", "len_offsets", "len_filenames", "len_extensions", "smth5", "smth6", "smth7", "smth8", "smth9"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['magic']['start'] = self._io.pos() + self.magic = self._io.ensure_fixed_contents(b"\xCE\x0A\x89\x51\x04") + self._debug['magic']['end'] = self._io.pos() + self._debug['pad1']['start'] = self._io.pos() + self.pad1 = self._io.read_bytes(335) + self._debug['pad1']['end'] = self._io.pos() + self._debug['num_files']['start'] = self._io.pos() + self.num_files = self._io.read_s4le() + self._debug['num_files']['end'] = self._io.pos() + self._debug['container_size']['start'] = self._io.pos() + self.container_size = self._io.read_s4le() + self._debug['container_size']['end'] = self._io.pos() + self._debug['len_offsets']['start'] = self._io.pos() + self.len_offsets = self._io.read_s4le() + self._debug['len_offsets']['end'] = self._io.pos() + self._debug['len_filenames']['start'] = self._io.pos() + self.len_filenames = self._io.read_s4le() + self._debug['len_filenames']['end'] = self._io.pos() + self._debug['len_extensions']['start'] = self._io.pos() + self.len_extensions = self._io.read_s4le() + self._debug['len_extensions']['end'] = self._io.pos() + self._debug['smth5']['start'] = self._io.pos() + self.smth5 = self._io.read_s4le() + self._debug['smth5']['end'] = self._io.pos() + self._debug['smth6']['start'] = self._io.pos() + self.smth6 = self._io.read_s4le() + self._debug['smth6']['end'] = self._io.pos() + self._debug['smth7']['start'] = self._io.pos() + self.smth7 = self._io.read_s4le() + self._debug['smth7']['end'] = self._io.pos() + self._debug['smth8']['start'] = self._io.pos() + self.smth8 = self._io.read_s4le() + self._debug['smth8']['end'] = self._io.pos() + self._debug['smth9']['start'] = self._io.pos() + self.smth9 = self._io.read_s4le() + self._debug['smth9']['end'] = self._io.pos() + + class Offsets(KaitaiStruct): + SEQ_FIELDS = ["entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['entries']['start'] = self._io.pos() + self.entries = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + _t_entries = self._root.Offsets.Offset(self._io, self, self._root) + _t_entries._read() + self.entries.append(_t_entries) + self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['entries']['end'] = self._io.pos() + + class Offset(KaitaiStruct): + SEQ_FIELDS = ["name_ofs", "ext_ofs", "smth2", "ofs_body", "len_body", "always_minus_1", "always_zero"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['name_ofs']['start'] = self._io.pos() + self.name_ofs = self._io.read_u4le() + self._debug['name_ofs']['end'] = self._io.pos() + self._debug['ext_ofs']['start'] = self._io.pos() + self.ext_ofs = self._io.read_u4le() + self._debug['ext_ofs']['end'] = self._io.pos() + self._debug['smth2']['start'] = self._io.pos() + self.smth2 = self._io.read_s4le() + self._debug['smth2']['end'] = self._io.pos() + self._debug['ofs_body']['start'] = self._io.pos() + self.ofs_body = self._io.read_s4le() + self._debug['ofs_body']['end'] = self._io.pos() + self._debug['len_body']['start'] = self._io.pos() + self.len_body = self._io.read_s4le() + self._debug['len_body']['end'] = self._io.pos() + self._debug['always_minus_1']['start'] = self._io.pos() + self.always_minus_1 = self._io.read_s4le() + self._debug['always_minus_1']['end'] = self._io.pos() + self._debug['always_zero']['start'] = self._io.pos() + self.always_zero = self._io.read_s4le() + self._debug['always_zero']['end'] = self._io.pos() + + @property + def filename(self): + if hasattr(self, '_m_filename'): + return self._m_filename if hasattr(self, '_m_filename') else None + + io = self._root.filenames._io + _pos = io.pos() + io.seek(self.name_ofs) + self._debug['_m_filename']['start'] = io.pos() + self._m_filename = (io.read_bytes_term(0, False, True, True)).decode(u"UTF-8") + self._debug['_m_filename']['end'] = io.pos() + io.seek(_pos) + return self._m_filename if hasattr(self, '_m_filename') else None + + @property + def ext(self): + if hasattr(self, '_m_ext'): + return self._m_ext if hasattr(self, '_m_ext') else None + + io = self._root.extensions._io + _pos = io.pos() + io.seek(self.ext_ofs) + self._debug['_m_ext']['start'] = io.pos() + self._m_ext = (io.read_bytes_term(0, False, True, True)).decode(u"UTF-8") + self._debug['_m_ext']['end'] = io.pos() + io.seek(_pos) + return self._m_ext if hasattr(self, '_m_ext') else None + + @property + def body(self): + if hasattr(self, '_m_body'): + return self._m_body if hasattr(self, '_m_body') else None + + io = self._root._io + _pos = io.pos() + io.seek((self._root.data_start + self.ofs_body)) + self._debug['_m_body']['start'] = io.pos() + self._m_body = io.read_bytes(self.len_body) + self._debug['_m_body']['end'] = io.pos() + io.seek(_pos) + return self._m_body if hasattr(self, '_m_body') else None + + + + class Strings(KaitaiStruct): + SEQ_FIELDS = ["entries"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['entries']['start'] = self._io.pos() + self.entries = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['entries']: + self._debug['entries']['arr'] = [] + self._debug['entries']['arr'].append({'start': self._io.pos()}) + self.entries.append((self._io.read_bytes_term(0, False, True, True)).decode(u"UTF-8")) + self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['entries']['end'] = self._io.pos() + + + @property + def filenames(self): + if hasattr(self, '_m_filenames'): + return self._m_filenames if hasattr(self, '_m_filenames') else None + + _pos = self._io.pos() + self._io.seek(self.ofs_filenames) + self._debug['_m_filenames']['start'] = self._io.pos() + self._raw__m_filenames = self._io.read_bytes(self.len_filenames) + io = KaitaiStream(BytesIO(self._raw__m_filenames)) + self._m_filenames = self._root.Strings(io, self, self._root) + self._m_filenames._read() + self._debug['_m_filenames']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_filenames if hasattr(self, '_m_filenames') else None + + @property + def ofs_extensions(self): + if hasattr(self, '_m_ofs_extensions'): + return self._m_ofs_extensions if hasattr(self, '_m_ofs_extensions') else None + + self._m_ofs_extensions = (((self.ofs_filenames + self.len_filenames) & 4294965248) + 2048) + return self._m_ofs_extensions if hasattr(self, '_m_ofs_extensions') else None + + @property + def files(self): + if hasattr(self, '_m_files'): + return self._m_files if hasattr(self, '_m_files') else None + + _pos = self._io.pos() + self._io.seek(2048) + self._debug['_m_files']['start'] = self._io.pos() + self._raw__m_files = self._io.read_bytes(self.len_offsets) + io = KaitaiStream(BytesIO(self._raw__m_files)) + self._m_files = self._root.Offsets(io, self, self._root) + self._m_files._read() + self._debug['_m_files']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_files if hasattr(self, '_m_files') else None + + @property + def data_start(self): + if hasattr(self, '_m_data_start'): + return self._m_data_start if hasattr(self, '_m_data_start') else None + + self._m_data_start = (((self.ofs_extensions + self.len_extensions) & 4294965248) + 2048) + return self._m_data_start if hasattr(self, '_m_data_start') else None + + @property + def extensions(self): + if hasattr(self, '_m_extensions'): + return self._m_extensions if hasattr(self, '_m_extensions') else None + + _pos = self._io.pos() + self._io.seek(self.ofs_extensions) + self._debug['_m_extensions']['start'] = self._io.pos() + self._raw__m_extensions = self._io.read_bytes(self.len_extensions) + io = KaitaiStream(BytesIO(self._raw__m_extensions)) + self._m_extensions = self._root.Strings(io, self, self._root) + self._m_extensions._read() + self._debug['_m_extensions']['end'] = self._io.pos() + self._io.seek(_pos) + return self._m_extensions if hasattr(self, '_m_extensions') else None + + @property + def ofs_filenames(self): + if hasattr(self, '_m_ofs_filenames'): + return self._m_ofs_filenames if hasattr(self, '_m_ofs_filenames') else None + + self._m_ofs_filenames = (((2048 + self.len_offsets) & 4294965248) + 2048) + return self._m_ofs_filenames if hasattr(self, '_m_ofs_filenames') else None + + diff --git a/python/examples/kaitai/kaitai_struct_formats/game/warcraft_2_pud.py b/python/examples/kaitai/kaitai_struct_formats/game/warcraft_2_pud.py new file mode 100644 index 00000000..a76f83d9 --- /dev/null +++ b/python/examples/kaitai/kaitai_struct_formats/game/warcraft_2_pud.py @@ -0,0 +1,421 @@ +from __future__ import absolute_import +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +from pkg_resources import parse_version +from ...kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO +from enum import Enum +import collections + + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + +class Warcraft2Pud(KaitaiStruct): + """Warcraft II game engine uses this format for map files. External + maps can be edited by official Warcraft II map editor and saved in + .pud files. Maps supplied with the game (i.e. single player + campaign) follow the same format, but are instead embedded inside + the game container files. + + There are two major versions: 0x11 (original one) and 0x13 (roughly + corresponds to v1.33 of the game engine, although some of the + features got limited support in v1.3). + + File consists of a sequence of typed sections. + + .. seealso:: + Source - http://cade.datamax.bg/war2x/pudspec.html + """ + + class Controller(Enum): + computer = 1 + passive_computer = 2 + nobody = 3 + computer = 4 + human = 5 + rescue_passive = 6 + rescue_active = 7 + + class TerrainType(Enum): + forest = 0 + winter = 1 + wasteland = 2 + swamp = 3 + + class UnitType(Enum): + infantry = 0 + grunt = 1 + peasant = 2 + peon = 3 + ballista = 4 + catapult = 5 + knight = 6 + ogre = 7 + archer = 8 + axethrower = 9 + mage = 10 + death_knight = 11 + paladin = 12 + ogre_mage = 13 + dwarves = 14 + goblin_sapper = 15 + attack_peasant = 16 + attack_peon = 17 + ranger = 18 + berserker = 19 + alleria = 20 + teron_gorefiend = 21 + kurdan_and_sky_ree = 22 + dentarg = 23 + khadgar = 24 + grom_hellscream = 25 + human_tanker = 26 + orc_tanker = 27 + human_transport = 28 + orc_transport = 29 + elven_destroyer = 30 + troll_destroyer = 31 + battleship = 32 + juggernaught = 33 + deathwing = 35 + gnomish_submarine = 38 + giant_turtle = 39 + gnomish_flying_machine = 40 + goblin_zepplin = 41 + gryphon_rider = 42 + dragon = 43 + turalyon = 44 + eye_of_kilrogg = 45 + danath = 46 + khorgath_bladefist = 47 + cho_gall = 49 + lothar = 50 + gul_dan = 51 + uther_lightbringer = 52 + zuljin = 53 + skeleton = 55 + daemon = 56 + critter = 57 + farm = 58 + pig_farm = 59 + human_barracks = 60 + orc_barracks = 61 + church = 62 + altar_of_storms = 63 + human_scout_tower = 64 + orc_scout_tower = 65 + stables = 66 + ogre_mound = 67 + gnomish_inventor = 68 + goblin_alchemist = 69 + gryphon_aviary = 70 + dragon_roost = 71 + human_shipyard = 72 + orc_shipyard = 73 + town_hall = 74 + great_hall = 75 + elven_lumber_mill = 76 + troll_lumber_mill = 77 + human_foundry = 78 + orc_foundry = 79 + mage_tower = 80 + temple_of_the_damned = 81 + human_blacksmith = 82 + orc_blacksmith = 83 + human_refinery = 84 + orc_refinery = 85 + human_oil_well = 86 + orc_oil_well = 87 + keep = 88 + stronghold = 89 + castle = 90 + fortress = 91 + gold_mine = 92 + oil_patch = 93 + human_start = 94 + orc_start = 95 + human_guard_tower = 96 + orc_guard_tower = 97 + human_cannon_tower = 98 + orc_cannon_tower = 99 + circle_of_power = 100 + dark_portal = 101 + runestone = 102 + human_wall = 103 + orc_wall = 104 + SEQ_FIELDS = ["sections"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['sections']['start'] = self._io.pos() + self.sections = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['sections']: + self._debug['sections']['arr'] = [] + self._debug['sections']['arr'].append({'start': self._io.pos()}) + _t_sections = self._root.Section(self._io, self, self._root) + _t_sections._read() + self.sections.append(_t_sections) + self._debug['sections']['arr'][len(self.sections) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['sections']['end'] = self._io.pos() + + class SectionStartingResource(KaitaiStruct): + SEQ_FIELDS = ["resources_by_player"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['resources_by_player']['start'] = self._io.pos() + self.resources_by_player = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['resources_by_player']: + self._debug['resources_by_player']['arr'] = [] + self._debug['resources_by_player']['arr'].append({'start': self._io.pos()}) + self.resources_by_player.append(self._io.read_u2le()) + self._debug['resources_by_player']['arr'][len(self.resources_by_player) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['resources_by_player']['end'] = self._io.pos() + + + class SectionEra(KaitaiStruct): + """Section that specifies terrain type for this map.""" + SEQ_FIELDS = ["terrain"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['terrain']['start'] = self._io.pos() + self.terrain = KaitaiStream.resolve_enum(self._root.TerrainType, self._io.read_u2le()) + self._debug['terrain']['end'] = self._io.pos() + + + class SectionVer(KaitaiStruct): + """Section that specifies format version.""" + SEQ_FIELDS = ["version"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['version']['start'] = self._io.pos() + self.version = self._io.read_u2le() + self._debug['version']['end'] = self._io.pos() + + + class SectionDim(KaitaiStruct): + SEQ_FIELDS = ["x", "y"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['x']['start'] = self._io.pos() + self.x = self._io.read_u2le() + self._debug['x']['end'] = self._io.pos() + self._debug['y']['start'] = self._io.pos() + self.y = self._io.read_u2le() + self._debug['y']['end'] = self._io.pos() + + + class SectionType(KaitaiStruct): + """Section that confirms that this file is a "map file" by certain + magic string and supplies a tag that could be used in + multiplayer to check that all player use the same version of the + map. + """ + SEQ_FIELDS = ["magic", "unused", "id_tag"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['magic']['start'] = self._io.pos() + self.magic = self._io.ensure_fixed_contents(b"\x57\x41\x52\x32\x20\x4D\x41\x50\x00\x00") + self._debug['magic']['end'] = self._io.pos() + self._debug['unused']['start'] = self._io.pos() + self.unused = self._io.read_bytes(2) + self._debug['unused']['end'] = self._io.pos() + self._debug['id_tag']['start'] = self._io.pos() + self.id_tag = self._io.read_u4le() + self._debug['id_tag']['end'] = self._io.pos() + + + class SectionUnit(KaitaiStruct): + SEQ_FIELDS = ["units"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['units']['start'] = self._io.pos() + self.units = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['units']: + self._debug['units']['arr'] = [] + self._debug['units']['arr'].append({'start': self._io.pos()}) + _t_units = self._root.Unit(self._io, self, self._root) + _t_units._read() + self.units.append(_t_units) + self._debug['units']['arr'][len(self.units) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['units']['end'] = self._io.pos() + + + class Section(KaitaiStruct): + SEQ_FIELDS = ["name", "size", "body"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['name']['start'] = self._io.pos() + self.name = (self._io.read_bytes(4)).decode(u"ASCII") + self._debug['name']['end'] = self._io.pos() + self._debug['size']['start'] = self._io.pos() + self.size = self._io.read_u4le() + self._debug['size']['end'] = self._io.pos() + self._debug['body']['start'] = self._io.pos() + _on = self.name + if _on == u"SLBR": + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.SectionStartingResource(io, self, self._root) + self.body._read() + elif _on == u"ERAX": + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.SectionEra(io, self, self._root) + self.body._read() + elif _on == u"OWNR": + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.SectionOwnr(io, self, self._root) + self.body._read() + elif _on == u"ERA ": + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.SectionEra(io, self, self._root) + self.body._read() + elif _on == u"SGLD": + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.SectionStartingResource(io, self, self._root) + self.body._read() + elif _on == u"VER ": + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.SectionVer(io, self, self._root) + self.body._read() + elif _on == u"SOIL": + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.SectionStartingResource(io, self, self._root) + self.body._read() + elif _on == u"UNIT": + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.SectionUnit(io, self, self._root) + self.body._read() + elif _on == u"DIM ": + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.SectionDim(io, self, self._root) + self.body._read() + elif _on == u"TYPE": + self._raw_body = self._io.read_bytes(self.size) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.SectionType(io, self, self._root) + self.body._read() + else: + self.body = self._io.read_bytes(self.size) + self._debug['body']['end'] = self._io.pos() + + + class SectionOwnr(KaitaiStruct): + """Section that specifies who controls each player.""" + SEQ_FIELDS = ["controller_by_player"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['controller_by_player']['start'] = self._io.pos() + self.controller_by_player = [] + i = 0 + while not self._io.is_eof(): + if not 'arr' in self._debug['controller_by_player']: + self._debug['controller_by_player']['arr'] = [] + self._debug['controller_by_player']['arr'].append({'start': self._io.pos()}) + self.controller_by_player.append(KaitaiStream.resolve_enum(self._root.Controller, self._io.read_u1())) + self._debug['controller_by_player']['arr'][len(self.controller_by_player) - 1]['end'] = self._io.pos() + i += 1 + + self._debug['controller_by_player']['end'] = self._io.pos() + + + class Unit(KaitaiStruct): + SEQ_FIELDS = ["x", "y", "u_type", "owner", "options"] + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._debug = collections.defaultdict(dict) + + def _read(self): + self._debug['x']['start'] = self._io.pos() + self.x = self._io.read_u2le() + self._debug['x']['end'] = self._io.pos() + self._debug['y']['start'] = self._io.pos() + self.y = self._io.read_u2le() + self._debug['y']['end'] = self._io.pos() + self._debug['u_type']['start'] = self._io.pos() + self.u_type = KaitaiStream.resolve_enum(self._root.UnitType, self._io.read_u1()) + self._debug['u_type']['end'] = self._io.pos() + self._debug['owner']['start'] = self._io.pos() + self.owner = self._io.read_u1() + self._debug['owner']['end'] = self._io.pos() + self._debug['options']['start'] = self._io.pos() + self.options = self._io.read_u2le() + self._debug['options']['end'] = self._io.pos() + + @property + def resource(self): + if hasattr(self, '_m_resource'): + return self._m_resource if hasattr(self, '_m_resource') else None + + if ((self.u_type == self._root.UnitType.gold_mine) or (self.u_type == self._root.UnitType.human_oil_well) or (self.u_type == self._root.UnitType.orc_oil_well) or (self.u_type == self._root.UnitType.oil_patch)) : + self._m_resource = (self.options * 2500) + + return self._m_resource if hasattr(self, '_m_resource') else None + + + |
