#include "common.h" #include "quam/pak.h" struct PakHeader { quint32 dirOffset; quint32 dirNum; }; struct PakEntry { std::string name; QByteArray data; }; static constexpr quint32 sizeOfPakEntry = 64; static PakHeader readPakHeader(std::istream &st) { auto magic = readBytes<4>(st); if(magic != std::array{'P', 'A', 'C', 'K'}) { throw std::runtime_error("not a pak file (invalid magic number)"); } auto dirOffset = readLE(st); auto dirSize = readLE(st); if(dirSize % sizeOfPakEntry != 0) { throw std::runtime_error("invalid directory size"); } PakHeader hdr; hdr.dirOffset = dirOffset; hdr.dirNum = dirSize / sizeOfPakEntry; return hdr; } static PakEntry readPakEntry(std::istream &st) { auto entName = readBytes<56>(st); auto entOffset = readLE(st); auto entSize = readLE(st); auto pos = st.tellg(); st.seekg(entOffset); QByteArray bytes; bytes.resize(entSize); st.read(bytes.data(), entSize); st.seekg(pos); auto zero = std::find(entName.cbegin(), entName.cend(), '\0'); std::string out; std::copy(entName.cbegin(), zero, std::back_inserter(out)); PakEntry ent; ent.name = std::move(out); ent.data = std::move(bytes); return ent; } PakFile readPakFile(std::istream &st) { auto hdr = readPakHeader(st); st.seekg(hdr.dirOffset); PakFile pak; for(quint32 i = 0; i < hdr.dirNum; i++) { auto ent = readPakEntry(st); pak.emplace(std::move(ent.name), std::move(ent.data)); } return pak; } // EOF