86 lines
2.6 KiB
C++
86 lines
2.6 KiB
C++
#include <cstring>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <algorithm>
|
|
|
|
#include <exceptions.hh>
|
|
|
|
#include "util.hh"
|
|
#include "Resource.hh"
|
|
#include "ResourceProvider.hh"
|
|
#include "ShapDecoder.hh"
|
|
|
|
ShapDecoder::ShapDecoder(std::string const& path)
|
|
: ShapDecoder(ResourceProvider::getInstance().getResource(path)) {
|
|
}
|
|
|
|
ShapDecoder::ShapDecoder(Resource::Handle res)
|
|
: res_(std::move(res))
|
|
{
|
|
if (res_->size() < 8)
|
|
throw FormatException{"Object smaller than header size"};
|
|
|
|
if (memcmp(res_->data(), "1.11", 4) != 0)
|
|
throw FormatException{"Wrong magic, not a SHAP?"};
|
|
|
|
uint32_t numSubObjs = readU32LE(res_->data()+4);
|
|
|
|
if (res_->size() < 8+numSubObjs*8)
|
|
throw FormatException{"Object smaller than subobject table size"};
|
|
|
|
uint32_t lastofs = 0;
|
|
for (uint32_t i = 0;i < numSubObjs;++i) {
|
|
uint32_t ofs = readU32LE(res_->data()+8+i*8);
|
|
if (lastofs)
|
|
printf("\t%u bytes of data\n", ofs-(lastofs+24));
|
|
lastofs = ofs;
|
|
uint32_t flags = readU32LE(res_->data()+8+i*8+4);
|
|
|
|
printf("Subobject %u: Ofs %u (0x%x), flags %.8x\n",
|
|
i, ofs, ofs, flags);
|
|
|
|
if (res_->size() < ofs+24)
|
|
throw FormatException{"Subobject header exceeds resource"};
|
|
|
|
uint16_t unk1 = readU16LE(res_->data()+ofs), unk2 = readU16LE(res_->data()+ofs+2),
|
|
unk3 = readU16LE(res_->data()+ofs+4), unk4 = readU16LE(res_->data()+ofs+6);
|
|
int32_t unk5 = readU32LE(res_->data()+ofs+8), unk6 = readU32LE(res_->data()+ofs+12);
|
|
uint32_t unk7 = readU32LE(res_->data()+ofs+16), unk8 = readU32LE(res_->data()+ofs+20);
|
|
|
|
printf("\tunk: %hu, %hu, %hu, %hu, %d, %d, %u, %u\n",
|
|
unk1, unk2, unk3, unk4, unk5, unk6, unk7, unk8);
|
|
|
|
std::vector<unsigned> hist(256, 0);
|
|
std::map<uint16_t, unsigned> hist2;
|
|
uint32_t end;
|
|
if (i < numSubObjs-1)
|
|
end = readU32LE(res_->data()+8+(i+1)*8);
|
|
else
|
|
end = res_->size();
|
|
uint16_t sreg = 0;
|
|
for (uint8_t const* it = res_->data()+ofs+24;it < res_->data()+end;++it) {
|
|
++hist.at(*it);
|
|
sreg = (sreg<<8)|*it;
|
|
++hist2[sreg];
|
|
}
|
|
|
|
for (unsigned i = 0;i < 256;++i)
|
|
if (hist[i])
|
|
printf("\t%.2x: %u\n", i, hist[i]);
|
|
|
|
std::vector<std::pair<uint16_t, unsigned> > sortedHist2(20);
|
|
std::partial_sort_copy
|
|
(hist2.begin(), hist2.end(),
|
|
sortedHist2.begin(), sortedHist2.end(),
|
|
[](std::pair<uint16_t, unsigned> const& a, std::pair<uint16_t, unsigned> const& b) -> bool {
|
|
return a.second > b.second;
|
|
});
|
|
|
|
for (auto& ent: sortedHist2)
|
|
if (ent.second > 1)
|
|
printf("\t%.4x: %u\n", ent.first, ent.second);
|
|
|
|
}
|
|
printf("\t%zu bytes of data\n", res_->size()-(lastofs+24));
|
|
}
|