|
|
|
|
@ -3,6 +3,8 @@
|
|
|
|
|
* |
|
|
|
|
* Implementation of functions for compression and decompressing MPQ data. |
|
|
|
|
*/ |
|
|
|
|
#include <memory> |
|
|
|
|
|
|
|
|
|
#include "encrypt.h" |
|
|
|
|
|
|
|
|
|
#include "engine.h" |
|
|
|
|
@ -10,15 +12,13 @@
|
|
|
|
|
|
|
|
|
|
namespace devilution { |
|
|
|
|
|
|
|
|
|
DWORD hashtable[5][256]; |
|
|
|
|
static uint32_t hashtable[5][256]; |
|
|
|
|
|
|
|
|
|
void Decrypt(DWORD *castBlock, DWORD size, DWORD key) |
|
|
|
|
void Decrypt(uint32_t *castBlock, uint32_t size, uint32_t key) |
|
|
|
|
{ |
|
|
|
|
DWORD seed, i; |
|
|
|
|
|
|
|
|
|
seed = 0xEEEEEEEE; |
|
|
|
|
for (i = 0; i < (size >> 2); i++) { |
|
|
|
|
DWORD t = SDL_SwapLE32(*castBlock); |
|
|
|
|
uint32_t seed = 0xEEEEEEEE; |
|
|
|
|
for (uint32_t i = 0; i < (size >> 2); i++) { |
|
|
|
|
uint32_t t = SDL_SwapLE32(*castBlock); |
|
|
|
|
seed += hashtable[4][(key & 0xFF)]; |
|
|
|
|
t ^= seed + key; |
|
|
|
|
*castBlock = t; |
|
|
|
|
@ -28,7 +28,7 @@ void Decrypt(DWORD *castBlock, DWORD size, DWORD key)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Encrypt(DWORD *castBlock, DWORD size, DWORD key) |
|
|
|
|
void Encrypt(uint32_t *castBlock, uint32_t size, uint32_t key) |
|
|
|
|
{ |
|
|
|
|
uint32_t seed = 0xEEEEEEEE; |
|
|
|
|
for (unsigned i = 0; i < (size >> 2); i++) { |
|
|
|
|
@ -58,15 +58,12 @@ uint32_t Hash(const char *s, int type)
|
|
|
|
|
|
|
|
|
|
void InitHash() |
|
|
|
|
{ |
|
|
|
|
DWORD seed, ch; |
|
|
|
|
int i, j; |
|
|
|
|
uint32_t seed = 0x00100001; |
|
|
|
|
|
|
|
|
|
seed = 0x00100001; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++) { |
|
|
|
|
for (j = 0; j < 5; j++) { |
|
|
|
|
for (int i = 0; i < 256; i++) { |
|
|
|
|
for (int j = 0; j < 5; j++) { |
|
|
|
|
seed = (125 * seed + 3) % 0x2AAAAB; |
|
|
|
|
ch = (seed & 0xFFFF); |
|
|
|
|
uint32_t ch = (seed & 0xFFFF); |
|
|
|
|
seed = (125 * seed + 3) % 0x2AAAAB; |
|
|
|
|
hashtable[j][i] = ch << 16 | (seed & 0xFFFF); |
|
|
|
|
} |
|
|
|
|
@ -75,11 +72,9 @@ void InitHash()
|
|
|
|
|
|
|
|
|
|
static unsigned int PkwareBufferRead(char *buf, unsigned int *size, void *param) |
|
|
|
|
{ |
|
|
|
|
TDataInfo *pInfo; |
|
|
|
|
DWORD sSize; |
|
|
|
|
|
|
|
|
|
pInfo = (TDataInfo *)param; |
|
|
|
|
TDataInfo *pInfo = (TDataInfo *)param; |
|
|
|
|
|
|
|
|
|
uint32_t sSize; |
|
|
|
|
if (*size >= pInfo->size - pInfo->srcOffset) { |
|
|
|
|
sSize = pInfo->size - pInfo->srcOffset; |
|
|
|
|
} else { |
|
|
|
|
@ -94,69 +89,56 @@ static unsigned int PkwareBufferRead(char *buf, unsigned int *size, void *param)
|
|
|
|
|
|
|
|
|
|
static void PkwareBufferWrite(char *buf, unsigned int *size, void *param) |
|
|
|
|
{ |
|
|
|
|
TDataInfo *pInfo; |
|
|
|
|
|
|
|
|
|
pInfo = (TDataInfo *)param; |
|
|
|
|
TDataInfo *pInfo = (TDataInfo *)param; |
|
|
|
|
|
|
|
|
|
memcpy(pInfo->destData + pInfo->destOffset, buf, *size); |
|
|
|
|
pInfo->destOffset += *size; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DWORD PkwareCompress(BYTE *srcData, DWORD size) |
|
|
|
|
uint32_t PkwareCompress(uint8_t *srcData, uint32_t size) |
|
|
|
|
{ |
|
|
|
|
BYTE *destData; |
|
|
|
|
char *ptr; |
|
|
|
|
unsigned int destSize, type, dsize; |
|
|
|
|
TDataInfo param; |
|
|
|
|
|
|
|
|
|
ptr = (char *)DiabloAllocPtr(CMP_BUFFER_SIZE); |
|
|
|
|
auto ptr = std::make_unique<char[]>(CMP_BUFFER_SIZE); |
|
|
|
|
|
|
|
|
|
destSize = 2 * size; |
|
|
|
|
unsigned destSize = 2 * size; |
|
|
|
|
if (destSize < 2 * 4096) |
|
|
|
|
destSize = 2 * 4096; |
|
|
|
|
|
|
|
|
|
destData = (BYTE *)DiabloAllocPtr(destSize); |
|
|
|
|
auto destData = std::make_unique<uint8_t[]>(destSize); |
|
|
|
|
|
|
|
|
|
TDataInfo param; |
|
|
|
|
param.srcData = srcData; |
|
|
|
|
param.srcOffset = 0; |
|
|
|
|
param.destData = destData; |
|
|
|
|
param.destData = destData.get(); |
|
|
|
|
param.destOffset = 0; |
|
|
|
|
param.size = size; |
|
|
|
|
|
|
|
|
|
type = 0; |
|
|
|
|
dsize = 4096; |
|
|
|
|
implode(PkwareBufferRead, PkwareBufferWrite, ptr, ¶m, &type, &dsize); |
|
|
|
|
unsigned type = 0; |
|
|
|
|
unsigned dsize = 4096; |
|
|
|
|
implode(PkwareBufferRead, PkwareBufferWrite, ptr.get(), ¶m, &type, &dsize); |
|
|
|
|
|
|
|
|
|
if (param.destOffset < size) { |
|
|
|
|
memcpy(srcData, destData, param.destOffset); |
|
|
|
|
memcpy(srcData, destData.get(), param.destOffset); |
|
|
|
|
size = param.destOffset; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
mem_free_dbg(ptr); |
|
|
|
|
mem_free_dbg(destData); |
|
|
|
|
|
|
|
|
|
return size; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PkwareDecompress(BYTE *pbInBuff, int recv_size, int dwMaxBytes) |
|
|
|
|
void PkwareDecompress(uint8_t *inBuff, int recvSize, int maxBytes) |
|
|
|
|
{ |
|
|
|
|
char *ptr; |
|
|
|
|
BYTE *pbOutBuff; |
|
|
|
|
TDataInfo info; |
|
|
|
|
|
|
|
|
|
ptr = (char *)DiabloAllocPtr(CMP_BUFFER_SIZE); |
|
|
|
|
pbOutBuff = DiabloAllocPtr(dwMaxBytes); |
|
|
|
|
auto ptr = std::make_unique<char[]>(CMP_BUFFER_SIZE); |
|
|
|
|
auto outBuff = std::make_unique<uint8_t[]>(maxBytes); |
|
|
|
|
|
|
|
|
|
info.srcData = pbInBuff; |
|
|
|
|
info.srcData = inBuff; |
|
|
|
|
info.srcOffset = 0; |
|
|
|
|
info.destData = pbOutBuff; |
|
|
|
|
info.destData = outBuff.get(); |
|
|
|
|
info.destOffset = 0; |
|
|
|
|
info.size = recv_size; |
|
|
|
|
info.size = recvSize; |
|
|
|
|
|
|
|
|
|
explode(PkwareBufferRead, PkwareBufferWrite, ptr, &info); |
|
|
|
|
memcpy(pbInBuff, pbOutBuff, info.destOffset); |
|
|
|
|
mem_free_dbg(ptr); |
|
|
|
|
mem_free_dbg(pbOutBuff); |
|
|
|
|
explode(PkwareBufferRead, PkwareBufferWrite, ptr.get(), &info); |
|
|
|
|
memcpy(inBuff, outBuff.get(), info.destOffset); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace devilution
|
|
|
|
|
|