#include "quam/wad.h" namespace Wad { enum Compression { CompressNone, CompressLZSS, }; } struct WadHeader { quint32 dirOffset; quint32 dirNum; }; struct WadEntry { std::string name; Arc::FileType type; ArcFile file; }; static WadHeader readWadHeader(std::istream &st) { auto magic = readBytes<4>(st); if(magic != std::array{'W', 'A', 'D', '2'}) { throw std::runtime_error("not a wad2 file (invalid magic number)"); } WadHeader hdr; hdr.dirOffset = readLE(st); hdr.dirNum = readLE(st); return hdr; } static WadEntry readWadEntry(std::istream &st) { auto entOffset = readLE(st); auto entSize = readLE(st); auto entCSize = readLE(st); auto entType = readByte(st); auto entCompr = readByte(st); /* padding */ readBytes<2>(st); auto entName = readBytes<16>(st); if(entSize != entCSize || entCompr != Wad::CompressNone) { throw std::runtime_error("compressed files not implemented"); } auto pos = st.tellg(); st.seekg(entOffset); ArcFile file; file.resize(entSize); st.read(file.data(), entSize); st.seekg(pos); WadEntry ent; ent.name = ntbsToString(entName); ent.file = std::move(file); ent.type = Arc::getFileType(entType); return ent; } ArcDir readWad(std::istream &st) { auto hdr = readWadHeader(st); st.seekg(hdr.dirOffset); ArcDir root; for(quint32 i = 0; i < hdr.dirNum; i++) { auto ent = readWadEntry(st); if(root.findNode(ent.name) != root.end()) { throw std::runtime_error("duplicate file"); } root.emplace_back(std::move(ent.file), std::move(ent.name), ent.type); } return root; } // EOF