diff --git a/src/openrct2/rct12/SawyerEncoding.cpp b/src/openrct2/rct12/SawyerEncoding.cpp index d1b161010e..fa0fa45141 100644 --- a/src/openrct2/rct12/SawyerEncoding.cpp +++ b/src/openrct2/rct12/SawyerEncoding.cpp @@ -97,4 +97,41 @@ namespace SawyerEncoding } return success; } + + bool ValidateChecksum(IStream * stream) + { + // Get data size + uint64 initialPosition = stream->GetPosition(); + uint64 dataSize = stream->GetLength() - initialPosition; + if (dataSize < 8) + { + return false; + } + dataSize -= 4; + + // Calculate checksum + uint32 checksum = 0; + do + { + uint8 buffer[4096]; + uint64 bufferSize = Math::Min(dataSize, sizeof(buffer)); + stream->Read(buffer, bufferSize); + + for (uint64 i = 0; i < bufferSize; i++) + { + checksum += buffer[i]; + } + + dataSize -= bufferSize; + } + while (dataSize != 0); + + // Read file checksum + uint32 fileChecksum = stream->ReadValue(); + + // Rewind + stream->SetPosition(initialPosition); + + return checksum == fileChecksum; + } } diff --git a/src/openrct2/rct12/SawyerEncoding.h b/src/openrct2/rct12/SawyerEncoding.h index ace15db533..bf25b6824b 100644 --- a/src/openrct2/rct12/SawyerEncoding.h +++ b/src/openrct2/rct12/SawyerEncoding.h @@ -31,4 +31,6 @@ namespace SawyerEncoding { return TryReadChunk(dst, sizeof(T), stream); } + + bool ValidateChecksum(IStream * stream); } diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 923efed6e7..8eca777a28 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -85,15 +85,6 @@ public: void LoadSavedGame(const utf8 * path) override { - // if (!sawyercoding_validate_checksum(rw)) - // { - // gErrorType = ERROR_TYPE_FILE_LOAD; - // gGameCommandErrorTitle = STR_FILE_CONTAINS_INVALID_DATA; - // - // log_error("failed to load saved game, invalid checksum"); - // throw IOException("Invalid SV6 checksum."); - // } - auto fs = FileStream(path, FILE_MODE_OPEN); LoadFromStream(&fs, false); _s6Path = path; @@ -101,17 +92,6 @@ public: void LoadScenario(const utf8 * path) override { - // if (!gConfigGeneral.allow_loading_with_incorrect_checksum && !sawyercoding_validate_checksum(rw)) - // { - // SDL_RWclose(rw); - // - // gErrorType = ERROR_TYPE_FILE_LOAD; - // gErrorStringId = STR_FILE_CONTAINS_INVALID_DATA; - // - // log_error("failed to load scenario, invalid checksum"); - // throw IOException("Invalid SC6 checksum."); - // } - auto fs = FileStream(path, FILE_MODE_OPEN); LoadFromStream(&fs, true); _s6Path = path; @@ -119,6 +99,11 @@ public: void LoadFromStream(IStream * stream, bool isScenario) { + if (!gConfigGeneral.allow_loading_with_incorrect_checksum && !SawyerEncoding::ValidateChecksum(stream)) + { + throw IOException("Invalid checksum."); + } + SawyerEncoding::ReadChunkTolerant(&_s6.header, sizeof(_s6.header), stream); log_verbose("saved game classic_flag = 0x%02x\n", _s6.header.classic_flag);