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