Add Resource as interface for in-memory resources
This commit is contained in:
14
IffFile.cc
14
IffFile.cc
@@ -9,13 +9,13 @@ struct ChunkHeader {
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
IffFile::IffFile(uint8_t const* base, size_t length)
|
||||
: base_(base), length_(length)
|
||||
IffFile::IffFile(Resource const& res)
|
||||
: res_(res)
|
||||
{
|
||||
size_t pos = 0;
|
||||
while (pos < length) {
|
||||
roots_.push_back(parseObject(base+pos, length-pos));
|
||||
pos += roots_.back()->getSize() + 8;
|
||||
while (pos < res_.size()) {
|
||||
roots_.push_back(parseObject(res_.data()+pos, res_.size()-pos));
|
||||
pos += roots_.back()->size() + 8;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ static void _printStructure(IffFile::Object const& obj, unsigned level)
|
||||
{
|
||||
for (unsigned i = 0;i < level;++i)
|
||||
putchar('\t');
|
||||
printf("%s Length %lu (0x%.lx)", obj.getType().c_str(), obj.getSize(), obj.getSize());
|
||||
printf("%s Length %lu (0x%.lx)", obj.getType().c_str(), obj.size(), obj.size());
|
||||
|
||||
if (obj.isForm()) {
|
||||
auto& form = dynamic_cast<IffFile::Form const&>(obj);
|
||||
@@ -129,7 +129,7 @@ IffFile::Form::Form(std::string type, uint8_t const* base, size_t length)
|
||||
size_t pos = 4;
|
||||
while (pos+8 < length) {
|
||||
children_.push_back(parseObject(base+pos, length-pos));
|
||||
pos += 8 + children_.back()->getSize();
|
||||
pos += 8 + children_.back()->size();
|
||||
|
||||
if (pos%2 != 0)
|
||||
++pos;
|
||||
|
||||
21
IffFile.hh
21
IffFile.hh
@@ -7,9 +7,11 @@
|
||||
#include <memory>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "Resource.hh"
|
||||
|
||||
class IffFile {
|
||||
public:
|
||||
IffFile(uint8_t const* base, size_t length);
|
||||
IffFile(Resource const& res);
|
||||
|
||||
~IffFile();
|
||||
|
||||
@@ -109,12 +111,12 @@ public:
|
||||
std::vector<std::unique_ptr<Object> >::const_iterator implIt_;
|
||||
};
|
||||
|
||||
class Object {
|
||||
class Object : public Resource {
|
||||
public:
|
||||
Object(std::string type, uint8_t const* base, size_t length);
|
||||
Object(Object const& copy) = delete;
|
||||
|
||||
virtual ~Object() {
|
||||
~Object() override {
|
||||
}
|
||||
|
||||
std::string const& getType() const {
|
||||
@@ -125,10 +127,14 @@ public:
|
||||
return (typeid(*this) == typeid(Form));
|
||||
}
|
||||
|
||||
size_t getSize() const {
|
||||
size_t size() const override {
|
||||
return length_;
|
||||
}
|
||||
|
||||
uint8_t const* data() const override {
|
||||
return base_;
|
||||
}
|
||||
|
||||
uint8_t const* begin() const {
|
||||
return base_;
|
||||
}
|
||||
@@ -138,6 +144,10 @@ public:
|
||||
}
|
||||
|
||||
operator std::string() const;
|
||||
|
||||
operator bool() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t const* base_;
|
||||
@@ -188,8 +198,7 @@ public:
|
||||
private:
|
||||
static std::unique_ptr<Object> parseObject(uint8_t const* base, size_t length);
|
||||
|
||||
uint8_t const* base_;
|
||||
const size_t length_;
|
||||
Resource const& res_;
|
||||
std::vector<std::unique_ptr<Object> > roots_;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#include "decompress.hh"
|
||||
#include "MveDecoder.hh"
|
||||
|
||||
MveDecoder::MveDecoder(uint8_t const* base, size_t length)
|
||||
: iff_(base, length), width_(320), height_(165)
|
||||
MveDecoder::MveDecoder(Resource const& res)
|
||||
: iff_(res), width_(320), height_(165)
|
||||
{
|
||||
//iff_.printStructure();
|
||||
|
||||
@@ -26,7 +26,7 @@ MveDecoder::MveDecoder(uint8_t const* base, size_t length)
|
||||
// Parse _PC_ chunk
|
||||
auto& PC = *it++;
|
||||
if ((PC.getType() != "_PC_") ||
|
||||
(PC.getSize() != 12))
|
||||
(PC.size() != 12))
|
||||
throw FormatException{"_PC_ chunk missing or wrong size"};
|
||||
|
||||
const uint32_t PC_PALTcount = readU32LE(PC.begin()+8);
|
||||
@@ -37,7 +37,7 @@ MveDecoder::MveDecoder(uint8_t const* base, size_t length)
|
||||
// // Parse SOND chunk
|
||||
// auto& SOND = *it++;
|
||||
// if ((SOND.getType() != "SOND") ||
|
||||
// (SOND.getSize() != 4))
|
||||
// (SOND.size() != 4))
|
||||
// throw FormatException{"SOND chunk missing or wrong size"};
|
||||
|
||||
// const uint32_t SONDc = readU32LE(SOND.begin());
|
||||
@@ -53,7 +53,7 @@ MveDecoder::MveDecoder(uint8_t const* base, size_t length)
|
||||
|
||||
for (;it != rootForm.childrenEnd();++it) {
|
||||
if (it->getType() == "SIZE") {
|
||||
if (it->getSize() != 8)
|
||||
if (it->size() != 8)
|
||||
throw FormatException{"Unexpected SIZE size"};
|
||||
|
||||
width_ = readU32LE(it->begin());
|
||||
@@ -61,7 +61,7 @@ MveDecoder::MveDecoder(uint8_t const* base, size_t length)
|
||||
} else if (it->getType() == "PALT") {
|
||||
if (curPALT > PC_PALTcount)
|
||||
throw FormatException{"Number of PALT chunks exceeds amount specified in _PC_"};
|
||||
if (it->getSize() != 768)
|
||||
if (it->size() != 768)
|
||||
throw FormatException{"Unexpected PALT size"};
|
||||
palts_.emplace_back();
|
||||
|
||||
@@ -95,11 +95,11 @@ MveDecoder::MveDecoder(uint8_t const* base, size_t length)
|
||||
throw FormatException{"INDX after SHOT"};
|
||||
haveIndex = true;
|
||||
|
||||
for(unsigned i = 0;i < it->getSize()/4;++i)
|
||||
for(unsigned i = 0;i < it->size()/4;++i)
|
||||
branches.push_back(readU32LE(it->begin()+i*4));
|
||||
branches_.resize(branches.size());
|
||||
} else if (it->getType() == "BRCH") {
|
||||
size_t ofs = it->begin()-base-8;
|
||||
size_t ofs = it->begin()-res.data()-8;
|
||||
auto idxIt = std::find(branches.begin(), branches.end(), ofs);
|
||||
if (idxIt == branches.end())
|
||||
throw FormatException{"Could not resolve branch " + std::to_string(ofs)};
|
||||
@@ -276,13 +276,13 @@ unsigned MveDecoder::Movie::getHeight() const
|
||||
void MveDecoder::Movie::parseVGA(IffFile::Object const& vga)
|
||||
{
|
||||
// Parse header
|
||||
if (vga.getSize() < 8)
|
||||
if (vga.size() < 8)
|
||||
throw FormatException{"VGA chunk smaller than VGA header"};
|
||||
|
||||
std::array<uint16_t, 4> segOfs;
|
||||
for(unsigned i = 0;i < segOfs.size();++i) {
|
||||
segOfs[i] = readU16LE(vga.begin()+i*2);
|
||||
if (segOfs[i] >= vga.getSize())
|
||||
if (segOfs[i] >= vga.size())
|
||||
throw FormatException{"Segment offset exceeds chunk"};
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga)
|
||||
((segOfs[1] && (segOfs[1] - segOfs[0]) < 45)) ||
|
||||
((segOfs[2] && (segOfs[2] - segOfs[0]) < 45)) ||
|
||||
((segOfs[3] && (segOfs[3] - segOfs[0]) < 45)) ||
|
||||
(vga.getSize() - segOfs[0] < 45))
|
||||
(vga.size() - segOfs[0] < 45))
|
||||
throw FormatException{"Segment 1 too small"};
|
||||
|
||||
commandBuf_.clear();
|
||||
@@ -301,7 +301,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga)
|
||||
|
||||
size_t pixelCount = 0;
|
||||
if (segOfs[3]) {
|
||||
pixelCount = parsePixels_(vga.begin()+segOfs[3], vga.getSize()-segOfs[3],
|
||||
pixelCount = parsePixels_(vga.begin()+segOfs[3], vga.size()-segOfs[3],
|
||||
pixelBuf_.data(), pixelBuf_.size());
|
||||
maxPixel_ = std::max(maxPixel_, pixelCount);
|
||||
}
|
||||
@@ -309,7 +309,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga)
|
||||
#ifdef VIDDEBUG_
|
||||
printf("%lu commands, %lu pixel data, %u mvecs, %lu size data\n",
|
||||
commands.size(), pixels.size(), (segOfs[2]?(segOfs[3]-segOfs[2]):0),
|
||||
segOfs[2]?(segOfs[2]-segOfs[1]):(segOfs[3]?(segOfs[3]-segOfs[1]):(vga.getSize()-segOfs[1])));
|
||||
segOfs[2]?(segOfs[2]-segOfs[1]):(segOfs[3]?(segOfs[3]-segOfs[1]):(vga.size()-segOfs[1])));
|
||||
#endif
|
||||
|
||||
// Interpret command stream to render frame
|
||||
@@ -352,7 +352,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga)
|
||||
if (!segOfs[1] ||
|
||||
(segOfs[2] && (segOfs[1]+seg2Idx >= segOfs[2])) ||
|
||||
(segOfs[3] && (segOfs[1]+seg2Idx >= segOfs[3])) ||
|
||||
(segOfs[1]+seg2Idx >= vga.getSize()))
|
||||
(segOfs[1]+seg2Idx >= vga.size()))
|
||||
throw FormatException{"Segment 2 overrun"};
|
||||
size = vga.begin()[segOfs[1]+seg2Idx++]&0xff;
|
||||
break;
|
||||
@@ -361,7 +361,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga)
|
||||
if (!segOfs[1] ||
|
||||
(segOfs[2] && (segOfs[1]+seg2Idx+1 >= segOfs[2])) ||
|
||||
(segOfs[3] && (segOfs[1]+seg2Idx >= segOfs[3])) ||
|
||||
(segOfs[1]+seg2Idx+1 >= vga.getSize()))
|
||||
(segOfs[1]+seg2Idx+1 >= vga.size()))
|
||||
throw FormatException{"Segment 2 overrun"};
|
||||
size = readU16BE(vga.begin()+segOfs[1]+seg2Idx);
|
||||
seg2Idx += 2;
|
||||
@@ -371,7 +371,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga)
|
||||
if (!segOfs[1] ||
|
||||
(segOfs[2] && (segOfs[1]+seg2Idx+2 >= segOfs[2])) ||
|
||||
(segOfs[3] && (segOfs[1]+seg2Idx >= segOfs[3])) ||
|
||||
(segOfs[1]+seg2Idx+2 >= vga.getSize()))
|
||||
(segOfs[1]+seg2Idx+2 >= vga.size()))
|
||||
throw FormatException{"Segment 2 overrun"};
|
||||
size = readU24BE(vga.begin()+segOfs[1]+seg2Idx);
|
||||
seg2Idx += 3;
|
||||
@@ -410,7 +410,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga)
|
||||
#endif
|
||||
if (!segOfs[2] ||
|
||||
(segOfs[3] && (segOfs[2]+seg3Idx > segOfs[3])) ||
|
||||
(segOfs[2]+seg3Idx > vga.getSize()))
|
||||
(segOfs[2]+seg3Idx > vga.size()))
|
||||
throw FormatException{"Segment 3 overrun"};
|
||||
|
||||
const uint8_t mpos = vga.begin()[segOfs[2]+seg3Idx++];
|
||||
@@ -467,7 +467,7 @@ void audioCB_(void* userdata, uint8_t *buf, int len)
|
||||
}
|
||||
|
||||
while ((len > 0) && cbdata->cur) {
|
||||
if (cbdata->pos >= (*cbdata->aCur)->getSize()) {
|
||||
if (cbdata->pos >= (*cbdata->aCur)->size()) {
|
||||
cbdata->pos = 0;
|
||||
++cbdata->aCur;
|
||||
if (cbdata->aCur == cbdata->cur->AUDIs.end()) {
|
||||
@@ -484,8 +484,8 @@ void audioCB_(void* userdata, uint8_t *buf, int len)
|
||||
|
||||
auto& aCur = *cbdata->aCur;
|
||||
size_t toCopy = len;
|
||||
if (cbdata->pos+toCopy > aCur->getSize())
|
||||
toCopy = aCur->getSize()-cbdata->pos;
|
||||
if (cbdata->pos+toCopy > aCur->size())
|
||||
toCopy = aCur->size()-cbdata->pos;
|
||||
std::copy(aCur->begin()+cbdata->pos, aCur->begin()+cbdata->pos+toCopy,
|
||||
buf);
|
||||
len -= toCopy;
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
|
||||
#include "IffFile.hh"
|
||||
|
||||
class Resource;
|
||||
|
||||
class MveDecoder {
|
||||
public:
|
||||
MveDecoder(uint8_t const* base, size_t length);
|
||||
MveDecoder(Resource const& res);
|
||||
|
||||
size_t numBranches() const {
|
||||
return branches_.size();
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#include "exceptions.hh"
|
||||
#include "util.hh"
|
||||
|
||||
ObjDecoder::ObjDecoder(uint8_t const* base, size_t length)
|
||||
: iff_(base, length)
|
||||
ObjDecoder::ObjDecoder(Resource const& res)
|
||||
: iff_(res)
|
||||
{
|
||||
auto& root = iff_.getRoot();
|
||||
if (!root.isForm())
|
||||
@@ -17,7 +17,7 @@ ObjDecoder::ObjDecoder(uint8_t const* base, size_t length)
|
||||
|
||||
for (auto realIt = rootForm.childrenBegin();realIt != rootForm.childrenEnd();++realIt) {
|
||||
if (realIt->getType() == "INFO") {
|
||||
name_ = *realIt;
|
||||
name_ = static_cast<std::string>(*realIt);
|
||||
printf("Name: \"%s\"\n", name_.c_str());
|
||||
} else if (realIt->isForm()) {
|
||||
auto& itForm = dynamic_cast<IffFile::Form const&>(*realIt);
|
||||
@@ -79,9 +79,9 @@ void ObjDecoder::parsePOLY_(IffFile::Form const& form)
|
||||
for (auto it = form.childrenBegin();it != form.childrenEnd();++it) {
|
||||
if (it->getType() == "INFO") {
|
||||
} else if (it->getType() == "VERT") {
|
||||
if (it->getSize()%12 != 0)
|
||||
if (it->size()%12 != 0)
|
||||
throw FormatException{"Unexpected VERT size"};
|
||||
for (size_t i = 0;i < it->getSize();i+=12) {
|
||||
for (size_t i = 0;i < it->size();i+=12) {
|
||||
std::array<int32_t, 3> vertex;
|
||||
for (size_t j = 0;j < 3;++j)
|
||||
vertex[j] = readU32LE(it->begin()+i+j*4);
|
||||
@@ -137,10 +137,10 @@ void ObjDecoder::parseTRIS_(IffFile::Form const& form)
|
||||
|
||||
assert(face && maps);
|
||||
|
||||
if (face->getSize()%8 != 0)
|
||||
if (face->size()%8 != 0)
|
||||
throw FormatException{"Unexpected FACE size"};
|
||||
auto numTriangles = face->getSize()/8;
|
||||
if (maps->getSize() != numTriangles*16)
|
||||
auto numTriangles = face->size()/8;
|
||||
if (maps->size() != numTriangles*16)
|
||||
printf("WARNING: Unexpected MAPS size\n");
|
||||
// throw FormatException{"Unexpected MAPS size"};
|
||||
|
||||
@@ -185,10 +185,10 @@ void ObjDecoder::parseQUAD_(IffFile::Form const& form)
|
||||
|
||||
assert(face && maps);
|
||||
|
||||
if (face->getSize()%10 != 0)
|
||||
if (face->size()%10 != 0)
|
||||
throw FormatException{"Unexpected FACE size"};
|
||||
auto numQuads = face->getSize()/10;
|
||||
if (maps->getSize() != numQuads*20)
|
||||
auto numQuads = face->size()/10;
|
||||
if (maps->size() != numQuads*20)
|
||||
printf("WARNING: Unexpected MAPS size\n");
|
||||
//throw FormatException{"Unexpected MAPS size"};
|
||||
|
||||
@@ -225,12 +225,12 @@ void ObjDecoder::parseDETA_(IffFile::Form const& form)
|
||||
if (std::stoi(it->getType().substr(3)) != lvl)
|
||||
throw FormatException{"Unexpected detail level"};
|
||||
|
||||
if (it->getSize() < 4)
|
||||
if (it->size() < 4)
|
||||
throw FormatException{"DETA child too small"};
|
||||
|
||||
// uint32_t unkown = readU32LE(it->begin());
|
||||
detailLevels_.emplace_back();
|
||||
for (size_t pos = 4;pos < it->getSize()-1;pos += 2)
|
||||
for (size_t pos = 4;pos < it->size()-1;pos += 2)
|
||||
detailLevels_.back().push_back(readU16LE(it->begin()+pos));
|
||||
|
||||
printf("LVL %u: %lu entries\n", lvl, detailLevels_.back().size());
|
||||
@@ -250,7 +250,7 @@ void ObjDecoder::parseTXMS_(IffFile::Form const& form)
|
||||
auto& info = *it++;
|
||||
if (info.getType() != "INFO")
|
||||
throw FormatException{"Missing INFO in TXMS"};
|
||||
if (info.getSize() != 4)
|
||||
if (info.size() != 4)
|
||||
throw FormatException{"Unexpected INFO size in TXMS"};
|
||||
|
||||
uint16_t numTXMP, numTXMA;
|
||||
@@ -263,7 +263,7 @@ void ObjDecoder::parseTXMS_(IffFile::Form const& form)
|
||||
texAnims_.reserve(numTXMA);
|
||||
for (;it != form.childrenEnd();++it) {
|
||||
if (it->getType() == "TXMP") {
|
||||
if (it->getSize() < 12u)
|
||||
if (it->size() < 12u)
|
||||
throw FormatException{"TXMP smaller than header"};
|
||||
|
||||
Texture tex;
|
||||
@@ -277,12 +277,12 @@ void ObjDecoder::parseTXMS_(IffFile::Form const& form)
|
||||
tex.height = readU16LE(it->begin()+10);
|
||||
printf("TXMP size %hux%hu\n", tex.width, tex.height);
|
||||
|
||||
if (it->getSize() < 12u+tex.width*tex.height)
|
||||
if (it->size() < 12u+tex.width*tex.height)
|
||||
throw FormatException{"TXMP too small for pixel data"};
|
||||
tex.pixels = std::vector<uint8_t>(it->begin()+12, it->begin()+12+tex.width*tex.height);
|
||||
textures_.emplace_back(std::move(tex));
|
||||
} else if (it->getType() == "TXMA") {
|
||||
if (it->getSize() < 14u)
|
||||
if (it->size() < 14u)
|
||||
throw FormatException{"TXMA smaller than header"};
|
||||
|
||||
TextureAnimation tex;
|
||||
@@ -297,7 +297,7 @@ void ObjDecoder::parseTXMS_(IffFile::Form const& form)
|
||||
tex.frames = readU16LE(it->begin()+12);
|
||||
printf("TXMA size %hux%hu, %hu frames\n", tex.width, tex.height, tex.frames);
|
||||
|
||||
if (it->getSize() < 14u+tex.width*tex.height*tex.frames)
|
||||
if (it->size() < 14u+tex.width*tex.height*tex.frames)
|
||||
throw FormatException{"TXMA too small for pixel data"};
|
||||
|
||||
tex.pixels.reserve(tex.frames);
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
|
||||
#include "IffFile.hh"
|
||||
|
||||
class Resource;
|
||||
|
||||
class ObjDecoder {
|
||||
public:
|
||||
ObjDecoder(uint8_t const* base, size_t length);
|
||||
ObjDecoder(Resource const& res);
|
||||
|
||||
using Vertex = std::array<int32_t, 3>;
|
||||
using Vertices = std::vector<Vertex>;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "PaletteDecoder.hh"
|
||||
#include "exceptions.hh"
|
||||
|
||||
PaletteDecoder::PaletteDecoder(uint8_t const* base, size_t length)
|
||||
: iff_(base, length)
|
||||
PaletteDecoder::PaletteDecoder(Resource const& res)
|
||||
: iff_(res)
|
||||
{
|
||||
auto& root = iff_.getRoot();
|
||||
if (!root.isForm())
|
||||
@@ -20,6 +20,21 @@ PaletteDecoder::PaletteDecoder(uint8_t const* base, size_t length)
|
||||
std::transform(paltIt->begin()+4, paltIt->begin()+772,
|
||||
palette_.begin(),
|
||||
[](const char& in) -> uint8_t {return (in << 2) | ((in >> 6)&0x3);});
|
||||
uint8_t min = 0xff, max = 0;
|
||||
for (auto it = paltIt->begin()+4;it != paltIt->end();++it) {
|
||||
if (*it == 0xff)
|
||||
continue;
|
||||
min = std::min(min, *it);
|
||||
max = std::max(max, *it);
|
||||
}
|
||||
|
||||
printf("palt value range %hhu..%hhu\n", min, max);
|
||||
} else if (paltIt->getType() == "BLWH") {
|
||||
auto dstIt = palette_.begin();
|
||||
for (auto it = paltIt->begin()+4;it != paltIt->end();++it) {
|
||||
*dstIt = *dstIt * ((*it << 2) | ((*it >> 6)&0x3)) / 255u;
|
||||
++dstIt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
class PaletteDecoder {
|
||||
public:
|
||||
PaletteDecoder(uint8_t const* base, size_t length);
|
||||
PaletteDecoder(Resource const& res);
|
||||
|
||||
using Palette = std::array<uint8_t, 768>;
|
||||
|
||||
|
||||
18
Resource.hh
Normal file
18
Resource.hh
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef WC3RE_RESOURCE_HH__
|
||||
#define WC3RE_RESOURCE_HH__
|
||||
|
||||
// Interface for any memory-resident resource
|
||||
// For example mmap'd data file, TRE object, IFF Object, ...
|
||||
|
||||
class Resource {
|
||||
public:
|
||||
virtual ~Resource() {}
|
||||
|
||||
virtual uint8_t const* data() const = 0;
|
||||
virtual size_t size() const = 0;
|
||||
|
||||
virtual operator bool() const = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
13
TreFile.hh
13
TreFile.hh
@@ -8,6 +8,8 @@
|
||||
#include <tuple>
|
||||
#include <experimental/optional>
|
||||
|
||||
#include "Resource.hh"
|
||||
|
||||
class TreFile {
|
||||
public:
|
||||
TreFile(uint8_t const* base, size_t length);
|
||||
@@ -27,7 +29,7 @@ public:
|
||||
'path' */
|
||||
static uint32_t calcCRC(std::string const& path);
|
||||
|
||||
class Object {
|
||||
class Object : public Resource {
|
||||
public:
|
||||
Object() : base_(nullptr), length_(0) {
|
||||
}
|
||||
@@ -50,19 +52,22 @@ public:
|
||||
move.length_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Object() override {
|
||||
}
|
||||
|
||||
uint8_t const* data() const {
|
||||
uint8_t const* data() const override {
|
||||
if (data_)
|
||||
return data_->data();
|
||||
else
|
||||
return base_;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
size_t size() const override {
|
||||
return length_;
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
operator bool() const override {
|
||||
return data_ || base_;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
#include "util.hh"
|
||||
#include "IffFile.hh"
|
||||
|
||||
void blobDump(IffFile::Object const& obj, std::string const& filename)
|
||||
void blobDump(Resource const& obj, std::string const& filename)
|
||||
{
|
||||
FILEUPtr file{fopen(filename.c_str(), "wb")};
|
||||
if (!file)
|
||||
throw POSIXException{errno, "Could not open file: " + filename};
|
||||
|
||||
if (fwrite(obj.begin(), obj.getSize(), 1, file.get()) != 1)
|
||||
if (fwrite(obj.data(), obj.size(), 1, file.get()) != 1)
|
||||
throw POSIXException{errno, "Could not write"};
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ void iffDumper(IffFile::Object const& obj, bool dumpBlobs, std::string dumpPath,
|
||||
{
|
||||
for (unsigned i = 0;i < level;++i)
|
||||
putchar('\t');
|
||||
printf("%s Length %lu (0x%.lx)", obj.getType().c_str(), obj.getSize(), obj.getSize());
|
||||
printf("%s Length %lu (0x%.lx)", obj.getType().c_str(), obj.size(), obj.size());
|
||||
|
||||
if (obj.isForm()) {
|
||||
auto& form = dynamic_cast<IffFile::Form const&>(obj);
|
||||
@@ -88,7 +88,7 @@ int main(int argc, char *argv[])
|
||||
try {
|
||||
MmapFile mmap{iffFile};
|
||||
|
||||
IffFile iff{mmap.data(), mmap.size()};
|
||||
IffFile iff{mmap};
|
||||
|
||||
if (printStructure) {
|
||||
unsigned blobCount = 0, subdoc = 0;
|
||||
|
||||
@@ -87,9 +87,9 @@ int main(int argc, char *argv[]) {
|
||||
if (!object) // Wasn't a CRC, try as name
|
||||
object = tre->openName(objectSpec);
|
||||
|
||||
mve = std::make_unique<MveDecoder>(object.data(), object.size());
|
||||
mve = std::make_unique<MveDecoder>(object);
|
||||
} else
|
||||
mve = std::make_unique<MveDecoder>(mmap.data(), mmap.size());
|
||||
mve = std::make_unique<MveDecoder>(mmap);
|
||||
|
||||
if (play) {
|
||||
Renderer renderer;
|
||||
|
||||
18
objdecode.cc
18
objdecode.cc
@@ -17,21 +17,25 @@
|
||||
#include "game/GSShowObject.hh"
|
||||
|
||||
void usage(char *argv0) {
|
||||
fprintf(stderr, "Usage: %s [-h] (tre-file name/crc)/iff-file\n", argv0);
|
||||
fprintf(stderr, "Usage: %s [-h] [-ppalt] (tre-file name/crc)/iff-file\n", argv0);
|
||||
fprintf(stderr, "\tAttempt to decode the object stored in iff-file, or in the\n\tiff-object \"name\"/\"crc\" contained in tre-file\n");
|
||||
fprintf(stderr, "\t-p palt\tUse palette \"palt\"");
|
||||
fprintf(stderr, "\t-h\tPrint this help\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::string inFile, objectSpec;
|
||||
std::string inFile, objectSpec, paltFile = "tmp/1DC61F50";
|
||||
bool useTre = false;
|
||||
{
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "h")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "hp:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
case 'p':
|
||||
paltFile = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
@@ -52,8 +56,8 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
try {
|
||||
MmapFile paltMmap{"tmp/1DC61F50"};
|
||||
PaletteDecoder palt{paltMmap.data(), paltMmap.size()};
|
||||
MmapFile paltMmap{paltFile};
|
||||
PaletteDecoder palt{paltMmap};
|
||||
|
||||
MmapFile mmap{inFile};
|
||||
|
||||
@@ -77,9 +81,9 @@ int main(int argc, char *argv[]) {
|
||||
if (!object) // Wasn't a CRC, try as name
|
||||
object = tre->openName(objectSpec);
|
||||
|
||||
obj = std::make_unique<ObjDecoder>(object.data(), object.size());
|
||||
obj = std::make_unique<ObjDecoder>(object);
|
||||
} else
|
||||
obj = std::make_unique<ObjDecoder>(mmap.data(), mmap.size());
|
||||
obj = std::make_unique<ObjDecoder>(mmap);
|
||||
|
||||
render::Renderer renderer;
|
||||
renderer.pushGS(std::make_unique<game::GSShowObject>(renderer, *obj, palt));
|
||||
|
||||
@@ -74,7 +74,7 @@ int main(int argc, char *argv[]) {
|
||||
continue;
|
||||
auto f = file.openName(name);
|
||||
try {
|
||||
IffFile iff{f.data(), f.size()};
|
||||
IffFile iff{f};
|
||||
printf("%s:\n", name.c_str());
|
||||
iff.printStructure(1);
|
||||
} catch(FormatException &ex) {
|
||||
@@ -85,7 +85,7 @@ int main(int argc, char *argv[]) {
|
||||
for(auto crc : file.getCRCs()) {
|
||||
auto f = file.openCRC(crc);
|
||||
try {
|
||||
IffFile iff{f.data(), f.size()};
|
||||
IffFile iff{f};
|
||||
printf("%.8x:\n", crc);
|
||||
iff.printStructure(1);
|
||||
} catch(FormatException &ex) {
|
||||
|
||||
11
util.hh
11
util.hh
@@ -5,23 +5,24 @@
|
||||
#include <string>
|
||||
|
||||
#include "common.hh"
|
||||
#include "Resource.hh"
|
||||
|
||||
class MmapFile {
|
||||
class MmapFile : public Resource {
|
||||
public:
|
||||
MmapFile(std::string fileName);
|
||||
MmapFile(MmapFile const& copy) = delete;
|
||||
MmapFile(MmapFile && move);
|
||||
|
||||
~MmapFile();
|
||||
~MmapFile() override;
|
||||
|
||||
MmapFile& operator=(MmapFile const& copy) = delete;
|
||||
MmapFile& operator=(MmapFile && move);
|
||||
|
||||
std::string const& name() const;
|
||||
size_t size() const;
|
||||
uint8_t const* data() const;
|
||||
size_t size() const override;
|
||||
uint8_t const* data() const override;
|
||||
|
||||
operator bool() const;
|
||||
operator bool() const override;
|
||||
private:
|
||||
std::string name_;
|
||||
FILEUPtr fd_;
|
||||
|
||||
Reference in New Issue
Block a user