Files
Diddy-Kong-Racing/tools/dkr_assets_tool_classes/libs/GECompression.cpp
T
2022-03-18 18:35:32 -04:00

1286 lines
32 KiB
C++

//#include "StdAfx.h"
#include "GECompression.h"
#include <math.h>
#define TABLE1 0
#define TABLE2 1
#define VARIABLETABLE 2
#define WORDTABLEBEGIN 3
#define WORDTABLEEND 4
GECompression::GECompression()
{
// inputBuffer = NULL;
compressedBuffer = NULL;
// inputBufferSize = 0;
compressedBufferSize = 0;
wordTable = NULL;
unpackTable = NULL;
game = GOLDENEYE;
unpackTable = new tableEntry[0xFFFF];
}
GECompression::~GECompression(void)
{
if (unpackTable != NULL)
{
delete [] unpackTable;
unpackTable = NULL;
}
if (wordTable != NULL)
{
delete [] wordTable;
wordTable = NULL;
}
if (compressedBuffer != NULL)
{
delete [] compressedBuffer;
compressedBuffer = NULL;
}
}
unsigned char GECompression::bt1Table1[288] =
{
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8
};
unsigned char GECompression::bt1Table2[30] =
{
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
};
unsigned short GECompression::bt12Table1S[0x20] =
{
0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
0x000b, 0x000d, 0x000f, 0x0011, 0x0013, 0x0017, 0x001b, 0x001f,
0x0023, 0x002b, 0x0033, 0x003b, 0x0043, 0x0053, 0x0063, 0x0073,
0x0083, 0x00a3, 0x00c3, 0x00e3, 0x0102, 0x0000, 0x0000, 0x0000
};
unsigned short GECompression::bt12Table1B[0x20] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x00, 0x63, 0x63, 0x00
};
unsigned short GECompression::bt12Table2S[0x20] =
{
0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d,
0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1,
0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01,
0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001, 0x0000, 0x0000
};
unsigned short GECompression::bt12Table2B[0x20] =
{
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06,
0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a,
0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x00, 0x00
};
unsigned char GECompression::bt2Table1B[0x13] =
{
0x10,0x11,0x12,0x00, 0x08,0x07,0x09,0x06, 0x0a,0x05,0x0b,0x04, 0x0c,0x03,0x0d,0x02, 0x0e,0x01,0x0f
};
/*
void GECompression::SetPath(CString directory)
{
mainFolder = directory;
}
*/
void GECompression::SetGame(int replaceGame)
{
game = replaceGame;
}
/*void GECompression::SetInputBuffer(unsigned char* Buffer, int bufferSize)
{
if (inputBuffer == NULL)
{
inputBuffer = new unsigned char[bufferSize];
}
else
{
delete [] inputBuffer;
inputBuffer = new unsigned char[bufferSize];
}
for (int x = 0; x < bufferSize; x++)
{
inputBuffer[x] = Buffer[x];
}
inputBufferSize = bufferSize;
}*/
/*unsigned char* GECompression::OutputCompressed(int compressionType, int& fileSize)
{
unsigned char* outputBuffer = NULL;
fileSize = 0;
if (compressionType == 1)
outputBuffer = Compress(fileSize);
return outputBuffer;
}*/
void GECompression::SetCompressedBuffer(unsigned char* Buffer, int bufferSize)
{
if (compressedBuffer == NULL)
{
compressedBuffer = new unsigned char[bufferSize];
}
else
{
delete [] compressedBuffer;
compressedBuffer = new unsigned char[bufferSize];
}
for (int x = 0; x < bufferSize; x++)
{
compressedBuffer[x] = Buffer[x];
}
compressedBufferSize = bufferSize;
}
unsigned long GECompression::GetNBits(int nBits)
{
while (bitsRemain < nBits)
{
if (bytesIndex >= maxByteSize)
return 0; // bad decompression
if (bytesIndex >= compressedBufferSize)
return 0; // bad decompression
bitsCache = ((bitsCache) | (compressedBuffer[bytesIndex] << bitsRemain));
bitsRemain = bitsRemain + 8;
bytesIndex++;
}
unsigned long result = (bitsCache & ((1 << nBits)-1));
bitsCache = bitsCache >> nBits;
bitsRemain = bitsRemain - nBits;
return result;
}
unsigned long GECompression::GetNBitsAndPreserve(int nBits)
{
while (bitsRemain < nBits)
{
if (bytesIndex >= maxByteSize)
return 0; // bad decompression
if (bytesIndex >= compressedBufferSize)
return 0; // bad decompression
bitsCache = ((bitsCache) | (compressedBuffer[bytesIndex] << bitsRemain));
bitsRemain = bitsRemain + 8;
bytesIndex++;
}
unsigned long result = (bitsCache & ((1 << nBits)-1));
return result;
}
/*
BOOL GECompression::hiddenExec (PTSTR pCmdLine, CString currentDirectory)
{
STARTUPINFO si;
PROCESS_INFORMATION processInfo;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
ZeroMemory(&processInfo, sizeof(processInfo));
CreateProcess(0, pCmdLine, 0, 0, FALSE, 0, 0, currentDirectory, &si, &processInfo);
WaitForSingleObject(processInfo.hProcess, 20000);
DWORD exitCode;
if (GetExitCodeProcess(processInfo.hProcess, &exitCode))
{
if (exitCode == STILL_ACTIVE)
{
std::cout << "For some reason GZip Failed" << std::endl;
TerminateProcess(processInfo.hProcess, exitCode);
return false;
}
}
return true;
};
BOOL GECompression::IsFileExist(LPSTR lpszFilename)
{
DWORD dwAttr = GetFileAttributes(lpszFilename);
if (dwAttr == 0xffffffff)
return FALSE;
else
return TRUE;
}
bool GECompression::CompressGZipFile(CString inputFile, CString outputFile, bool byteFlipCompressed)
{
CString gzipFileName = (mainFolder + "gzip.exe");
char tempFileExistName[1000];
strcpy(tempFileExistName, (mainFolder + "gzip.exe"));
if (IsFileExist(tempFileExistName) == false)
{
std::cout << "gzip.exe not found!" << std::endl;
return false;
}
strcpy(tempFileExistName, inputFile);
if (IsFileExist(tempFileExistName))
{
FILE* tempInputFile = fopen(inputFile, "rb");
fseek(tempInputFile, 0, SEEK_END);
unsigned long size = ftell(tempInputFile);
unsigned char* tempBuffer;
tempBuffer = new unsigned char[size + 0x10];
for (int x = 0; x < (size + 0x10); x++)
tempBuffer[x] = 0;
fseek(tempInputFile, 0, SEEK_SET);
fread(tempBuffer, 1, size, tempInputFile);
FILE* tempOutputFile = fopen((mainFolder+"tempgh9.bin"), "wb");
if (tempOutputFile == 0)
{
fclose(tempInputFile);
delete [] tempBuffer;
std::cout << "Cannot Write Temporary File" << std::endl;
return false;
}
unsigned long compressedSize = size;
if ((game != BANJOTOOIE) && (game != CONKER))
{
if (((compressedSize % 0x10) != 0))
compressedSize = ((compressedSize - (compressedSize % 0x10)) + 0x10);
}
fwrite(tempBuffer, 1, compressedSize, tempOutputFile);
fclose(tempInputFile);
fclose(tempOutputFile);
delete [] tempBuffer;
::SetCurrentDirectory(mainFolder);
CString tempStr = ("gzip.exe -f -q -9 tempgh9.bin");
hiddenExec(_T(tempStr.GetBuffer()), (mainFolder));
CString outputGZippedName = (mainFolder+"TEMPGH9.BIZ");
strcpy(tempFileExistName, outputGZippedName);
if (!IsFileExist(tempFileExistName))
{
outputGZippedName = (mainFolder+"tempgh9.bin.gz");;
}
strcpy(tempFileExistName, outputGZippedName);
if (IsFileExist(tempFileExistName))
{
FILE* inputFileName = fopen(outputGZippedName, "rb");
int sizeNew = 0;
fseek(inputFileName, 0, SEEK_END);
sizeNew = ftell(inputFileName);
fseek(inputFileName, 0, SEEK_SET);
unsigned char* tempBufferNew;
tempBufferNew = new unsigned char[sizeNew];
fread(tempBufferNew, 1, sizeNew, inputFileName);
fclose(inputFileName);
DeleteFile((mainFolder+"TEMPGH9.BIZ"));
FILE* outputFileName = fopen(outputFile, "wb");
if (outputFileName == NULL)
{
delete [] tempBufferNew;
std::cout << "Error opening temp output file" << std::endl;
return false;
}
unsigned long start = 0x16;
if ((game == GOLDENEYE) || (game == KILLERINSTINCT))
{
start = start - 2;
tempBufferNew[start] = 0x11;
tempBufferNew[start+1] = 0x72;
}
else if (game == PD)
{
start = start - 5;
tempBufferNew[start] = 0x11;
tempBufferNew[start+1] = 0x73;
tempBufferNew[start+2] = ((size >> 16) & 0xFF);
tempBufferNew[start+3] = ((size >> 8) & 0xFF);
tempBufferNew[start+4] = ((size) & 0xFF);
}
else if (game == BANJOKAZOOIE)
{
start = start - 6;
tempBufferNew[start] = 0x11;
tempBufferNew[start+1] = 0x72;
tempBufferNew[start+2] = ((size >> 24) & 0xFF);
tempBufferNew[start+3] = ((size >> 16) & 0xFF);
tempBufferNew[start+4] = ((size >> 8) & 0xFF);
tempBufferNew[start+5] = ((size) & 0xFF);
}
else if ((game == DONKEYKONG64) || (game == BLASTCORPS))
{
start = start - 0xA;
tempBufferNew[start] = 0x1F;
tempBufferNew[start+1] = 0x8B;
tempBufferNew[start+2] = 0x08;
tempBufferNew[start+3] = 0x00;
tempBufferNew[start+4] = 0x00;
tempBufferNew[start+5] = 0x00;
tempBufferNew[start+6] = 0x00;
tempBufferNew[start+7] = 0x00;
tempBufferNew[start+8] = 0x02;
tempBufferNew[start+9] = 0x03;
}
else if (game == DONKEYKONG64KIOSK)
{
start = start - 0x12;
tempBufferNew[start] = 0x1F;
tempBufferNew[start+1] = 0x8B;
tempBufferNew[start+2] = 0x08;
tempBufferNew[start+3] = 0x08;
tempBufferNew[start+4] = 0x03;
tempBufferNew[start+5] = 0x45;
tempBufferNew[start+6] = 0x75;
tempBufferNew[start+7] = 0x37;
tempBufferNew[start+8] = 0x00;
tempBufferNew[start+9] = 0x03;
tempBufferNew[start+0xA] = 0x74;
tempBufferNew[start+0xB] = 0x6D;
tempBufferNew[start+0xC] = 0x70;
tempBufferNew[start+0xD] = 0x2E;
tempBufferNew[start+0xE] = 0x62;
tempBufferNew[start+0xF] = 0x69;
tempBufferNew[start+0x10] = 0x6E;
tempBufferNew[start+0x11] = 0x00;
}
else if (game == BANJOTOOIE)
{
start = start - 2;
// is this checksum, not sure?
float roundedSize = ceil((float)size / (float)0x10);
unsigned short roundedSizeShort = (unsigned short)roundedSize;
tempBufferNew[start] = ((roundedSizeShort >> 8) & 0xFF);
tempBufferNew[start+1] = ((roundedSizeShort) & 0xFF);
}
else if (game == CONKER)
{
start = start - 4;
tempBufferNew[start] = ((size >> 24) & 0xFF);
tempBufferNew[start+1] = ((size >> 16) & 0xFF);
tempBufferNew[start+2] = ((size >> 8) & 0xFF);
tempBufferNew[start+3] = ((size) & 0xFF);
}
else if (game == TOPGEARRALLY)
{
start = start - 0xE;
// compressed
tempBufferNew[start] = (((sizeNew-(start + 8)) >> 24) & 0xFF);
tempBufferNew[start+1] = (((sizeNew-(start + 8)) >> 16) & 0xFF);
tempBufferNew[start+2] = (((sizeNew-(start + 8)) >> 8) & 0xFF);
tempBufferNew[start+3] = (((sizeNew-(start + 8))) & 0xFF);
// uncompressed
tempBufferNew[start+4] = ((size >> 24) & 0xFF);
tempBufferNew[start+5] = ((size >> 16) & 0xFF);
tempBufferNew[start+6] = ((size >> 8) & 0xFF);
tempBufferNew[start+7] = ((size) & 0xFF);
// ?
tempBufferNew[start+8] = 0x0;
tempBufferNew[start+9] = 0x0;
tempBufferNew[start+0xA] = 0x0;
tempBufferNew[start+0xB] = 0x0;
tempBufferNew[start+0xC] = 0x0;
tempBufferNew[start+0xD] = 0x0;
}
else if (game == MILO)
{
start = start - 2;
tempBufferNew[start] = 0x78;
tempBufferNew[start+1] = 0x9C;
}
else if ((game == JFG) || (game == JFGKIOSK))
{
// unknown 5 bytes
start = start - 5;
tempBufferNew[start] = 0x04;
tempBufferNew[start+1] = 0x03;
tempBufferNew[start+2] = 0x00;
tempBufferNew[start+3] = 0x00;
tempBufferNew[start+4] = 0x09;
}
else if (game == DKR)
{
// unknown 5 bytes
start = start - 5;
tempBufferNew[start] = 0x04;
tempBufferNew[start+1] = 0x03;
tempBufferNew[start+2] = 0x00;
tempBufferNew[start+3] = 0x00;
tempBufferNew[start+4] = 0x09;
}
else if (game == MICKEYSPEEDWAY)
{
// unknown 5 bytes
start = start - 5;
tempBufferNew[start] = 0x04;
tempBufferNew[start+1] = 0x03;
tempBufferNew[start+2] = 0x00;
tempBufferNew[start+3] = 0x00;
tempBufferNew[start+4] = 0x09;
}
else if (game == STUNTRACER64)
{
start = start - 2;
tempBufferNew[start] = 0x78;
tempBufferNew[start+1] = 0xDA;
}
else if (game == RESIDENTEVIL2)
{
start = start - 2;
tempBufferNew[start] = 0x68;
tempBufferNew[start+1] = 0xDE;
}
else if (game == ZLB)
{
start = start - 0x12;
tempBufferNew[start] = 0x5A;
tempBufferNew[start] = 0x4C;
tempBufferNew[start] = 0x42;
tempBufferNew[start] = 0x00;
tempBufferNew[start] = 0x00;
tempBufferNew[start] = 0x00;
tempBufferNew[start] = 0x00;
tempBufferNew[start] = 0x01;
tempBufferNew[start] = 0x00;
tempBufferNew[start] = 0x00;
tempBufferNew[start] = 0x02;
tempBufferNew[start] = 0x60;
tempBufferNew[start] = 0x00;
tempBufferNew[start] = 0x00;
tempBufferNew[start] = 0x00;
tempBufferNew[start] = 0xC6;
tempBufferNew[start] = 0x58;
tempBufferNew[start] = 0x85;
}
if (byteFlipCompressed == true)
{
if ((sizeNew%2) == 1)
{
tempBufferNew[sizeNew-0x8] = 0;
sizeNew++;
}
for (int x = 0; x < sizeNew; x=x+2)
{
unsigned char tempSpot = tempBufferNew[x];
tempBufferNew[x] = tempBufferNew[x+1];
tempBufferNew[x+1] = tempSpot;
}
}
fwrite(&tempBufferNew[start], 1, (sizeNew-(start + 8)), outputFileName);
if (game != CONKER)
{
unsigned long fileSizeNew = (sizeNew-(start + 8));
if ((fileSizeNew % 0x8) != 0)
{
for (int x = 0; x < (0x8-(fileSizeNew % 0x8)); x++)
{
if ((game == BANJOKAZOOIE) || (game == BANJOTOOIE))
{
unsigned char tempZero = 0xAA;
fwrite(&tempZero, 1, 1, outputFileName);
}
else
{
unsigned char tempZero = 0;
fwrite(&tempZero, 1, 1, outputFileName);
}
}
}
}
delete [] tempBufferNew;
fflush(outputFileName);
fclose(outputFileName);
return true;
}
else
{
std::cout << "Error Compressing - GZip didn't spit out a file" << std::endl;
return false;
}
}
}
*/
unsigned char* GECompression::OutputDecompressedBuffer(int& fileSize, int& compressedSize)
{
compressedSize = 0;
if ((compressedBuffer == NULL) || (compressedBufferSize < 3))
return NULL;
if ((((compressedBuffer[0] << 8) | compressedBuffer[1]) != 0x1172) && (((compressedBuffer[0] << 8) | compressedBuffer[1]) != 0x1173) && (((compressedBuffer[0] << 8) | compressedBuffer[1]) != 0x68DE)&& (((compressedBuffer[0] << 8) | compressedBuffer[1]) != 0x789C) && (((compressedBuffer[0] << 8) | compressedBuffer[1]) != 0x78DA) && (((compressedBuffer[0] << 24) | (compressedBuffer[1]<<16) | (compressedBuffer[2]<<8) | (compressedBuffer[3])) != 0x1F8B0800) && (((compressedBuffer[0] << 24) | (compressedBuffer[1]<<16) | (compressedBuffer[2]<<8) | (compressedBuffer[3])) != 0x1F8B0808) && (game != BLASTCORPS) && (game != BANJOTOOIE) && (game != CONKER) && (game != TOPGEARRALLY) && (game != JFG) && (game != DKR) && (game != JFGKIOSK) && (game != MICKEYSPEEDWAY) && (game != ZLB))
{
//MessageBox(NULL, "Not 1172/1173/1F8B0800/1F8B0808 Compressed", "Error", NULL);
std::cout << "Error: Not 1172/1173/1F8B0800/1F8B0808 Compressed" << std::endl;
return NULL;
}
bitsCache = 0;
bitsRemain = 0;
if ((game == GOLDENEYE) || (game == KILLERINSTINCT) || (game == MILO) || (game == STUNTRACER64) || (game == RESIDENTEVIL2))
bytesIndex = 2;
else if (game == PD)
bytesIndex = 5;
else if (game == BANJOKAZOOIE)
bytesIndex = 6;
else if ((game == DONKEYKONG64) || (game == DONKEYKONG64KIOSK) || (game == BLASTCORPS))
bytesIndex = 0xA;
else if ((game == BANJOTOOIE))
bytesIndex = 0x2;
else if (game == CONKER)
bytesIndex = 4;
else if (game == TOPGEARRALLY)
bytesIndex = 0xE;
else if ((game == JFG) || (game == JFGKIOSK) || (game == DKR) || (game == MICKEYSPEEDWAY))
bytesIndex = 0x5;
else if (game == ZLB)
bytesIndex = 0x12;
if (((game == DONKEYKONG64) || (game == DONKEYKONG64KIOSK) || (game == BLASTCORPS)) && (((compressedBuffer[0] << 24) | (compressedBuffer[1]<<16) | (compressedBuffer[2]<<8) | (compressedBuffer[3])) == 0x1F8B0808))
{
while (compressedBuffer[bytesIndex] != 0)
bytesIndex++;
bytesIndex++;
}
unpackTableIndex = 0;
for (int x = 0; x < 0xFFFF; x++)
{
unpackTable[x].bits = 0;
unpackTable[x].flags = 0;
unpackTable[x].nextIndex = 0;
unpackTable[x].wordValue = 0;
}
unsigned char* returnBuffer;
returnBuffer = new unsigned char[maxByteSize];
bool done = false;
unsigned char compressionType;
fileSize = 0;
iterationCounter = 0;
do
{
if (iterationCounter > 268435455)
{
fileSize = 0;
if (returnBuffer != NULL)
delete [] returnBuffer;
return NULL;
}
iterationCounter++;
done = GetNBits(1);
if (bytesIndex >= maxByteSize)
{
fileSize = 0;
if (returnBuffer != NULL)
delete [] returnBuffer;
return NULL;
}
compressionType = GetNBits(2);
if (compressionType == 0)
{
if (!UncompressType0(returnBuffer, fileSize))
{
fileSize = 0;
if (returnBuffer != NULL)
delete [] returnBuffer;
return NULL;
}
}
else if (compressionType == 1)
{
if (!UncompressType1(returnBuffer, fileSize))
{
fileSize = 0;
if (returnBuffer != NULL)
delete [] returnBuffer;
return NULL;
}
}
else if (compressionType == 2)
{
if (!UncompressType2(returnBuffer, fileSize))
{
fileSize = 0;
if (returnBuffer != NULL)
delete [] returnBuffer;
return NULL;
}
}
else
{
fileSize = 0;
if (returnBuffer != NULL)
delete [] returnBuffer;
return NULL;
}
} while (done != 1);
compressedSize = bytesIndex;
return returnBuffer;
}
bool GECompression::UncompressType0(unsigned char* returnBuffer, int& fileSize)
{
// discard bits
unsigned long discardBits = bitsRemain & 0x7;
GetNBits(discardBits); // discard begins
unsigned short copyLen = GetNBits(16);
GetNBits(16); // discarded
for (int x = 0; x < copyLen; x++)
{
if (fileSize >= maxByteSize)
{
fileSize = 0;
return false;
}
returnBuffer[fileSize] = GetNBits(8);
fileSize++;
if (iterationCounter > 268435455)
{
fileSize = 0;
return false;
}
iterationCounter++;
}
return true;
}
bool GECompression::UncompressType1(unsigned char* returnBuffer, int& fileSize)
{
bool returnValue1, returnValue2;
int numBits1, numBits2;
int startIndex1, startIndex2;
CreateGlobalDecompressionTable(0, 0x101, 0, 0, 7, returnValue1, numBits1, startIndex1);
CreateGlobalDecompressionTable(1, 0, 1, 1, 5, returnValue2, numBits2, startIndex2);
return DecompressBasedOnTable(startIndex1, startIndex2, numBits1, numBits2, returnBuffer, fileSize);
}
bool GECompression::UncompressType2(unsigned char* returnBuffer, int& fileSize)
{
try
{
for (int x = 0; x < 0x13; x++)
{
variableTable[x] = 0;
}
tableSize = (GetNBits(5)+0x101);
fiveBits = GetNBits(5)+0x1;
unsigned char fourBits = GetNBits(4)+0x4;
for (int index = 0; index < fourBits; index++)
{
unsigned char threeBits = GetNBits(3);
variableTable[bt2Table1B[index]] = threeBits;
}
bool returnValue1;
int numBits1;
int startIndex1;
CreateGlobalDecompressionTable(2, 0x13, 2, 2, 7, returnValue1, numBits1, startIndex1);
if (wordTable != NULL)
{
delete [] wordTable;
wordTable = NULL;
}
wordTable = new unsigned long[0xFFFF];
int wordTableSpot = 0;
unsigned long lastWritten = 0;
while (wordTableSpot < (tableSize + fiveBits))
{
if (iterationCounter > 268435455)
{
fileSize = 0;
return false;
}
iterationCounter++;
unsigned long tableIndex = GetNBitsAndPreserve(numBits1);
if ((startIndex1 + tableIndex) > 0xFFFF)
{
fileSize = 0;
return false;
}
int numBits2 = unpackTable[startIndex1 + tableIndex].bits;
if (bytesIndex >= maxByteSize)
{
fileSize = 0;
return false;
}
GetNBits(numBits2);
unsigned long wordValue = unpackTable[startIndex1 + tableIndex].wordValue;
if (unpackTable[startIndex1 + tableIndex].nextIndex == 0)
{
if (wordValue < 0x10)
{
lastWritten = wordValue;
wordTable[wordTableSpot] = wordValue;
wordTableSpot++;
}
else if (wordValue == 0x10)
{
int repeatLen = (GetNBits(2) + 3);
for (int index = 0; index < repeatLen; index++)
{
wordTable[wordTableSpot] = lastWritten;
wordTableSpot++;
}
}
else if (wordValue == 0x11)
{
int repeatLen = (GetNBits(3) + 3);
for (int index = 0; index < repeatLen; index++)
{
wordTable[wordTableSpot] = 0;
wordTableSpot++;
}
}
else
{
int repeatLen = (GetNBits(7) + 0xB);
for (int index = 0; index < repeatLen; index++)
{
wordTable[wordTableSpot] = 0;
wordTableSpot++;
}
}
}
}
bool returnValue2, returnValue3;
int numBits2, numBits3;
int startIndex2, startIndex3;
CreateGlobalDecompressionTable(3, 0x101, 0, 0, 9, returnValue2, numBits2, startIndex2);
CreateGlobalDecompressionTable(4, 0, 1, 1, 6, returnValue3, numBits3, startIndex3);
DecompressBasedOnTable(startIndex2, startIndex3, numBits2, numBits3, returnBuffer, fileSize);
if (wordTable != NULL)
{
delete [] wordTable;
wordTable = NULL;
}
} catch (...)
{
fileSize = 0;
return false;
}
return true;
}
void GECompression::CreateGlobalDecompressionTable(int bit1TableChoice, int size2, int bit12STableSChoice, int bit12BTableChoice, int numBits, bool& returnValue, int& numReturnBits, int& returnStartIndex)
{
//if (bit1TableChoice == 0) bt1Table1 else bt1Table2
//if (bit12STableSChoice == 0) bt12Table1S else bt12Table2S
//if (bit12BTableChoice == 0) bt12Table1B else bt12Table2B
CString temp; // temp var del later
tableEntry localTableEntry;
localTableEntry.bits = 0;
localTableEntry.flags = 0;
localTableEntry.nextIndex = 0;
localTableEntry.wordValue = 0;
int table1Size = 0;
int returnIndex = -1;
unsigned long seventeenints1[17];
for (int x = 0; x < 17; x++)
seventeenints1[x] = 0;
if (bit1TableChoice == TABLE1)
{
table1Size = 288;
for (int x = 0; x < 288; x++)
{
seventeenints1[bt1Table1[x]]++;
}
}
else if (bit1TableChoice == TABLE2)
{
table1Size = 30;
for (int x = 0; x < 30; x++)
{
seventeenints1[bt1Table2[x]]++;
}
}
else if (bit1TableChoice == VARIABLETABLE)
{
table1Size = 0x13;
for (int x = 0; x < 0x13; x++)
{
seventeenints1[variableTable[x]]++;
}
}
else if (bit1TableChoice == WORDTABLEBEGIN)
{
table1Size = tableSize;
for (int x = 0; x < table1Size; x++)
{
seventeenints1[wordTable[x]]++;
}
}
else if (bit1TableChoice == WORDTABLEEND)
{
table1Size = ((tableSize + fiveBits) - tableSize);
for (int x = 0; x < table1Size; x++)
{
seventeenints1[wordTable[tableSize + x]]++;
}
}
int firstBit = 1;
while (seventeenints1[firstBit] == 0)
firstBit++;
int lastBit = 16;
while (seventeenints1[lastBit] == 0)
lastBit--;
if (numBits < firstBit)
numBits = firstBit;
if (numBits > lastBit)
numBits = lastBit;
unsigned long v1temp = (1<<firstBit);
if (firstBit != lastBit)
{
for (int bitNum = firstBit; bitNum < lastBit; bitNum++)
{
v1temp = ((v1temp - seventeenints1[bitNum])*2);
}
}
int oldLastBitCount = seventeenints1[lastBit];
seventeenints1[lastBit] = v1temp;
v1temp = v1temp - oldLastBitCount;
unsigned long seventeenints2[17];
for (int x = 0; x < 17; x++)
seventeenints2[x] = 0;
int accumulator = 0;
for (int index = 1; index < lastBit; index++)
{
accumulator = accumulator + seventeenints1[index];
seventeenints2[index+1] = accumulator;
}
unsigned long* moreWords;
moreWords = new unsigned long[table1Size];
int moreWordsIndex = 0;
int index = 0;
for (int x = 0; x < table1Size; x++)
{
moreWords[x] = 0;
}
for (int x = 0; x < table1Size; x++)
{
if (bit1TableChoice == TABLE1)
{
if ((bt1Table1[x]) != 0)
{
moreWords[seventeenints2[bt1Table1[x]]] = index;
seventeenints2[bt1Table1[x]]++;
}
}
else if (bit1TableChoice == TABLE2)
{
if ((bt1Table2[x]) != 0)
{
moreWords[seventeenints2[bt1Table2[x]]] = index;
seventeenints2[bt1Table2[x]]++;
}
}
else if (bit1TableChoice == VARIABLETABLE)
{
if ((variableTable[x]) != 0)
{
moreWords[seventeenints2[variableTable[x]]] = index;
seventeenints2[variableTable[x]]++;
}
}
else if (bit1TableChoice == WORDTABLEBEGIN)
{
if ((wordTable[x]) != 0)
{
moreWords[seventeenints2[wordTable[x]]] = index;
seventeenints2[wordTable[x]]++;
}
}
else if (bit1TableChoice == WORDTABLEEND)
{
if ((wordTable[tableSize + x]) != 0)
{
moreWords[seventeenints2[wordTable[tableSize + x]]] = index;
seventeenints2[wordTable[tableSize + x]]++;
}
}
index++;
}
int stemp2_v1 = -numBits;
int blockNum = -1;
int bitPattern = 0;
int unpackTableStarts[0x20000];
int unpackTableStartsIndex = -1;
unsigned long temp_a3 = 0;
int thisTableStart = 0;
for (int bitNum = firstBit; bitNum < (lastBit+1); bitNum++)
{
int iterationsLeft = seventeenints1[bitNum];
unsigned long lv34 = (1<<(bitNum-1));
int moreWordsIndex2 = table1Size;
while (iterationsLeft)
{
if (iterationsLeft < 0)
break;
stemp2_v1 = stemp2_v1 + numBits;
while (stemp2_v1 < bitNum)
{
blockNum++;
unsigned long temp_t0 = 0;
if (numBits < (lastBit-stemp2_v1))
temp_t0=numBits;
else
temp_t0 = lastBit-stemp2_v1;
temp_a3 = bitNum - stemp2_v1;
if (iterationsLeft < (1<<temp_a3))
{
unsigned long another_var_v1= ((1 << temp_a3) - iterationsLeft);
temp_a3++;
index = bitNum + 1;
while (temp_a3 < temp_t0)
{
if (seventeenints1[index] < (another_var_v1*2))
{
temp_a3++;
another_var_v1 = another_var_v1*2 - seventeenints1[index];
}
index++;
}
}
if (returnIndex==-1)
returnIndex=unpackTableIndex + 1;
unpackTableStartsIndex++;
unpackTableStarts[unpackTableStartsIndex] = (unpackTableIndex+1);
thisTableStart = unpackTableIndex + 1;
if (blockNum != 0)
{
seventeenints2[blockNum] = bitPattern;
localTableEntry.bits = numBits;
localTableEntry.flags = temp_a3 + 0x10;
localTableEntry.nextIndex= unpackTableIndex + 1;
localTableEntry.wordValue = -1;
unpackTable[(bitPattern>>(stemp2_v1-numBits))+unpackTableStarts[blockNum-1]].bits = localTableEntry.bits;
unpackTable[(bitPattern>>(stemp2_v1-numBits))+unpackTableStarts[blockNum-1]].flags = localTableEntry.flags;
unpackTable[(bitPattern>>(stemp2_v1-numBits))+unpackTableStarts[blockNum-1]].wordValue = localTableEntry.wordValue;
unpackTable[(bitPattern>>(stemp2_v1-numBits))+unpackTableStarts[blockNum-1]].nextIndex = localTableEntry.nextIndex;
}
unpackTableIndex=unpackTableIndex + ((1<<temp_a3)+1);
stemp2_v1+=numBits;
}
stemp2_v1 = stemp2_v1 - numBits;
localTableEntry.bits = bitNum - stemp2_v1;
localTableEntry.nextIndex = 0;
if (moreWordsIndex >= moreWordsIndex2)
localTableEntry.flags = 0x63;
else
{
unsigned long tempWord = moreWords[moreWordsIndex];
if (tempWord<size2)
{
if (tempWord >= 0x100)
localTableEntry.flags = 0xf;
else
localTableEntry.flags = 0x10;
localTableEntry.wordValue = tempWord;
}
else
{
if (bit12STableSChoice == TABLE1)
{
localTableEntry.flags = bt12Table1B[moreWords[moreWordsIndex]-size2];
localTableEntry.wordValue = bt12Table1S[moreWords[moreWordsIndex]-size2];
}
else if (bit12STableSChoice == TABLE2)
{
localTableEntry.flags = bt12Table2B[moreWords[moreWordsIndex]-size2];
localTableEntry.wordValue = bt12Table2S[moreWords[moreWordsIndex]-size2];
}
else if (bit12STableSChoice == VARIABLETABLE)
{
// shouldn't happen
}
}
moreWordsIndex++;
}
unsigned long nu_accum_a3 = (bitPattern >> stemp2_v1);
unsigned long stride_v0 = (1<<(bitNum - stemp2_v1));
/*if (thisTableStart==744)
{
if thisTableStart+nu_accum_a3==758
{
if stride_v0==16:
{
debugIt=1
}
}
}*/
while ((1<<temp_a3) > nu_accum_a3)
{
if ((thisTableStart+nu_accum_a3) > 0xFFFF)
{
delete [] moreWords;
return;
}
unpackTable[thisTableStart+nu_accum_a3].bits = localTableEntry.bits;
unpackTable[thisTableStart+nu_accum_a3].flags = localTableEntry.flags;
unpackTable[thisTableStart+nu_accum_a3].wordValue = localTableEntry.wordValue;
unpackTable[thisTableStart+nu_accum_a3].nextIndex = localTableEntry.nextIndex;
nu_accum_a3 = nu_accum_a3 + stride_v0;
}
unsigned long tempLv=lv34;
while (bitPattern & tempLv)
{
bitPattern = bitPattern ^ tempLv;
tempLv = tempLv >> 1;
}
bitPattern = bitPattern ^ tempLv;
while((bitPattern & ((1 << stemp2_v1)-1)) != seventeenints2[blockNum])
{
blockNum = blockNum- 1;
stemp2_v1=0;
}
iterationsLeft = iterationsLeft - 1;
}
}
delete [] moreWords;
if (v1temp > 0)
{
returnValue = (0<(lastBit^1));
numReturnBits = numBits;
returnStartIndex = returnIndex;
}
else
{
returnValue = 0;
numReturnBits = numBits;
returnStartIndex = returnIndex;
}
}
bool GECompression::DecompressBasedOnTable(int startIndex1, int startIndex2, int bitLen1, int bitLen2, unsigned char* returnBuffer, int& fileSize)
{
unsigned long index = 0;
bool exitFlag = 1;
try
{
while (exitFlag)
{
if (iterationCounter > 268435455)
{
fileSize = 0;
return false;
}
iterationCounter++;
if (bytesIndex >= maxByteSize)
{
fileSize = 0;
return false;
}
index = GetNBitsAndPreserve(bitLen1);
if ((startIndex1 + index) > 0xFFFF)
{
fileSize = 0;
return false;
}
tableEntry entry = unpackTable[startIndex1 + index];
while (entry.flags > 0x10)
{
if (iterationCounter > 268435455)
{
fileSize = 0;
return false;
}
iterationCounter++;
if (bytesIndex >= maxByteSize)
{
fileSize = 0;
return false;
}
GetNBits(entry.bits); // discard
index = GetNBitsAndPreserve(entry.flags-0x10);
if ((entry.nextIndex+index) > 0xFFFF)
{
fileSize = 0;
return false;
}
entry = unpackTable[entry.nextIndex+index];
}
if (bytesIndex >= maxByteSize)
{
fileSize = 0;
return false;
}
GetNBits(entry.bits); // discard
if (entry.flags==0x10)
{
if (fileSize >= maxByteSize)
{
fileSize = 0;
return false;
}
returnBuffer[fileSize] = entry.wordValue;
fileSize++;
}
else if (entry.flags < 0xf)
{
unsigned long copyLen = entry.wordValue + GetNBits(entry.flags);
unsigned long index2 = GetNBitsAndPreserve(bitLen2);
if ((startIndex2+index2) > 0xFFFF)
{
fileSize = 0;
return false;
}
tableEntry entry2 = unpackTable[startIndex2+index2];
while (entry2.flags>0x10)
{
if (iterationCounter > 268435455)
{
fileSize = 0;
return false;
}
iterationCounter++;
if (bytesIndex >= maxByteSize)
{
fileSize = 0;
return false;
}
GetNBits(entry2.bits); // discard
index2 = GetNBitsAndPreserve(entry2.flags-0x10);
if ((entry2.nextIndex+index2) > 0xFFFF)
{
fileSize = 0;
return false;
}
entry2 = unpackTable[entry2.nextIndex+index2];
}
if (bytesIndex >= maxByteSize)
{
fileSize = 0;
return false;
}
GetNBits(entry2.bits); // discard
unsigned long endOffset1 = entry2.wordValue;
unsigned long endOffset2 = GetNBits(entry2.flags);
unsigned long start = fileSize-endOffset1-endOffset2;
unsigned long end = start + copyLen;
for (int x = start; x < end; x++)
{
if ((((signed long) start) < 0) || ((((signed long) end) < 0)) || ((start > maxByteSize)) || ((end > maxByteSize)))
{
fileSize = 0;
return false;
}
returnBuffer[fileSize] = returnBuffer[x];
fileSize++;
}
}
else
exitFlag = 0;
}
} catch (...)
{
return false;
}
return true;
}