mirror of
https://github.com/hedge-dev/XenonRecomp.git
synced 2026-04-28 12:42:02 +00:00
Added normal compression handling to XenonAnalyse
This commit is contained in:
parent
51ae35da02
commit
fda7d86aec
3 changed files with 104 additions and 27 deletions
|
|
@ -5,6 +5,8 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <aes.hpp>
|
#include <aes.hpp>
|
||||||
|
#include <TinySHA1.hpp>
|
||||||
|
#include <xex_patcher.h>
|
||||||
|
|
||||||
#define STRINGIFY(X) #X
|
#define STRINGIFY(X) #X
|
||||||
#define XE_EXPORT(MODULE, ORDINAL, NAME, TYPE) { (ORDINAL), "__imp__" STRINGIFY(NAME) }
|
#define XE_EXPORT(MODULE, ORDINAL, NAME, TYPE) { (ORDINAL), "__imp__" STRINGIFY(NAME) }
|
||||||
|
|
@ -135,7 +137,7 @@ Image Xex2LoadImage(const uint8_t* data, size_t dataSize)
|
||||||
// Decompress image
|
// Decompress image
|
||||||
if (fileFormatInfo != nullptr)
|
if (fileFormatInfo != nullptr)
|
||||||
{
|
{
|
||||||
assert(fileFormatInfo->compressionType <= XEX_COMPRESSION_BASIC);
|
assert(fileFormatInfo->compressionType <= XEX_COMPRESSION_NORMAL);
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> decryptedData;
|
std::unique_ptr<uint8_t[]> decryptedData;
|
||||||
const uint8_t* srcData = nullptr;
|
const uint8_t* srcData = nullptr;
|
||||||
|
|
@ -192,6 +194,79 @@ Image Xex2LoadImage(const uint8_t* data, size_t dataSize)
|
||||||
destData += blocks[i].zeroSize;
|
destData += blocks[i].zeroSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (fileFormatInfo->compressionType == XEX_COMPRESSION_NORMAL)
|
||||||
|
{
|
||||||
|
result = std::make_unique<uint8_t[]>(imageSize);
|
||||||
|
auto* destData = result.get();
|
||||||
|
|
||||||
|
const Xex2CompressedBlockInfo* blocks = &((const Xex2FileNormalCompressionInfo*)(fileFormatInfo + 1))->firstBlock;
|
||||||
|
const uint32_t headerSize = header->headerSize.get();
|
||||||
|
|
||||||
|
const uint32_t exeLength = dataSize - headerSize;
|
||||||
|
const uint8_t* exeBuffer = srcData;
|
||||||
|
|
||||||
|
uint8_t* compressBuffer = NULL;
|
||||||
|
const uint8_t* p = NULL;
|
||||||
|
uint8_t* d = NULL;
|
||||||
|
sha1::SHA1 s;
|
||||||
|
|
||||||
|
compressBuffer = (uint8_t*)calloc(1, exeLength);
|
||||||
|
|
||||||
|
p = exeBuffer;
|
||||||
|
d = compressBuffer;
|
||||||
|
|
||||||
|
int resultCode = 0;
|
||||||
|
|
||||||
|
uint8_t blockCalcedDigest[0x14];
|
||||||
|
while (blocks->blockSize) {
|
||||||
|
const uint8_t* pNext = p + blocks->blockSize;
|
||||||
|
const auto* nextBlock = (const Xex2CompressedBlockInfo*)p;
|
||||||
|
|
||||||
|
s.reset();
|
||||||
|
s.processBytes(p, blocks->blockSize);
|
||||||
|
s.finalize(blockCalcedDigest);
|
||||||
|
|
||||||
|
if (memcmp(blockCalcedDigest, blocks->blockHash, 0x14) != 0) {
|
||||||
|
resultCode = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 4;
|
||||||
|
p += 20;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const size_t chunkSize = (p[0] << 8) | p[1];
|
||||||
|
p += 2;
|
||||||
|
if (!chunkSize) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(d, p, chunkSize);
|
||||||
|
p += chunkSize;
|
||||||
|
d += chunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = pNext;
|
||||||
|
blocks = nextBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resultCode)
|
||||||
|
{
|
||||||
|
uint32_t uncompressedSize = security->imageSize;
|
||||||
|
uint8_t* buffer = destData;
|
||||||
|
|
||||||
|
resultCode = lzxDecompress(compressBuffer, d - compressBuffer, buffer, uncompressedSize, ((const Xex2FileNormalCompressionInfo*)(fileFormatInfo + 1))->windowSize, nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compressBuffer)
|
||||||
|
free((void*)compressBuffer);
|
||||||
|
|
||||||
|
if (resultCode)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image.data = std::move(result);
|
image.data = std::move(result);
|
||||||
|
|
|
||||||
|
|
@ -406,32 +406,32 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz
|
||||||
else if (fileFormatInfo->compressionType == XEX_COMPRESSION_NORMAL)
|
else if (fileFormatInfo->compressionType == XEX_COMPRESSION_NORMAL)
|
||||||
{
|
{
|
||||||
const Xex2CompressedBlockInfo* blocks = &((const Xex2FileNormalCompressionInfo*)(fileFormatInfo + 1))->firstBlock;
|
const Xex2CompressedBlockInfo* blocks = &((const Xex2FileNormalCompressionInfo*)(fileFormatInfo + 1))->firstBlock;
|
||||||
const uint32_t exe_length = xexBytesSize - xexHeader->headerSize.get();
|
const uint32_t exeLength = xexBytesSize - xexHeader->headerSize.get();
|
||||||
const uint8_t* exe_buffer = &outBytes[headerTargetSize];
|
const uint8_t* exeBuffer = &outBytes[headerTargetSize];
|
||||||
|
|
||||||
uint8_t* compress_buffer = NULL;
|
uint8_t* compressBuffer = NULL;
|
||||||
const uint8_t* p = NULL;
|
const uint8_t* p = NULL;
|
||||||
uint8_t* d = NULL;
|
uint8_t* d = NULL;
|
||||||
sha1::SHA1 s;
|
sha1::SHA1 s;
|
||||||
|
|
||||||
compress_buffer = (uint8_t*)calloc(1, exe_length);
|
compressBuffer = (uint8_t*)calloc(1, exeLength);
|
||||||
|
|
||||||
p = exe_buffer;
|
p = exeBuffer;
|
||||||
d = compress_buffer;
|
d = compressBuffer;
|
||||||
|
|
||||||
int result_code = 0;
|
int resultCode = 0;
|
||||||
|
|
||||||
uint8_t block_calced_digest[0x14];
|
uint8_t blockCalcedDigest[0x14];
|
||||||
while (blocks->blockSize) {
|
while (blocks->blockSize) {
|
||||||
const uint8_t* pnext = p + blocks->blockSize;
|
const uint8_t* pNext = p + blocks->blockSize;
|
||||||
const auto* next_block = (const Xex2CompressedBlockInfo*)p;
|
const auto* nextBlock = (const Xex2CompressedBlockInfo*)p;
|
||||||
|
|
||||||
s.reset();
|
s.reset();
|
||||||
s.processBytes(p, blocks->blockSize);
|
s.processBytes(p, blocks->blockSize);
|
||||||
s.finalize(block_calced_digest);
|
s.finalize(blockCalcedDigest);
|
||||||
|
|
||||||
if (memcmp(block_calced_digest, blocks->blockHash, 0x14) != 0) {
|
if (memcmp(blockCalcedDigest, blocks->blockHash, 0x14) != 0) {
|
||||||
result_code = 2;
|
resultCode = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -439,32 +439,32 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz
|
||||||
p += 20;
|
p += 20;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const size_t chunk_size = (p[0] << 8) | p[1];
|
const size_t chunkSize = (p[0] << 8) | p[1];
|
||||||
p += 2;
|
p += 2;
|
||||||
if (!chunk_size) {
|
if (!chunkSize) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(d, p, chunk_size);
|
memcpy(d, p, chunkSize);
|
||||||
p += chunk_size;
|
p += chunkSize;
|
||||||
d += chunk_size;
|
d += chunkSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = pnext;
|
p = pNext;
|
||||||
blocks = next_block;
|
blocks = nextBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result_code)
|
if (!resultCode)
|
||||||
{
|
{
|
||||||
uint32_t uncompressed_size = originalSecurityInfo->imageSize;
|
uint32_t uncompressedSize = originalSecurityInfo->imageSize;
|
||||||
uint8_t* buffer = outBytes.data() + newXexHeaderSize;
|
uint8_t* buffer = outBytes.data() + newXexHeaderSize;
|
||||||
result_code = lzxDecompress(compress_buffer, d - compress_buffer, buffer, uncompressed_size, ((const Xex2FileNormalCompressionInfo*)(fileFormatInfo + 1))->windowSize, nullptr, 0);
|
resultCode = lzxDecompress(compressBuffer, d - compressBuffer, buffer, uncompressedSize, ((const Xex2FileNormalCompressionInfo*)(fileFormatInfo + 1))->windowSize, nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compress_buffer)
|
if (compressBuffer)
|
||||||
free((void*)compress_buffer);
|
free((void*)compressBuffer);
|
||||||
|
|
||||||
if (result_code)
|
if (resultCode)
|
||||||
return Result::PatchFailed;
|
return Result::PatchFailed;
|
||||||
}
|
}
|
||||||
else if (fileFormatInfo->compressionType == XEX_COMPRESSION_DELTA)
|
else if (fileFormatInfo->compressionType == XEX_COMPRESSION_DELTA)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
extern int lzxDecompress(const void* lzxData, size_t lzxLength, void* dst, size_t dstLength, uint32_t windowSize, void* windowData, size_t windowDataLength);
|
||||||
|
|
||||||
struct XexPatcher
|
struct XexPatcher
|
||||||
{
|
{
|
||||||
enum class Result {
|
enum class Result {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue