#include "quam/wad2.h" namespace Wad2 { enum Compression { CompressNone, CompressLZSS, }; } struct Wad2Header { quint32 dirNum; quint32 dirOffset; }; struct Wad2Entry { std::string name; Arc::FileType type; ArcFile file; }; static Wad2Header readWad2Header(std::istream &st) { auto magic = readBytes<4>(st); if(magic != std::array{'W', 'A', 'D', '2'}) { throw FileFormatError("not a wad2 file (invalid magic number)"); } Wad2Header hdr; hdr.dirNum = readLE(st); hdr.dirOffset = readLE(st); return hdr; } static Wad2Entry readWad2Entry(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 != Wad2::CompressNone) { throw UnimplementedError("compressed files not supported"); } auto pos = st.tellg(); st.seekg(entOffset); ArcFile file; file.resize(entSize); st.read(file.data(), entSize); st.seekg(pos); Wad2Entry ent; ent.name = ntbsToString(entName); ent.file = std::move(file); ent.type = Arc::getFileType(entType); return ent; } ArcDir readWad2(std::istream &st) { auto hdr = readWad2Header(st); st.seekg(hdr.dirOffset); ArcDir root; for(quint32 i = 0; i < hdr.dirNum; i++) { auto ent = readWad2Entry(st); /* if(root.findNode(ent.name) != root.end()) { throw FileFormatError("duplicate file"); } */ root.emplace_back(std::move(ent.file), std::move(ent.name), ent.type); } return root; } // EOF