quake-tools/source/quam/wad2.cc

92 lines
1.9 KiB
C++
Raw Normal View History

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;
Arc::File file;
2019-10-03 14:06:05 -07:00
};
static Arc::FileType getFileType(int n) {
switch(n) {
case 0: return Arc::FileType::Normal;
case 1: return Arc::FileType::Label;
case 64: return Arc::FileType::Palette;
case 65: return Arc::FileType::Texture;
case 66: return Arc::FileType::Picture;
case 67: return Arc::FileType::Sound;
case 68: return Arc::FileType::MipTexture;
default: throw EnumError("invalid file type");
}
}
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);
Arc::File file;
2019-10-03 14:06:05 -07:00
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 = getFileType(entType);
2019-10-03 14:06:05 -07:00
return ent;
}
Arc::Dir readWad2(std::istream &st) {
2019-10-04 10:37:34 -07:00
auto hdr = readWad2Header(st);
2019-10-03 14:06:05 -07:00
st.seekg(hdr.dirOffset);
Arc::Dir root;
2019-10-03 14:06:05 -07:00
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
root.emplace_back(std::move(ent.file), std::move(ent.name), ent.type);
}
return root;
}
// EOF