diff options
| author | qwasdrizzel <145519042+qwasdrizzel@users.noreply.github.com> | 2026-03-16 21:44:26 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-16 21:44:26 -0500 |
| commit | ce739f6045ec72127491286ea3f3f21e537c1b55 (patch) | |
| tree | f33bd42a47c1b4a7b2153a7fb77127ee3b407db9 /Minecraft.World/compression.cpp | |
| parent | 255a18fe8e9b57377975f82e2b227afe2a12eda0 (diff) | |
| parent | 5a59f5d146b43811dde6a5a0245ee9875d7b5cd1 (diff) | |
Merge branch 'smartcmd:main' into main
Diffstat (limited to 'Minecraft.World/compression.cpp')
| -rw-r--r-- | Minecraft.World/compression.cpp | 197 |
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 |
