You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

77 lines
1.8 KiB

/**
* @file encrypt.cpp
*
* Implementation of functions for compression and decompressing MPQ data.
*/
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <mpqfs/mpqfs.h>
#include "encrypt.h"
namespace devilution {
uint32_t PkwareCompress(std::byte *srcData, uint32_t size)
{
// Stack buffer covers typical network messages and MPQ sectors (≤ 4096).
// Falls back to heap for larger payloads.
constexpr size_t StackBufSize = 4096 * 2 + 64;
uint8_t stackBuf[StackBufSize];
size_t dstCap = static_cast<size_t>(size) * 2 + 64;
uint8_t *dst;
std::unique_ptr<uint8_t[]> heapBuf;
if (dstCap <= StackBufSize) {
dst = stackBuf;
} else {
heapBuf = std::make_unique<uint8_t[]>(dstCap);
dst = heapBuf.get();
}
size_t dstSize = dstCap;
int rc = mpqfs_pk_implode(
reinterpret_cast<const uint8_t *>(srcData), size,
dst, &dstSize, /*dict_bits=*/6);
if (rc == 0 && dstSize < size) {
std::memcpy(srcData, dst, dstSize);
return static_cast<uint32_t>(dstSize);
}
// Compression didn't help — return original size.
return size;
}
uint32_t PkwareDecompress(std::byte *inBuff, uint32_t recvSize, size_t maxBytes)
{
// Stack buffer covers most decompressed network payloads.
// Falls back to heap for larger buffers.
constexpr size_t StackBufSize = 8192;
uint8_t stackBuf[StackBufSize];
uint8_t *out;
std::unique_ptr<uint8_t[]> heapBuf;
if (maxBytes <= StackBufSize) {
out = stackBuf;
} else {
heapBuf = std::make_unique<uint8_t[]>(maxBytes);
out = heapBuf.get();
}
size_t outSize = maxBytes;
int rc = mpqfs_pk_explode(
reinterpret_cast<const uint8_t *>(inBuff), recvSize,
out, &outSize);
if (rc != 0)
return 0;
std::memcpy(inBuff, out, outSize);
return static_cast<uint32_t>(outSize);
}
} // namespace devilution