| 1461 | #endif |
| 1462 | |
| 1463 | bool ReadCompressedBlock(FILE* filePtr, bool skip) |
| 1464 | { |
| 1465 | long long compressedSize = 0; |
| 1466 | long long uncompressedSize = 0; |
| 1467 | |
| 1468 | ReadFileEx(&uncompressedSize, 1, sizeof(long long), filePtr); |
| 1469 | ReadFileEx(&compressedSize, 1, sizeof(long long), filePtr); |
| 1470 | |
| 1471 | #ifndef _WIN64 |
| 1472 | // Safeguard against incompatible block size. |
| 1473 | if (uncompressedSize > INT_MAX || compressedSize > INT_MAX) |
| 1474 | throw std::exception{ "Level data block exceeds 2 GB and can't be loaded by a 32-bit version of the engine." }; |
| 1475 | #endif |
| 1476 | |
| 1477 | // Safeguard against changed file format. |
| 1478 | auto remainingSize = GetRemainingSize(filePtr); |
| 1479 | if (uncompressedSize <= 0 || compressedSize <= 0 || compressedSize > remainingSize) |
| 1480 | throw std::exception{ "Data block size is incorrect. Probably old level version?" }; |
| 1481 | |
| 1482 | if (skip) |
| 1483 | { |
| 1484 | #ifdef _WIN64 |
| 1485 | _fseeki64(filePtr, compressedSize, SEEK_CUR); |
| 1486 | #else |
| 1487 | fseek(filePtr, compressedSize, SEEK_CUR); |
| 1488 | #endif |
| 1489 | return false; |
| 1490 | } |
| 1491 | |
| 1492 | auto compressedBuffer = (char*)malloc(compressedSize); |
| 1493 | ReadFileEx(compressedBuffer, compressedSize, 1, filePtr); |
| 1494 | DataPtr = (char*)malloc(uncompressedSize); |
| 1495 | |
| 1496 | if (!Decompress(DataPtr, compressedBuffer, uncompressedSize)) |
| 1497 | { |
| 1498 | free(compressedBuffer); |
| 1499 | free(DataPtr); |
| 1500 | DataPtr = nullptr; |
| 1501 | throw std::exception{ "LZ4 decompression failed." }; |
| 1502 | } |
| 1503 | |
| 1504 | free(compressedBuffer); |
| 1505 | |
| 1506 | CurrentDataPtr = DataPtr; |
| 1507 | |
| 1508 | return true; |
| 1509 | } |
| 1510 | |
| 1511 | void FinalizeBlock() |
| 1512 | { |
no test coverage detected