mirror of
https://github.com/SAT-R/sa2.git
synced 2026-10-28 09:43:38 +00:00
81 lines
2.7 KiB
C
81 lines
2.7 KiB
C
// Copyright (c) 2015 YamaArashi
|
|
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#define FATAL_ERROR(format, ...) \
|
|
do { \
|
|
fprintf(stderr, format, __VA_ARGS__); \
|
|
exit(1); \
|
|
} while (0)
|
|
|
|
#define UNUSED
|
|
|
|
#else
|
|
|
|
#define FATAL_ERROR(format, ...) \
|
|
do { \
|
|
fprintf(stderr, format, ##__VA_ARGS__); \
|
|
exit(1); \
|
|
} while (0)
|
|
|
|
#define UNUSED __attribute__((__unused__))
|
|
|
|
#endif // _MSC_VER
|
|
|
|
void LZDecompressUnsafe(unsigned char *src, unsigned char *dest, int *uncompressedSize)
|
|
{
|
|
int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
|
|
|
|
if (dest == NULL)
|
|
goto fail;
|
|
|
|
int srcPos = 4;
|
|
int destPos = 0;
|
|
|
|
for (;;) {
|
|
unsigned char flags = src[srcPos++];
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
if (flags & 0x80) {
|
|
int blockSize = (src[srcPos] >> 4) + 3;
|
|
int blockDistance = (((src[srcPos] & 0xF) << 8) | src[srcPos + 1]) + 1;
|
|
|
|
srcPos += 2;
|
|
|
|
int blockPos = destPos - blockDistance;
|
|
|
|
// Some Ruby/Sapphire tilesets overflow.
|
|
if (destPos + blockSize > destSize) {
|
|
blockSize = destSize - destPos;
|
|
fprintf(stderr, "Destination buffer overflow.\n");
|
|
}
|
|
|
|
if (blockPos < 0)
|
|
goto fail;
|
|
|
|
for (int j = 0; j < blockSize; j++)
|
|
dest[destPos++] = dest[blockPos + j];
|
|
} else {
|
|
if (destPos >= destSize)
|
|
goto fail;
|
|
|
|
dest[destPos++] = src[srcPos++];
|
|
}
|
|
|
|
if (destPos == destSize) {
|
|
*uncompressedSize = destSize;
|
|
return;
|
|
}
|
|
|
|
flags <<= 1;
|
|
}
|
|
}
|
|
|
|
fail:
|
|
FATAL_ERROR("Fatal error while decompressing LZ file.\n");
|
|
}
|