1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
/* Copyright (C) Teemu Suutari */
#include "Decompressor.hpp"
#include <memory>
#include <vector>
#include "BZIP2Decompressor.hpp"
#include "CompactDecompressor.hpp"
#include "CompressDecompressor.hpp"
#include "CRMDecompressor.hpp"
#include "DEFLATEDecompressor.hpp"
#include "DMSDecompressor.hpp"
#include "FreezeDecompressor.hpp"
#include "IMPDecompressor.hpp"
#include "LOBDecompressor.hpp"
#include "MMCMPDecompressor.hpp"
#include "PackDecompressor.hpp"
#include "PPDecompressor.hpp"
#include "RNCDecompressor.hpp"
#include "SCOCompressDecompressor.hpp"
#include "StoneCrackerDecompressor.hpp"
#include "TPWMDecompressor.hpp"
#include "VicXDecompressor.hpp"
#include "XPKMain.hpp"
namespace ancient::internal
{
// ---
static std::vector<std::pair<bool(*)(uint32_t),std::shared_ptr<Decompressor>(*)(const Buffer&,bool,bool)>> decompressors={
{BZIP2Decompressor::detectHeader,BZIP2Decompressor::create},
{CompactDecompressor::detectHeader,CompactDecompressor::create},
{CompressDecompressor::detectHeader,CompressDecompressor::create},
{CRMDecompressor::detectHeader,CRMDecompressor::create},
{DEFLATEDecompressor::detectHeader,DEFLATEDecompressor::create},
{DMSDecompressor::detectHeader,DMSDecompressor::create},
{FreezeDecompressor::detectHeader,FreezeDecompressor::create},
{IMPDecompressor::detectHeader,IMPDecompressor::create},
{LOBDecompressor::detectHeader,LOBDecompressor::create},
{MMCMPDecompressor::detectHeader,MMCMPDecompressor::create},
{PackDecompressor::detectHeader,PackDecompressor::create},
{PPDecompressor::detectHeader,PPDecompressor::create},
{RNCDecompressor::detectHeader,RNCDecompressor::create},
{SCOCompressDecompressor::detectHeader,SCOCompressDecompressor::create},
{TPWMDecompressor::detectHeader,TPWMDecompressor::create},
{VicXDecompressor::detectHeader,VicXDecompressor::create},
{XPKMain::detectHeader,XPKMain::create},
// Putting StoneCracker last since detection can be accidentally be detected instead of correct format
{StoneCrackerDecompressor::detectHeader,StoneCrackerDecompressor::create}
};
std::shared_ptr<Decompressor> Decompressor::create(const Buffer &packedData,bool exactSizeKnown,bool verify)
{
try
{
uint32_t hdr{(packedData.size()>=4)?packedData.readBE32(0):(uint32_t(packedData.readBE16(0))<<16)};
for (auto &it : decompressors)
{
if (it.first(hdr)) return it.second(packedData,exactSizeKnown,verify);
}
throw InvalidFormatError();
} catch (const Buffer::Error&) {
throw InvalidFormatError();
}
}
bool Decompressor::detect(const Buffer &packedData) noexcept
{
if (packedData.size()<2) return false;
try
{
uint32_t hdr{(packedData.size()>=4)?packedData.readBE32(0):(uint32_t(packedData.readBE16(0))<<16)};
for (auto &it : decompressors)
if (it.first(hdr)) return true;
return false;
} catch (const Buffer::Error&) {
return false;
}
}
void Decompressor::decompress(Buffer &rawData,bool verify)
{
// Simplifying the implementation of sub-decompressors. Just let the buffer-exception pass here,
// and that will get translated into Decompressor exceptions
try
{
decompressImpl(rawData,verify);
} catch (const Buffer::Error&) {
throw DecompressionError();
}
}
size_t Decompressor::getImageSize() const noexcept
{
return 0;
}
size_t Decompressor::getImageOffset() const noexcept
{
return 0;
}
// 1G should be enough for everyone (this is retro!)
size_t Decompressor::getMaxPackedSize() noexcept
{
return 0x4000'0000U;
}
size_t Decompressor::getMaxRawSize() noexcept
{
return 0x4000'0000U;
}
}
|