aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/compression.cpp
diff options
context:
space:
mode:
authorqwasdrizzel <145519042+qwasdrizzel@users.noreply.github.com>2026-03-16 21:44:26 -0500
committerGitHub <noreply@github.com>2026-03-16 21:44:26 -0500
commitce739f6045ec72127491286ea3f3f21e537c1b55 (patch)
treef33bd42a47c1b4a7b2153a7fb77127ee3b407db9 /Minecraft.World/compression.cpp
parent255a18fe8e9b57377975f82e2b227afe2a12eda0 (diff)
parent5a59f5d146b43811dde6a5a0245ee9875d7b5cd1 (diff)
Merge branch 'smartcmd:main' into main
Diffstat (limited to 'Minecraft.World/compression.cpp')
-rw-r--r--Minecraft.World/compression.cpp197
1 files changed, 143 insertions, 54 deletions
diff --git a/Minecraft.World/compression.cpp b/Minecraft.World/compression.cpp
index 99c5228a..4122922b 100644
--- a/Minecraft.World/compression.cpp
+++ b/Minecraft.World/compression.cpp
@@ -12,7 +12,7 @@
DWORD Compression::tlsIdx = 0;
-Compression::ThreadStorage *Compression::tlsDefault = NULL;
+Compression::ThreadStorage *Compression::tlsDefault = nullptr;
Compression::ThreadStorage::ThreadStorage()
{
@@ -27,7 +27,7 @@ Compression::ThreadStorage::~ThreadStorage()
void Compression::CreateNewThreadStorage()
{
ThreadStorage *tls = new ThreadStorage();
- if(tlsDefault == NULL )
+ if(tlsDefault == nullptr )
{
tlsIdx = TlsAlloc();
tlsDefault = tls;
@@ -42,7 +42,7 @@ void Compression::UseDefaultThreadStorage()
void Compression::ReleaseThreadStorage()
{
- ThreadStorage *tls = (ThreadStorage *)TlsGetValue(tlsIdx);
+ const ThreadStorage *tls = static_cast<ThreadStorage *>(TlsGetValue(tlsIdx));
if( tls == tlsDefault ) return;
delete tls;
@@ -50,7 +50,7 @@ void Compression::ReleaseThreadStorage()
Compression *Compression::getCompression()
{
- ThreadStorage *tls = (ThreadStorage *)TlsGetValue(tlsIdx);
+ const ThreadStorage *tls = static_cast<ThreadStorage *>(TlsGetValue(tlsIdx));
return tls->compression;
}
@@ -59,9 +59,27 @@ HRESULT Compression::CompressLZXRLE(void *pDestination, unsigned int *pDestSize,
EnterCriticalSection(&rleCompressLock);
//static unsigned char rleBuf[1024*100];
- unsigned char *pucIn = (unsigned char *)pSource;
- unsigned char *pucEnd = pucIn + SrcSize;
- unsigned char *pucOut = (unsigned char *)rleCompressBuf;
+ // RLE can expand data (each 0xFF byte becomes 2 bytes), so worst case is 2*SrcSize.
+ // Use the static buffer when it fits, dynamically allocate otherwise.
+ static const unsigned int staticCompressSize = 1024*100;
+ unsigned int rleBufSize = SrcSize * 2;
+ unsigned char *dynamicRleBuf = nullptr;
+ unsigned char *rleBuf;
+
+ if(rleBufSize <= staticCompressSize)
+ {
+ rleBuf = rleCompressBuf;
+ rleBufSize = staticCompressSize;
+ }
+ else
+ {
+ dynamicRleBuf = new unsigned char[rleBufSize];
+ rleBuf = dynamicRleBuf;
+ }
+
+ const unsigned char *pucIn = static_cast<unsigned char*>(pSource);
+ const unsigned char *pucEnd = pucIn + SrcSize;
+ unsigned char *pucOut = rleBuf;
// Compress with RLE first:
// 0 - 254 - encodes a single byte
@@ -70,7 +88,7 @@ HRESULT Compression::CompressLZXRLE(void *pDestination, unsigned int *pDestSize,
PIXBeginNamedEvent(0,"RLE compression");
do
{
- unsigned char thisOne = *pucIn++;
+ const unsigned char thisOne = *pucIn++;
unsigned int count = 1;
while( ( pucIn != pucEnd ) && ( *pucIn == thisOne ) && ( count < 256 ) )
@@ -101,12 +119,15 @@ HRESULT Compression::CompressLZXRLE(void *pDestination, unsigned int *pDestSize,
*pucOut++ = thisOne;
}
} while (pucIn != pucEnd);
- unsigned int rleSize = (unsigned int)(pucOut - rleCompressBuf);
+ const unsigned int rleSize = static_cast<unsigned int>(pucOut - rleBuf);
PIXEndNamedEvent();
PIXBeginNamedEvent(0,"Secondary compression");
- Compress(pDestination, pDestSize, rleCompressBuf, rleSize);
+ Compress(pDestination, pDestSize, rleBuf, rleSize);
PIXEndNamedEvent();
+
+ if(dynamicRleBuf != nullptr) delete [] dynamicRleBuf;
+
LeaveCriticalSection(&rleCompressLock);
// printf("Compressed from %d to %d to %d\n",SrcSize,rleSize,*pDestSize);
@@ -118,9 +139,26 @@ HRESULT Compression::CompressRLE(void *pDestination, unsigned int *pDestSize, vo
EnterCriticalSection(&rleCompressLock);
//static unsigned char rleBuf[1024*100];
- unsigned char *pucIn = (unsigned char *)pSource;
- unsigned char *pucEnd = pucIn + SrcSize;
- unsigned char *pucOut = (unsigned char *)rleCompressBuf;
+ // RLE can expand data (each 0xFF byte becomes 2 bytes), so worst case is 2*SrcSize.
+ static const unsigned int staticCompressSize = 1024*100;
+ unsigned int rleBufSize = SrcSize * 2;
+ unsigned char *dynamicRleBuf = nullptr;
+ unsigned char *rleBuf;
+
+ if(rleBufSize <= staticCompressSize)
+ {
+ rleBuf = rleCompressBuf;
+ rleBufSize = staticCompressSize;
+ }
+ else
+ {
+ dynamicRleBuf = new unsigned char[rleBufSize];
+ rleBuf = dynamicRleBuf;
+ }
+
+ const unsigned char *pucIn = static_cast<unsigned char*>(pSource);
+ const unsigned char *pucEnd = pucIn + SrcSize;
+ unsigned char *pucOut = rleBuf;
// Compress with RLE first:
// 0 - 254 - encodes a single byte
@@ -129,7 +167,7 @@ HRESULT Compression::CompressRLE(void *pDestination, unsigned int *pDestSize, vo
PIXBeginNamedEvent(0,"RLE compression");
do
{
- unsigned char thisOne = *pucIn++;
+ const unsigned char thisOne = *pucIn++;
unsigned int count = 1;
while( ( pucIn != pucEnd ) && ( *pucIn == thisOne ) && ( count < 256 ) )
@@ -160,15 +198,14 @@ HRESULT Compression::CompressRLE(void *pDestination, unsigned int *pDestSize, vo
*pucOut++ = thisOne;
}
} while (pucIn != pucEnd);
- unsigned int rleSize = (unsigned int)(pucOut - rleCompressBuf);
+ const unsigned int rleSize = static_cast<unsigned int>(pucOut - rleBuf);
PIXEndNamedEvent();
- LeaveCriticalSection(&rleCompressLock);
// Return
if (rleSize <= *pDestSize)
{
*pDestSize = rleSize;
- memcpy(pDestination, rleCompressBuf, *pDestSize);
+ memcpy(pDestination, rleBuf, *pDestSize);
}
else
{
@@ -177,6 +214,9 @@ HRESULT Compression::CompressRLE(void *pDestination, unsigned int *pDestSize, vo
#endif
}
+ if(dynamicRleBuf != nullptr) delete [] dynamicRleBuf;
+ LeaveCriticalSection(&rleCompressLock);
+
return S_OK;
}
@@ -189,39 +229,67 @@ HRESULT Compression::DecompressLZXRLE(void *pDestination, unsigned int *pDestSiz
// only use 5% of this buffer
// 4J Stu - Changed this again to dynamically allocate a buffer if it's going to be too big
- unsigned char *pucIn = NULL;
+ unsigned char *pucIn = nullptr;
//const unsigned int staticRleSize = 1024*200;
//static unsigned char rleBuf[staticRleSize];
unsigned int rleSize = staticRleSize;
- unsigned char *dynamicRleBuf = NULL;
+ unsigned char *dynamicRleBuf = nullptr;
+ HRESULT decompressResult;
+
+ unsigned int safeRleSize = max(rleSize, *pDestSize);
- if(*pDestSize > rleSize)
+ const unsigned int MAX_RLE_ALLOC = 16 * 1024 * 1024; // 16 MB
+ if (safeRleSize > MAX_RLE_ALLOC)
+ {
+ LeaveCriticalSection(&rleDecompressLock);
+ *pDestSize = 0;
+ return E_FAIL;
+ }
+
+ if (safeRleSize > staticRleSize)
{
- rleSize = *pDestSize;
+ rleSize = safeRleSize;
dynamicRleBuf = new unsigned char[rleSize];
- Decompress(dynamicRleBuf, &rleSize, pSource, SrcSize);
+ decompressResult = Decompress(dynamicRleBuf, &rleSize, pSource, SrcSize);
pucIn = (unsigned char *)dynamicRleBuf;
}
else
{
- Decompress(rleDecompressBuf, &rleSize, pSource, SrcSize);
- pucIn = (unsigned char *)rleDecompressBuf;
+ decompressResult = Decompress(rleDecompressBuf, &rleSize, pSource, SrcSize);
+ pucIn = static_cast<unsigned char*>(rleDecompressBuf);
+ }
+
+ if(decompressResult != S_OK)
+ {
+ app.DebugPrintf("*** DecompressLZXRLE: zlib Decompress FAILED hr=0x%08X srcSize=%u expectedDest=%u rleSize=%u\n",
+ decompressResult, SrcSize, *pDestSize, rleSize);
+ if(dynamicRleBuf != nullptr) delete [] dynamicRleBuf;
+ *pDestSize = 0;
+ LeaveCriticalSection(&rleDecompressLock);
+ return decompressResult;
}
//unsigned char *pucIn = (unsigned char *)rleDecompressBuf;
- unsigned char *pucEnd = pucIn + rleSize;
- unsigned char *pucOut = (unsigned char *)pDestination;
+ const unsigned char *pucEnd = pucIn + rleSize;
+ unsigned char *pucOut = static_cast<unsigned char*>(pDestination);
+ unsigned char *pucOutEnd = pucOut + *pDestSize;
while( pucIn != pucEnd )
{
- unsigned char thisOne = *pucIn++;
+ const unsigned char thisOne = *pucIn++;
if( thisOne == 255 )
{
+ if( pucIn >= pucEnd ) break;
unsigned int count = *pucIn++;
if( count < 3 )
{
count++;
+ if (pucOut + count > pucOutEnd)
+ {
+ pucOut = pucOutEnd;
+ break;
+ }
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = 255;
@@ -230,7 +298,13 @@ HRESULT Compression::DecompressLZXRLE(void *pDestination, unsigned int *pDestSiz
else
{
count++;
- unsigned char data = *pucIn++;
+ if( pucIn >= pucEnd ) break;
+ const unsigned char data = *pucIn++;
+ if (pucOut + count > pucOutEnd)
+ {
+ pucOut = pucOutEnd;
+ break;
+ }
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = data;
@@ -239,14 +313,15 @@ HRESULT Compression::DecompressLZXRLE(void *pDestination, unsigned int *pDestSiz
}
else
{
+ if( pucOut >= pucOutEnd ) break;
*pucOut++ = thisOne;
}
}
- *pDestSize = (unsigned int)(pucOut - (unsigned char *)pDestination);
+ *pDestSize = static_cast<unsigned int>(pucOut - static_cast<unsigned char*>(pDestination));
// printf("Decompressed from %d to %d to %d\n",SrcSize,rleSize,*pDestSize);
- if(dynamicRleBuf != NULL) delete [] dynamicRleBuf;
+ if(dynamicRleBuf != nullptr) delete [] dynamicRleBuf;
LeaveCriticalSection(&rleDecompressLock);
return S_OK;
@@ -257,19 +332,26 @@ HRESULT Compression::DecompressRLE(void *pDestination, unsigned int *pDestSize,
EnterCriticalSection(&rleDecompressLock);
//unsigned char *pucIn = (unsigned char *)rleDecompressBuf;
- unsigned char *pucIn = (unsigned char *)pSource;
- unsigned char *pucEnd = pucIn + SrcSize;
- unsigned char *pucOut = (unsigned char *)pDestination;
+ unsigned char *pucIn = static_cast<unsigned char *>(pSource);
+ const unsigned char *pucEnd = pucIn + SrcSize;
+ unsigned char *pucOut = static_cast<unsigned char*>(pDestination);
+ unsigned char *pucOutEnd = pucOut + *pDestSize;
while( pucIn != pucEnd )
{
- unsigned char thisOne = *pucIn++;
+ const unsigned char thisOne = *pucIn++;
if( thisOne == 255 )
{
+ if( pucIn >= pucEnd ) break;
unsigned int count = *pucIn++;
if( count < 3 )
{
count++;
+ if (pucOut + count > pucOutEnd)
+ {
+ pucOut = pucOutEnd;
+ break;
+ }
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = 255;
@@ -278,7 +360,13 @@ HRESULT Compression::DecompressRLE(void *pDestination, unsigned int *pDestSize,
else
{
count++;
- unsigned char data = *pucIn++;
+ if( pucIn >= pucEnd ) break;
+ const unsigned char data = *pucIn++;
+ if (pucOut + count > pucOutEnd)
+ {
+ pucOut = pucOutEnd;
+ break;
+ }
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = data;
@@ -287,10 +375,11 @@ HRESULT Compression::DecompressRLE(void *pDestination, unsigned int *pDestSize,
}
else
{
+ if( pucOut >= pucOutEnd ) break;
*pucOut++ = thisOne;
}
}
- *pDestSize = (unsigned int)(pucOut - (unsigned char *)pDestination);
+ *pDestSize = static_cast<unsigned int>(pucOut - static_cast<unsigned char*>(pDestination));
LeaveCriticalSection(&rleDecompressLock);
return S_OK;
@@ -302,8 +391,8 @@ HRESULT Compression::Compress(void *pDestination, unsigned int *pDestSize, void
// Using zlib for x64 compression - 360 is using native 360 compression and PS3 a stubbed non-compressing version of this
#if defined __ORBIS__ || defined _DURANGO || defined _WIN64 || defined __PSVITA__
SIZE_T destSize = (SIZE_T)(*pDestSize);
- int res = ::compress((Bytef *)pDestination, (uLongf *)&destSize, (Bytef *)pSource, SrcSize);
- *pDestSize = (unsigned int)destSize;
+ const int res = ::compress(static_cast<Bytef *>(pDestination), (uLongf *)&destSize, static_cast<Bytef *>(pSource), SrcSize);
+ *pDestSize = static_cast<unsigned int>(destSize);
return ( ( res == Z_OK ) ? S_OK : -1 );
#elif defined __PS3__
uint32_t destSize = (uint32_t)(*pDestSize);
@@ -330,8 +419,8 @@ HRESULT Compression::Decompress(void *pDestination, unsigned int *pDestSize, voi
// Using zlib for x64 compression - 360 is using native 360 compression and PS3 a stubbed non-compressing version of this
#if defined __ORBIS__ || defined _DURANGO || defined _WIN64 || defined __PSVITA__
SIZE_T destSize = (SIZE_T)(*pDestSize);
- int res = ::uncompress((Bytef *)pDestination, (uLongf *)&destSize, (Bytef *)pSource, SrcSize);
- *pDestSize = (unsigned int)destSize;
+ const int res = ::uncompress(static_cast<Bytef *>(pDestination), (uLongf *)&destSize, static_cast<Bytef *>(pSource), SrcSize);
+ *pDestSize = static_cast<unsigned int>(destSize);
return ( ( res == Z_OK ) ? S_OK : -1 );
#elif defined __PS3__
uint32_t destSize = (uint32_t)(*pDestSize);
@@ -350,11 +439,11 @@ HRESULT Compression::Decompress(void *pDestination, unsigned int *pDestSize, voi
#ifndef _XBOX
VOID Compression::VitaVirtualDecompress(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize) // (LPVOID buf, SIZE_T dwSize, LPVOID dst)
{
- uint8_t *pSrc = (uint8_t *)pSource;
+ const uint8_t *pSrc = static_cast<uint8_t *>(pSource);
int Offset = 0;
int Page = 0;
int Index = 0;
- uint8_t* Data = (uint8_t*)pDestination;
+ uint8_t* Data = static_cast<uint8_t *>(pDestination);
while( Index != SrcSize )
{
// is this a normal value
@@ -368,7 +457,7 @@ VOID Compression::VitaVirtualDecompress(void *pDestination, unsigned int *pDestS
{
// how many zeros do we have
Index += 1;
- int Count = pSrc[Index];
+ const int Count = pSrc[Index];
// to do : this should really be a sequence of memsets
for( int i = 0;i < Count;i += 1 )
{
@@ -396,8 +485,8 @@ HRESULT Compression::DecompressWithType(void *pDestination, unsigned int *pDestS
{
#if (defined _XBOX || defined _DURANGO || defined _WIN64)
SIZE_T destSize = (SIZE_T)(*pDestSize);
- HRESULT res = XMemDecompress(decompressionContext, pDestination, (SIZE_T *)&destSize, pSource, SrcSize);
- *pDestSize = (unsigned int)destSize;
+ const HRESULT res = XMemDecompress(decompressionContext, pDestination, (SIZE_T *)&destSize, pSource, SrcSize);
+ *pDestSize = static_cast<unsigned int>(destSize);
return res;
#else
assert(0);
@@ -406,9 +495,9 @@ HRESULT Compression::DecompressWithType(void *pDestination, unsigned int *pDestS
break;
case eCompressionType_ZLIBRLE:
#if (defined __ORBIS__ || defined __PS3__ || defined _DURANGO || defined _WIN64)
- if (pDestination != NULL)
- return ::uncompress((PBYTE)pDestination, (unsigned long *) pDestSize, (PBYTE) pSource, SrcSize); // Decompress
- else break; // Cannot decompress when destination is NULL
+ if (pDestination != nullptr)
+ return ::uncompress(static_cast<PBYTE>(pDestination), (unsigned long *) pDestSize, static_cast<PBYTE>(pSource), SrcSize); // Decompress
+ else break; // Cannot decompress when destination is nullptr
#else
assert(0);
break;
@@ -417,16 +506,16 @@ HRESULT Compression::DecompressWithType(void *pDestination, unsigned int *pDestS
#if (defined __ORBIS__ || defined __PSVITA__ || defined _DURANGO || defined _WIN64)
// Note that we're missing the normal zlib header and footer so we'll use inflate to
// decompress the payload and skip all the CRC checking, etc
- if (pDestination != NULL)
+ if (pDestination != nullptr)
{
// Read big-endian srcize from array
- PBYTE pbDestSize = (PBYTE) pDestSize;
- PBYTE pbSource = (PBYTE) pSource;
+ const PBYTE pbDestSize = (PBYTE) pDestSize;
+ const PBYTE pbSource = static_cast<PBYTE>(pSource);
for (int i = 3; i >= 0; i--) {
pbDestSize[3-i] = pbSource[i];
}
- byteArray uncompr = byteArray(*pDestSize);
+ const byteArray uncompr = byteArray(*pDestSize);
// Build decompression stream
z_stream strm;
@@ -436,7 +525,7 @@ HRESULT Compression::DecompressWithType(void *pDestination, unsigned int *pDestS
strm.next_out = uncompr.data;
strm.avail_out = uncompr.length;
// Skip those first 4 bytes
- strm.next_in = (PBYTE) pSource + 4;
+ strm.next_in = static_cast<PBYTE>(pSource) + 4;
strm.avail_in = SrcSize - 4;
int hr = inflateInit2(&strm, -15);
@@ -466,7 +555,7 @@ HRESULT Compression::DecompressWithType(void *pDestination, unsigned int *pDestS
delete uncompr.data;
return S_OK;
}
- else break; // Cannot decompress when destination is NULL
+ else break; // Cannot decompress when destination is nullptr
#else
assert(0);
#endif