mirror of
https://github.com/red031000/nitrogfx.git
synced 2025-06-18 21:25:38 -04:00
Restore backward lookback function, add -reverse option to LZ compression command
This commit is contained in:
parent
fc527bccbd
commit
b934160afb
81
lz.c
81
lz.c
@ -71,7 +71,58 @@ fail:
|
||||
FATAL_ERROR("Fatal error while decompressing LZ file.\n");
|
||||
}
|
||||
|
||||
unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance)
|
||||
static void FindBestBlockForwards(unsigned char *src, int srcPos, int srcSize, const int minDistance, int *outBestBlockDistance, int *outBestBlockSize)
|
||||
{
|
||||
int blockStart = srcPos < 0x1000 ? 0 : srcPos - 0x1000;
|
||||
while (blockStart != srcPos) {
|
||||
int blockSize = 0;
|
||||
|
||||
while (blockSize < 18
|
||||
&& srcPos + blockSize < srcSize
|
||||
&& src[blockStart + blockSize] == src[srcPos + blockSize])
|
||||
blockSize++;
|
||||
|
||||
if (blockSize > *outBestBlockSize
|
||||
&& srcPos - blockStart >= minDistance) {
|
||||
*outBestBlockDistance = srcPos - blockStart;
|
||||
*outBestBlockSize = blockSize;
|
||||
|
||||
if (blockSize == 18)
|
||||
break;
|
||||
}
|
||||
|
||||
blockStart++;
|
||||
}
|
||||
}
|
||||
|
||||
static void FindBestBlockBackwards(unsigned char *src, int srcPos, int srcSize, const int minDistance, int *outBestBlockDistance, int *outBestBlockSize)
|
||||
{
|
||||
int blockDistance = minDistance;
|
||||
|
||||
while (blockDistance <= srcPos && blockDistance <= 0x1000) {
|
||||
int blockStart = srcPos - blockDistance;
|
||||
int blockSize = 0;
|
||||
|
||||
while (blockSize < 18
|
||||
&& srcPos + blockSize < srcSize
|
||||
&& src[blockStart + blockSize] == src[srcPos + blockSize])
|
||||
blockSize++;
|
||||
|
||||
if (blockSize > *outBestBlockSize) {
|
||||
*outBestBlockDistance = blockDistance;
|
||||
*outBestBlockSize = blockSize;
|
||||
|
||||
if (blockSize == 18)
|
||||
break;
|
||||
}
|
||||
|
||||
blockDistance++;
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*FindBestBlockFunc)(unsigned char *src, int srcPos, int srcSize, const int minDistance, int *outBestBlockDistance, int *outBestBlockSize);
|
||||
|
||||
unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance, bool forwardIteration)
|
||||
{
|
||||
if (srcSize <= 0)
|
||||
goto fail;
|
||||
@ -94,7 +145,7 @@ unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize,
|
||||
|
||||
int srcPos = 0;
|
||||
int destPos = 4;
|
||||
int lookbackStart = 0;
|
||||
FindBestBlockFunc FindBestBlock = forwardIteration ? FindBestBlockForwards : FindBestBlockBackwards;
|
||||
|
||||
for (;;) {
|
||||
unsigned char *flags = &dest[destPos++];
|
||||
@ -104,42 +155,18 @@ unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize,
|
||||
int bestBlockDistance = 0;
|
||||
int bestBlockSize = 0;
|
||||
|
||||
int blockStart = lookbackStart;
|
||||
while (blockStart != srcPos) {
|
||||
int blockSize = 0;
|
||||
FindBestBlock(src, srcPos, srcSize, minDistance, &bestBlockDistance, &bestBlockSize);
|
||||
|
||||
while (blockSize < 18
|
||||
&& srcPos + blockSize < srcSize
|
||||
&& src[blockStart + blockSize] == src[srcPos + blockSize])
|
||||
blockSize++;
|
||||
|
||||
if (blockSize > bestBlockSize
|
||||
&& srcPos - blockStart >= minDistance) {
|
||||
bestBlockDistance = srcPos - blockStart;
|
||||
bestBlockSize = blockSize;
|
||||
|
||||
if (blockSize == 18)
|
||||
break;
|
||||
}
|
||||
|
||||
blockStart++;
|
||||
}
|
||||
|
||||
int lookbackJump = 0;
|
||||
if (bestBlockSize >= 3) {
|
||||
*flags |= (0x80 >> i);
|
||||
srcPos += bestBlockSize;
|
||||
lookbackJump = srcPos - lookbackStart > 0x1000 ? bestBlockSize : 0;
|
||||
|
||||
bestBlockSize -= 3;
|
||||
bestBlockDistance--;
|
||||
dest[destPos++] = (bestBlockSize << 4) | ((unsigned int)bestBlockDistance >> 8);
|
||||
dest[destPos++] = (unsigned char)bestBlockDistance;
|
||||
} else {
|
||||
lookbackJump = (int)(srcPos - lookbackStart > 0x1000);
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
lookbackStart += lookbackJump;
|
||||
|
||||
if (srcPos == srcSize) {
|
||||
// Pad to multiple of 4 bytes.
|
||||
|
4
lz.h
4
lz.h
@ -3,7 +3,9 @@
|
||||
#ifndef LZ_H
|
||||
#define LZ_H
|
||||
|
||||
#include "stdbool.h"
|
||||
|
||||
unsigned char *LZDecompress(unsigned char *src, int srcSize, int *uncompressedSize);
|
||||
unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance);
|
||||
unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance, bool forwardIteration);
|
||||
|
||||
#endif // LZ_H
|
||||
|
7
main.c
7
main.c
@ -955,6 +955,7 @@ void HandleLZCompressCommand(char *inputPath, char *outputPath, int argc, char *
|
||||
{
|
||||
int overflowSize = 0;
|
||||
int minDistance = 2; // default, for compatibility with LZ77UnCompVram()
|
||||
bool forwardIteration = true;
|
||||
|
||||
for (int i = 3; i < argc; i++)
|
||||
{
|
||||
@ -986,6 +987,10 @@ void HandleLZCompressCommand(char *inputPath, char *outputPath, int argc, char *
|
||||
if (minDistance < 1)
|
||||
FATAL_ERROR("LZ min search distance must be positive.\n");
|
||||
}
|
||||
else if (strcmp(option, "-reverse") == 0)
|
||||
{
|
||||
forwardIteration = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
FATAL_ERROR("Unrecognized option \"%s\".\n", option);
|
||||
@ -1002,7 +1007,7 @@ void HandleLZCompressCommand(char *inputPath, char *outputPath, int argc, char *
|
||||
unsigned char *buffer = ReadWholeFileZeroPadded(inputPath, &fileSize, overflowSize);
|
||||
|
||||
int compressedSize;
|
||||
unsigned char *compressedData = LZCompress(buffer, fileSize + overflowSize, &compressedSize, minDistance);
|
||||
unsigned char *compressedData = LZCompress(buffer, fileSize + overflowSize, &compressedSize, minDistance, forwardIteration);
|
||||
|
||||
compressedData[1] = (unsigned char)fileSize;
|
||||
compressedData[2] = (unsigned char)(fileSize >> 8);
|
||||
|
Loading…
Reference in New Issue
Block a user