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-05 16:58:19 -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-10 14:29:08 -07:00
|
|
|
static std::pair<quint32, quint32> 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-10 14:29:08 -07:00
|
|
|
auto dirNum = readLE<quint32>(st);
|
|
|
|
auto dirOffset = readLE<quint32>(st);
|
|
|
|
return std::make_pair(dirOffset, dirNum);
|
2019-10-03 14:06:05 -07:00
|
|
|
}
|
|
|
|
|
2019-10-10 14:29:08 -07:00
|
|
|
static Arc::File 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);
|
|
|
|
|
2019-11-06 22:42:59 -08:00
|
|
|
QByteArray data;
|
2019-10-10 14:29:08 -07:00
|
|
|
|
2019-11-06 22:42:59 -08:00
|
|
|
data.resize(entSize);
|
|
|
|
st.read(data.data(), entSize);
|
2019-10-03 14:06:05 -07:00
|
|
|
st.seekg(pos);
|
|
|
|
|
2019-11-06 22:42:59 -08:00
|
|
|
Arc::File file{ntbsToString(entName), std::move(data)};
|
2019-10-10 14:29:08 -07:00
|
|
|
file.type = getFileType(entType);
|
|
|
|
return file;
|
2019-10-03 14:06:05 -07:00
|
|
|
}
|
|
|
|
|
2019-10-05 16:58:19 -07:00
|
|
|
Arc::Dir readWad2(std::istream &st) {
|
2019-10-04 10:37:34 -07:00
|
|
|
auto hdr = readWad2Header(st);
|
2019-10-10 14:29:08 -07:00
|
|
|
st.seekg(hdr.first);
|
2019-10-03 14:06:05 -07:00
|
|
|
|
2019-10-10 14:29:08 -07:00
|
|
|
Arc::Dir root{std::string{}};
|
2019-10-03 14:06:05 -07:00
|
|
|
|
2019-10-10 14:29:08 -07:00
|
|
|
for(quint32 i = 0; i < hdr.second; i++) {
|
2019-11-06 22:42:59 -08:00
|
|
|
root.emplaceBack(new Arc::File(readWad2Entry(st)));
|
2019-10-03 14:06:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return root;
|
|
|
|
}
|
|
|
|
|
2019-10-09 16:06:14 -07:00
|
|
|
Wad2Validator::Wad2Validator(QObject *parent) :
|
|
|
|
QValidator{parent}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QValidator::State Wad2Validator::validate(QString &input, int &pos) const {
|
|
|
|
return QValidator::Acceptable;
|
|
|
|
}
|
|
|
|
|
2019-10-03 14:06:05 -07:00
|
|
|
// EOF
|