the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 546 lines 15 kB view raw
1#include "stdafx.h" 2#include "compression.h" 3#if defined __ORBIS__ || defined __PS3__ || defined _DURANGO || defined _WIN64 4#include "..\Minecraft.Client\Common\zlib\zlib.h" 5#endif 6 7#if defined __PSVITA__ 8#include "..\Minecraft.Client\PSVita\PSVitaExtras\zlib.h" 9#elif defined __PS3__ 10#include "..\Minecraft.Client\PS3\PS3Extras\EdgeZLib.h" 11#endif //__PS3__ 12 13 14DWORD Compression::tlsIdx = 0; 15Compression::ThreadStorage *Compression::tlsDefault = NULL; 16 17Compression::ThreadStorage::ThreadStorage() 18{ 19 compression = new Compression(); 20} 21 22Compression::ThreadStorage::~ThreadStorage() 23{ 24 delete compression; 25} 26 27void Compression::CreateNewThreadStorage() 28{ 29 ThreadStorage *tls = new ThreadStorage(); 30 if(tlsDefault == NULL ) 31 { 32 tlsIdx = TlsAlloc(); 33 tlsDefault = tls; 34 } 35 TlsSetValue(tlsIdx, tls); 36} 37 38void Compression::UseDefaultThreadStorage() 39{ 40 TlsSetValue(tlsIdx, tlsDefault); 41} 42 43void Compression::ReleaseThreadStorage() 44{ 45 ThreadStorage *tls = (ThreadStorage *)TlsGetValue(tlsIdx); 46 if( tls == tlsDefault ) return; 47 48 delete tls; 49} 50 51Compression *Compression::getCompression() 52{ 53 ThreadStorage *tls = (ThreadStorage *)TlsGetValue(tlsIdx); 54 return tls->compression; 55} 56 57HRESULT Compression::CompressLZXRLE(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize) 58{ 59 EnterCriticalSection(&rleCompressLock); 60 //static unsigned char rleBuf[1024*100]; 61 62 unsigned char *pucIn = (unsigned char *)pSource; 63 unsigned char *pucEnd = pucIn + SrcSize; 64 unsigned char *pucOut = (unsigned char *)rleCompressBuf; 65 66 // Compress with RLE first: 67 // 0 - 254 - encodes a single byte 68 // 255 followed by 0, 1, 2 - encodes a 1, 2, or 3 255s 69 // 255 followed by 3-255, followed by a byte - encodes a run of n + 1 bytes 70 PIXBeginNamedEvent(0,"RLE compression"); 71 do 72 { 73 unsigned char thisOne = *pucIn++; 74 75 unsigned int count = 1; 76 while( ( pucIn != pucEnd ) && ( *pucIn == thisOne ) && ( count < 256 ) ) 77 { 78 pucIn++; 79 count++; 80 } 81 82 if( count <= 3 ) 83 { 84 if( thisOne == 255 ) 85 { 86 *pucOut++ = 255; 87 *pucOut++ = count - 1; 88 } 89 else 90 { 91 for( unsigned int i = 0; i < count ; i++ ) 92 { 93 *pucOut++ = thisOne; 94 } 95 } 96 } 97 else 98 { 99 *pucOut++ = 255; 100 *pucOut++ = count - 1; 101 *pucOut++ = thisOne; 102 } 103 } while (pucIn != pucEnd); 104 unsigned int rleSize = (unsigned int)(pucOut - rleCompressBuf); 105 PIXEndNamedEvent(); 106 107 PIXBeginNamedEvent(0,"Secondary compression"); 108 Compress(pDestination, pDestSize, rleCompressBuf, rleSize); 109 PIXEndNamedEvent(); 110 LeaveCriticalSection(&rleCompressLock); 111// printf("Compressed from %d to %d to %d\n",SrcSize,rleSize,*pDestSize); 112 113 return S_OK; 114} 115 116HRESULT Compression::CompressRLE(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize) 117{ 118 EnterCriticalSection(&rleCompressLock); 119 //static unsigned char rleBuf[1024*100]; 120 121 unsigned char *pucIn = (unsigned char *)pSource; 122 unsigned char *pucEnd = pucIn + SrcSize; 123 unsigned char *pucOut = (unsigned char *)rleCompressBuf; 124 125 // Compress with RLE first: 126 // 0 - 254 - encodes a single byte 127 // 255 followed by 0, 1, 2 - encodes a 1, 2, or 3 255s 128 // 255 followed by 3-255, followed by a byte - encodes a run of n + 1 bytes 129 PIXBeginNamedEvent(0,"RLE compression"); 130 do 131 { 132 unsigned char thisOne = *pucIn++; 133 134 unsigned int count = 1; 135 while( ( pucIn != pucEnd ) && ( *pucIn == thisOne ) && ( count < 256 ) ) 136 { 137 pucIn++; 138 count++; 139 } 140 141 if( count <= 3 ) 142 { 143 if( thisOne == 255 ) 144 { 145 *pucOut++ = 255; 146 *pucOut++ = count - 1; 147 } 148 else 149 { 150 for( unsigned int i = 0; i < count ; i++ ) 151 { 152 *pucOut++ = thisOne; 153 } 154 } 155 } 156 else 157 { 158 *pucOut++ = 255; 159 *pucOut++ = count - 1; 160 *pucOut++ = thisOne; 161 } 162 } while (pucIn != pucEnd); 163 unsigned int rleSize = (unsigned int)(pucOut - rleCompressBuf); 164 PIXEndNamedEvent(); 165 LeaveCriticalSection(&rleCompressLock); 166 167 // Return 168 if (rleSize <= *pDestSize) 169 { 170 *pDestSize = rleSize; 171 memcpy(pDestination, rleCompressBuf, *pDestSize); 172 } 173 else 174 { 175#ifndef _CONTENT_PACKAGE 176 assert(false); 177#endif 178 } 179 180 return S_OK; 181} 182 183HRESULT Compression::DecompressLZXRLE(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize) 184{ 185 EnterCriticalSection(&rleDecompressLock); 186 // 4J Stu - Fix for #13676 - Crash: Crash while attempting to load a world after updating TU 187 // Some saves can have chunks that decompress into very large sizes, so I have doubled the size of this buffer 188 // Ideally we should be able to dynamically allocate the buffer if it's going to be too big, as most chunks 189 // only use 5% of this buffer 190 191 // 4J Stu - Changed this again to dynamically allocate a buffer if it's going to be too big 192 unsigned char *pucIn = NULL; 193 194 //const unsigned int staticRleSize = 1024*200; 195 //static unsigned char rleBuf[staticRleSize]; 196 unsigned int rleSize = staticRleSize; 197 unsigned char *dynamicRleBuf = NULL; 198 199 if(*pDestSize > rleSize) 200 { 201 rleSize = *pDestSize; 202 dynamicRleBuf = new unsigned char[rleSize]; 203 Decompress(dynamicRleBuf, &rleSize, pSource, SrcSize); 204 pucIn = (unsigned char *)dynamicRleBuf; 205 } 206 else 207 { 208 Decompress(rleDecompressBuf, &rleSize, pSource, SrcSize); 209 pucIn = (unsigned char *)rleDecompressBuf; 210 } 211 212 //unsigned char *pucIn = (unsigned char *)rleDecompressBuf; 213 unsigned char *pucEnd = pucIn + rleSize; 214 unsigned char *pucOut = (unsigned char *)pDestination; 215 216 while( pucIn != pucEnd ) 217 { 218 unsigned char thisOne = *pucIn++; 219 if( thisOne == 255 ) 220 { 221 unsigned int count = *pucIn++; 222 if( count < 3 ) 223 { 224 count++; 225 for( unsigned int i = 0; i < count; i++ ) 226 { 227 *pucOut++ = 255; 228 } 229 } 230 else 231 { 232 count++; 233 unsigned char data = *pucIn++; 234 for( unsigned int i = 0; i < count; i++ ) 235 { 236 *pucOut++ = data; 237 } 238 } 239 } 240 else 241 { 242 *pucOut++ = thisOne; 243 } 244 } 245 *pDestSize = (unsigned int)(pucOut - (unsigned char *)pDestination); 246 247// printf("Decompressed from %d to %d to %d\n",SrcSize,rleSize,*pDestSize); 248 249 if(dynamicRleBuf != NULL) delete [] dynamicRleBuf; 250 251 LeaveCriticalSection(&rleDecompressLock); 252 return S_OK; 253} 254 255HRESULT Compression::DecompressRLE(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize) 256{ 257 EnterCriticalSection(&rleDecompressLock); 258 259 //unsigned char *pucIn = (unsigned char *)rleDecompressBuf; 260 unsigned char *pucIn = (unsigned char *)pSource; 261 unsigned char *pucEnd = pucIn + SrcSize; 262 unsigned char *pucOut = (unsigned char *)pDestination; 263 264 while( pucIn != pucEnd ) 265 { 266 unsigned char thisOne = *pucIn++; 267 if( thisOne == 255 ) 268 { 269 unsigned int count = *pucIn++; 270 if( count < 3 ) 271 { 272 count++; 273 for( unsigned int i = 0; i < count; i++ ) 274 { 275 *pucOut++ = 255; 276 } 277 } 278 else 279 { 280 count++; 281 unsigned char data = *pucIn++; 282 for( unsigned int i = 0; i < count; i++ ) 283 { 284 *pucOut++ = data; 285 } 286 } 287 } 288 else 289 { 290 *pucOut++ = thisOne; 291 } 292 } 293 *pDestSize = (unsigned int)(pucOut - (unsigned char *)pDestination); 294 295 LeaveCriticalSection(&rleDecompressLock); 296 return S_OK; 297} 298 299 300HRESULT Compression::Compress(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize) 301{ 302 // Using zlib for x64 compression - 360 is using native 360 compression and PS3 a stubbed non-compressing version of this 303#if defined __ORBIS__ || defined _DURANGO || defined _WIN64 || defined __PSVITA__ 304 SIZE_T destSize = (SIZE_T)(*pDestSize); 305 int res = ::compress((Bytef *)pDestination, (uLongf *)&destSize, (Bytef *)pSource, SrcSize); 306 *pDestSize = (unsigned int)destSize; 307 return ( ( res == Z_OK ) ? S_OK : -1 ); 308#elif defined __PS3__ 309 uint32_t destSize = (uint32_t)(*pDestSize); 310 bool res = EdgeZLib::Compress(pDestination, &destSize, pSource, SrcSize); 311 *pDestSize = (unsigned int)destSize; 312 return ( ( res ) ? S_OK : -1 ); 313#else 314 SIZE_T destSize = (SIZE_T)(*pDestSize); 315 HRESULT res = XMemCompress(compressionContext, pDestination, &destSize, pSource, SrcSize); 316 *pDestSize = (unsigned int)destSize; 317 return res; 318#endif 319} 320 321HRESULT Compression::Decompress(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize) 322{ 323 324 if(m_decompressType != m_localDecompressType) // check if we're decompressing data from a different platform 325 { 326 // only used for loading a save from a different platform (Sony cloud storage cross play) 327 return DecompressWithType(pDestination, pDestSize, pSource, SrcSize); 328 } 329 330 // Using zlib for x64 compression - 360 is using native 360 compression and PS3 a stubbed non-compressing version of this 331#if defined __ORBIS__ || defined _DURANGO || defined _WIN64 || defined __PSVITA__ 332 SIZE_T destSize = (SIZE_T)(*pDestSize); 333 int res = ::uncompress((Bytef *)pDestination, (uLongf *)&destSize, (Bytef *)pSource, SrcSize); 334 *pDestSize = (unsigned int)destSize; 335 return ( ( res == Z_OK ) ? S_OK : -1 ); 336#elif defined __PS3__ 337 uint32_t destSize = (uint32_t)(*pDestSize); 338 bool res = EdgeZLib::Decompress(pDestination, &destSize, pSource, SrcSize); 339 *pDestSize = (unsigned int)destSize; 340 return ( ( res ) ? S_OK : -1 ); 341#else 342 SIZE_T destSize = (SIZE_T)(*pDestSize); 343 HRESULT res = XMemDecompress(decompressionContext, pDestination, (SIZE_T *)&destSize, pSource, SrcSize); 344 *pDestSize = (unsigned int)destSize; 345 return res; 346#endif 347} 348 349// MGH - same as VirtualDecompress in PSVitaStubs, but for use on other platforms (so no virtual mem stuff) 350#ifndef _XBOX 351VOID Compression::VitaVirtualDecompress(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize) // (LPVOID buf, SIZE_T dwSize, LPVOID dst) 352{ 353 uint8_t *pSrc = (uint8_t *)pSource; 354 int Offset = 0; 355 int Page = 0; 356 int Index = 0; 357 uint8_t* Data = (uint8_t*)pDestination; 358 while( Index != SrcSize ) 359 { 360 // is this a normal value 361 if( pSrc[Index] ) 362 { 363 // just copy it across 364 Data[Offset] = pSrc[Index]; 365 Offset += 1; 366 } 367 else 368 { 369 // how many zeros do we have 370 Index += 1; 371 int Count = pSrc[Index]; 372 // to do : this should really be a sequence of memsets 373 for( int i = 0;i < Count;i += 1 ) 374 { 375 Data[Offset] = 0; 376 Offset += 1; 377 } 378 } 379 Index += 1; 380 } 381 *pDestSize = Offset; 382} 383#endif 384 385 386HRESULT Compression::DecompressWithType(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize) 387{ 388 switch(m_decompressType) 389 { 390 case eCompressionType_RLE: // 4J-JEV, RLE is just that; don't want to break here though. 391 case eCompressionType_None: 392 memcpy(pDestination,pSource,SrcSize); 393 *pDestSize = SrcSize; 394 return S_OK; 395 case eCompressionType_LZXRLE: 396 { 397#if (defined _XBOX || defined _DURANGO || defined _WIN64) 398 SIZE_T destSize = (SIZE_T)(*pDestSize); 399 HRESULT res = XMemDecompress(decompressionContext, pDestination, (SIZE_T *)&destSize, pSource, SrcSize); 400 *pDestSize = (unsigned int)destSize; 401 return res; 402#else 403 assert(0); 404#endif 405 } 406 break; 407 case eCompressionType_ZLIBRLE: 408#if (defined __ORBIS__ || defined __PS3__ || defined _DURANGO || defined _WIN64) 409 if (pDestination != NULL) 410 return ::uncompress((PBYTE)pDestination, (unsigned long *) pDestSize, (PBYTE) pSource, SrcSize); // Decompress 411 else break; // Cannot decompress when destination is NULL 412#else 413 assert(0); 414 break; 415#endif 416 case eCompressionType_PS3ZLIB: 417#if (defined __ORBIS__ || defined __PSVITA__ || defined _DURANGO || defined _WIN64) 418 // Note that we're missing the normal zlib header and footer so we'll use inflate to 419 // decompress the payload and skip all the CRC checking, etc 420 if (pDestination != NULL) 421 { 422 // Read big-endian srcize from array 423 PBYTE pbDestSize = (PBYTE) pDestSize; 424 PBYTE pbSource = (PBYTE) pSource; 425 for (int i = 3; i >= 0; i--) { 426 pbDestSize[3-i] = pbSource[i]; 427 } 428 429 byteArray uncompr = byteArray(*pDestSize); 430 431 // Build decompression stream 432 z_stream strm; 433 strm.zalloc = Z_NULL; 434 strm.zfree = Z_NULL; 435 strm.opaque = Z_NULL; 436 strm.next_out = uncompr.data; 437 strm.avail_out = uncompr.length; 438 // Skip those first 4 bytes 439 strm.next_in = (PBYTE) pSource + 4; 440 strm.avail_in = SrcSize - 4; 441 442 int hr = inflateInit2(&strm, -15); 443 444 // Run inflate() on input until end of stream 445 do { 446 hr = inflate(&strm, Z_NO_FLUSH); 447 448 // Check 449 switch (hr) { 450 case Z_NEED_DICT: 451 case Z_DATA_ERROR: 452 case Z_MEM_ERROR: 453 case Z_STREAM_ERROR: 454 (void)inflateEnd(&strm); 455 assert(false); 456 } 457 } while (hr != Z_STREAM_END); 458 459 inflateEnd(&strm); // MGH - added, to clean up zlib, was causing a leak on Vita when dowloading a PS3 save 460 461 // Copy the uncompressed data to the destination 462 memcpy(pDestination, uncompr.data, uncompr.length); 463 *pDestSize = uncompr.length; 464 465 // Delete uncompressed data 466 delete uncompr.data; 467 return S_OK; 468 } 469 else break; // Cannot decompress when destination is NULL 470#else 471 assert(0); 472#endif 473 } 474 475 assert(false); 476 return -1; 477} 478 479 480 481Compression::Compression() 482{ 483 // Using zlib for x64 compression - 360 is using native 360 compression and PS3 a stubbed non-compressing version of this 484#if !(defined __ORBIS__ || defined __PS3__) 485 // The default parameters for compression context allocated about 6.5MB, reducing the partition size here from the default 512KB to 128KB 486 // brings this down to about 3MB 487 XMEMCODEC_PARAMETERS_LZX params; 488 params.Flags = 0; 489 params.WindowSize = 128 * 1024; 490 params.CompressionPartitionSize = 128 * 1024; 491 492 XMemCreateCompressionContext(XMEMCODEC_LZX,&params,0,&compressionContext); 493 XMemCreateDecompressionContext(XMEMCODEC_LZX,&params,0,&decompressionContext); 494#endif 495 496#if defined _XBOX 497 m_localDecompressType = eCompressionType_LZXRLE; 498#elif defined __PS3__ 499 m_localDecompressType = eCompressionType_PS3ZLIB; 500#else 501 m_localDecompressType = eCompressionType_ZLIBRLE; 502#endif 503 m_decompressType = m_localDecompressType; 504 505 InitializeCriticalSection(&rleCompressLock); 506 InitializeCriticalSection(&rleDecompressLock); 507} 508 509Compression::~Compression() 510{ 511#if !(defined __ORBIS__ || defined __PS3__ || defined __PSVITA__) 512 513 XMemDestroyCompressionContext(compressionContext); 514 XMemDestroyDecompressionContext(decompressionContext); 515#endif 516 DeleteCriticalSection(&rleCompressLock); 517 DeleteCriticalSection(&rleDecompressLock); 518} 519 520 521 522void Compression::SetDecompressionType(ESavePlatform platform) 523{ 524 switch(platform) 525 { 526 case SAVE_FILE_PLATFORM_X360: 527 Compression::getCompression()->SetDecompressionType(Compression::eCompressionType_LZXRLE); 528 break; 529 case SAVE_FILE_PLATFORM_PS3: 530 Compression::getCompression()->SetDecompressionType(Compression::eCompressionType_PS3ZLIB); 531 break; 532 case SAVE_FILE_PLATFORM_XBONE: 533 case SAVE_FILE_PLATFORM_PS4: 534 case SAVE_FILE_PLATFORM_PSVITA: 535 case SAVE_FILE_PLATFORM_WIN64: 536 Compression::getCompression()->SetDecompressionType(Compression::eCompressionType_ZLIBRLE); 537 break; 538 default: 539 assert(0); 540 break; 541 } 542} 543 544/*Compression gCompression;*/ 545 546