This page hosts a formal specification of Saints Rows 2 game packages using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
All parsing code for C++11/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.
For C++, the easiest way is to clone the runtime library sources and build them along with your project.
Using Kaitai Struct in C++/STL usually consists of 3 steps.
std::istream
). One can open local file for that, or use existing std::string
or char*
buffer.
#include <fstream>
std::ifstream is("path/to/local/file.vpp_pc", std::ifstream::binary);
#include <sstream>
std::istringstream is(str);
#include <sstream>
const char buf[] = { ... };
std::string str(buf, sizeof buf);
std::istringstream is(str);
#include "kaitai/kaitaistream.h"
kaitai::kstream ks(&is);
saints_row_2_vpp_pc_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.magic() // => get magic
#pragma once
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include <memory>
#include <vector>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
class saints_row_2_vpp_pc_t : public kaitai::kstruct {
public:
class offsets_t;
class strings_t;
saints_row_2_vpp_pc_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, saints_row_2_vpp_pc_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~saints_row_2_vpp_pc_t();
class offsets_t : public kaitai::kstruct {
public:
class offset_t;
offsets_t(kaitai::kstream* p__io, saints_row_2_vpp_pc_t* p__parent = nullptr, saints_row_2_vpp_pc_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~offsets_t();
class offset_t : public kaitai::kstruct {
public:
offset_t(kaitai::kstream* p__io, saints_row_2_vpp_pc_t::offsets_t* p__parent = nullptr, saints_row_2_vpp_pc_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~offset_t();
private:
bool f_filename;
std::string m_filename;
public:
std::string filename();
private:
bool f_ext;
std::string m_ext;
public:
std::string ext();
private:
bool f_body;
std::string m_body;
public:
std::string body();
private:
uint32_t m_name_ofs;
uint32_t m_ext_ofs;
int32_t m_smth2;
int32_t m_ofs_body;
int32_t m_len_body;
int32_t m_always_minus_1;
int32_t m_always_zero;
saints_row_2_vpp_pc_t* m__root;
saints_row_2_vpp_pc_t::offsets_t* m__parent;
public:
uint32_t name_ofs() const { return m_name_ofs; }
uint32_t ext_ofs() const { return m_ext_ofs; }
int32_t smth2() const { return m_smth2; }
int32_t ofs_body() const { return m_ofs_body; }
int32_t len_body() const { return m_len_body; }
int32_t always_minus_1() const { return m_always_minus_1; }
int32_t always_zero() const { return m_always_zero; }
saints_row_2_vpp_pc_t* _root() const { return m__root; }
saints_row_2_vpp_pc_t::offsets_t* _parent() const { return m__parent; }
};
private:
std::unique_ptr<std::vector<std::unique_ptr<offset_t>>> m_entries;
saints_row_2_vpp_pc_t* m__root;
saints_row_2_vpp_pc_t* m__parent;
public:
std::vector<std::unique_ptr<offset_t>>* entries() const { return m_entries.get(); }
saints_row_2_vpp_pc_t* _root() const { return m__root; }
saints_row_2_vpp_pc_t* _parent() const { return m__parent; }
};
class strings_t : public kaitai::kstruct {
public:
strings_t(kaitai::kstream* p__io, saints_row_2_vpp_pc_t* p__parent = nullptr, saints_row_2_vpp_pc_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~strings_t();
private:
std::unique_ptr<std::vector<std::string>> m_entries;
saints_row_2_vpp_pc_t* m__root;
saints_row_2_vpp_pc_t* m__parent;
public:
std::vector<std::string>* entries() const { return m_entries.get(); }
saints_row_2_vpp_pc_t* _root() const { return m__root; }
saints_row_2_vpp_pc_t* _parent() const { return m__parent; }
};
private:
bool f_filenames;
std::unique_ptr<strings_t> m_filenames;
public:
strings_t* filenames();
private:
bool f_ofs_extensions;
int32_t m_ofs_extensions;
public:
int32_t ofs_extensions();
private:
bool f_files;
std::unique_ptr<offsets_t> m_files;
public:
offsets_t* files();
private:
bool f_data_start;
int32_t m_data_start;
public:
int32_t data_start();
private:
bool f_extensions;
std::unique_ptr<strings_t> m_extensions;
public:
strings_t* extensions();
private:
bool f_ofs_filenames;
int32_t m_ofs_filenames;
public:
int32_t ofs_filenames();
private:
std::string m_magic;
std::string m_pad1;
int32_t m_num_files;
int32_t m_container_size;
int32_t m_len_offsets;
int32_t m_len_filenames;
int32_t m_len_extensions;
int32_t m_smth5;
int32_t m_smth6;
int32_t m_smth7;
int32_t m_smth8;
int32_t m_smth9;
saints_row_2_vpp_pc_t* m__root;
kaitai::kstruct* m__parent;
std::string m__raw_filenames;
std::unique_ptr<kaitai::kstream> m__io__raw_filenames;
std::string m__raw_files;
std::unique_ptr<kaitai::kstream> m__io__raw_files;
std::string m__raw_extensions;
std::unique_ptr<kaitai::kstream> m__io__raw_extensions;
public:
std::string magic() const { return m_magic; }
std::string pad1() const { return m_pad1; }
int32_t num_files() const { return m_num_files; }
int32_t container_size() const { return m_container_size; }
int32_t len_offsets() const { return m_len_offsets; }
int32_t len_filenames() const { return m_len_filenames; }
int32_t len_extensions() const { return m_len_extensions; }
int32_t smth5() const { return m_smth5; }
int32_t smth6() const { return m_smth6; }
int32_t smth7() const { return m_smth7; }
int32_t smth8() const { return m_smth8; }
int32_t smth9() const { return m_smth9; }
saints_row_2_vpp_pc_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
std::string _raw_filenames() const { return m__raw_filenames; }
kaitai::kstream* _io__raw_filenames() const { return m__io__raw_filenames.get(); }
std::string _raw_files() const { return m__raw_files; }
kaitai::kstream* _io__raw_files() const { return m__io__raw_files.get(); }
std::string _raw_extensions() const { return m__raw_extensions; }
kaitai::kstream* _io__raw_extensions() const { return m__io__raw_extensions.get(); }
};
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "saints_row_2_vpp_pc.h"
#include "kaitai/exceptions.h"
saints_row_2_vpp_pc_t::saints_row_2_vpp_pc_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, saints_row_2_vpp_pc_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_filenames = nullptr;
m__io__raw_filenames = nullptr;
m_files = nullptr;
m__io__raw_files = nullptr;
m_extensions = nullptr;
m__io__raw_extensions = nullptr;
f_filenames = false;
f_ofs_extensions = false;
f_files = false;
f_data_start = false;
f_extensions = false;
f_ofs_filenames = false;
_read();
}
void saints_row_2_vpp_pc_t::_read() {
m_magic = m__io->read_bytes(5);
if (!(magic() == std::string("\xCE\x0A\x89\x51\x04", 5))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\xCE\x0A\x89\x51\x04", 5), magic(), _io(), std::string("/seq/0"));
}
m_pad1 = m__io->read_bytes(335);
m_num_files = m__io->read_s4le();
m_container_size = m__io->read_s4le();
m_len_offsets = m__io->read_s4le();
m_len_filenames = m__io->read_s4le();
m_len_extensions = m__io->read_s4le();
m_smth5 = m__io->read_s4le();
m_smth6 = m__io->read_s4le();
m_smth7 = m__io->read_s4le();
m_smth8 = m__io->read_s4le();
m_smth9 = m__io->read_s4le();
}
saints_row_2_vpp_pc_t::~saints_row_2_vpp_pc_t() {
_clean_up();
}
void saints_row_2_vpp_pc_t::_clean_up() {
if (f_filenames) {
}
if (f_files) {
}
if (f_extensions) {
}
}
saints_row_2_vpp_pc_t::offsets_t::offsets_t(kaitai::kstream* p__io, saints_row_2_vpp_pc_t* p__parent, saints_row_2_vpp_pc_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = nullptr;
_read();
}
void saints_row_2_vpp_pc_t::offsets_t::_read() {
m_entries = std::unique_ptr<std::vector<std::unique_ptr<offset_t>>>(new std::vector<std::unique_ptr<offset_t>>());
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(std::move(std::unique_ptr<offset_t>(new offset_t(m__io, this, m__root))));
i++;
}
}
}
saints_row_2_vpp_pc_t::offsets_t::~offsets_t() {
_clean_up();
}
void saints_row_2_vpp_pc_t::offsets_t::_clean_up() {
}
saints_row_2_vpp_pc_t::offsets_t::offset_t::offset_t(kaitai::kstream* p__io, saints_row_2_vpp_pc_t::offsets_t* p__parent, saints_row_2_vpp_pc_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_filename = false;
f_ext = false;
f_body = false;
_read();
}
void saints_row_2_vpp_pc_t::offsets_t::offset_t::_read() {
m_name_ofs = m__io->read_u4le();
m_ext_ofs = m__io->read_u4le();
m_smth2 = m__io->read_s4le();
m_ofs_body = m__io->read_s4le();
m_len_body = m__io->read_s4le();
m_always_minus_1 = m__io->read_s4le();
m_always_zero = m__io->read_s4le();
}
saints_row_2_vpp_pc_t::offsets_t::offset_t::~offset_t() {
_clean_up();
}
void saints_row_2_vpp_pc_t::offsets_t::offset_t::_clean_up() {
if (f_filename) {
}
if (f_ext) {
}
if (f_body) {
}
}
std::string saints_row_2_vpp_pc_t::offsets_t::offset_t::filename() {
if (f_filename)
return m_filename;
kaitai::kstream *io = _root()->filenames()->_io();
std::streampos _pos = io->pos();
io->seek(name_ofs());
m_filename = kaitai::kstream::bytes_to_str(io->read_bytes_term(0, false, true, true), std::string("UTF-8"));
io->seek(_pos);
f_filename = true;
return m_filename;
}
std::string saints_row_2_vpp_pc_t::offsets_t::offset_t::ext() {
if (f_ext)
return m_ext;
kaitai::kstream *io = _root()->extensions()->_io();
std::streampos _pos = io->pos();
io->seek(ext_ofs());
m_ext = kaitai::kstream::bytes_to_str(io->read_bytes_term(0, false, true, true), std::string("UTF-8"));
io->seek(_pos);
f_ext = true;
return m_ext;
}
std::string saints_row_2_vpp_pc_t::offsets_t::offset_t::body() {
if (f_body)
return m_body;
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek((_root()->data_start() + ofs_body()));
m_body = io->read_bytes(len_body());
io->seek(_pos);
f_body = true;
return m_body;
}
saints_row_2_vpp_pc_t::strings_t::strings_t(kaitai::kstream* p__io, saints_row_2_vpp_pc_t* p__parent, saints_row_2_vpp_pc_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = nullptr;
_read();
}
void saints_row_2_vpp_pc_t::strings_t::_read() {
m_entries = std::unique_ptr<std::vector<std::string>>(new std::vector<std::string>());
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(std::move(kaitai::kstream::bytes_to_str(m__io->read_bytes_term(0, false, true, true), std::string("UTF-8"))));
i++;
}
}
}
saints_row_2_vpp_pc_t::strings_t::~strings_t() {
_clean_up();
}
void saints_row_2_vpp_pc_t::strings_t::_clean_up() {
}
saints_row_2_vpp_pc_t::strings_t* saints_row_2_vpp_pc_t::filenames() {
if (f_filenames)
return m_filenames.get();
std::streampos _pos = m__io->pos();
m__io->seek(ofs_filenames());
m__raw_filenames = m__io->read_bytes(len_filenames());
m__io__raw_filenames = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_filenames));
m_filenames = std::unique_ptr<strings_t>(new strings_t(m__io__raw_filenames.get(), this, m__root));
m__io->seek(_pos);
f_filenames = true;
return m_filenames.get();
}
int32_t saints_row_2_vpp_pc_t::ofs_extensions() {
if (f_ofs_extensions)
return m_ofs_extensions;
m_ofs_extensions = (((ofs_filenames() + len_filenames()) & 4294965248UL) + 2048);
f_ofs_extensions = true;
return m_ofs_extensions;
}
saints_row_2_vpp_pc_t::offsets_t* saints_row_2_vpp_pc_t::files() {
if (f_files)
return m_files.get();
std::streampos _pos = m__io->pos();
m__io->seek(2048);
m__raw_files = m__io->read_bytes(len_offsets());
m__io__raw_files = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_files));
m_files = std::unique_ptr<offsets_t>(new offsets_t(m__io__raw_files.get(), this, m__root));
m__io->seek(_pos);
f_files = true;
return m_files.get();
}
int32_t saints_row_2_vpp_pc_t::data_start() {
if (f_data_start)
return m_data_start;
m_data_start = (((ofs_extensions() + len_extensions()) & 4294965248UL) + 2048);
f_data_start = true;
return m_data_start;
}
saints_row_2_vpp_pc_t::strings_t* saints_row_2_vpp_pc_t::extensions() {
if (f_extensions)
return m_extensions.get();
std::streampos _pos = m__io->pos();
m__io->seek(ofs_extensions());
m__raw_extensions = m__io->read_bytes(len_extensions());
m__io__raw_extensions = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_extensions));
m_extensions = std::unique_ptr<strings_t>(new strings_t(m__io__raw_extensions.get(), this, m__root));
m__io->seek(_pos);
f_extensions = true;
return m_extensions.get();
}
int32_t saints_row_2_vpp_pc_t::ofs_filenames() {
if (f_ofs_filenames)
return m_ofs_filenames;
m_ofs_filenames = (((2048 + len_offsets()) & 4294965248UL) + 2048);
f_ofs_filenames = true;
return m_ofs_filenames;
}