diff --git a/src/saveload/oldloader.cpp b/src/saveload/oldloader.cpp --- a/src/saveload/oldloader.cpp +++ b/src/saveload/oldloader.cpp @@ -22,6 +22,8 @@ #include "saveload_internal.h" #include "oldloader.h" +#include + static const int TTO_HEADER_SIZE = 41; static const int TTD_HEADER_SIZE = 49; @@ -49,13 +51,14 @@ static byte ReadByteFromFile(LoadgameSta /* To avoid slow reads, we read BUFFER_SIZE of bytes per time and just return a byte per time */ if (ls->buffer_cur >= ls->buffer_count) { + /* Read some new bytes from the file */ int count = (int)fread(ls->buffer, 1, BUFFER_SIZE, ls->file); /* We tried to read, but there is nothing in the file anymore.. */ if (count == 0) { DEBUG(oldloader, 0, "Read past end of file, loading failed"); - ls->failed = true; + throw std::exception(); } ls->buffer_count = count; @@ -119,8 +122,6 @@ bool LoadChunk(LoadgameState *ls, void * if (chunk->type & OC_DEREFERENCE_POINTER) ptr = *(byte**)ptr; for (uint i = 0; i < chunk->amount; i++) { - if (ls->failed) return false; - /* Handle simple types */ if (GetOldChunkType(chunk->type) != 0) { switch (GetOldChunkType(chunk->type)) { @@ -135,7 +136,7 @@ bool LoadChunk(LoadgameState *ls, void * case OC_ASSERT: DEBUG(oldloader, 4, "Assert point: 0x%X / 0x%X", ls->total_read, chunk->offset + _bump_assert_value); - if (ls->total_read != chunk->offset + _bump_assert_value) ls->failed = true; + if (ls->total_read != chunk->offset + _bump_assert_value) throw std::exception(); default: break; } } else { @@ -189,7 +190,6 @@ static void InitLoading(LoadgameState *l { ls->chunk_size = 0; ls->total_read = 0; - ls->failed = false; ls->decoding = false; ls->decode_char = 0; @@ -301,7 +301,14 @@ bool LoadOldSaveGame(const char *file) _savegame_type = type; - if (proc == NULL || !proc(&ls)) { + bool game_loaded; + try { + game_loaded = proc != NULL && proc(&ls); + } catch (...) { + game_loaded = false; + } + + if (!game_loaded) { SetSaveLoadError(STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED); fclose(ls.file); return false; diff --git a/src/saveload/oldloader.h b/src/saveload/oldloader.h --- a/src/saveload/oldloader.h +++ b/src/saveload/oldloader.h @@ -31,7 +31,6 @@ struct LoadgameState { byte buffer[BUFFER_SIZE]; uint total_read; - bool failed; }; /* OldChunk-Type */ diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -1479,7 +1479,7 @@ static bool LoadOldMapPart1(LoadgameStat } } - return !ls->failed; + return true; } static bool LoadOldMapPart2(LoadgameState *ls, int num) @@ -1493,7 +1493,7 @@ static bool LoadOldMapPart2(LoadgameStat _m[i].m5 = ReadByte(ls); } - return !ls->failed; + return true; } static bool LoadTTDPatchExtraChunks(LoadgameState *ls, int num) @@ -1548,7 +1548,7 @@ static bool LoadTTDPatchExtraChunks(Load } } - return !ls->failed; + return true; } extern TileIndex _cur_tileloop_tile; @@ -1734,11 +1734,17 @@ bool LoadTTDMain(LoadgameState *ls) SmallStackSafeStackAlloc map3; _old_map3 = map3.data; _old_vehicle_names = NULL; - if (!LoadChunk(ls, NULL, main_chunk)) { - DEBUG(oldloader, 0, "Loading failed"); + try { + if (!LoadChunk(ls, NULL, main_chunk)) { + DEBUG(oldloader, 0, "Loading failed"); + free(_old_vehicle_names); + return false; + } + } catch (...) { free(_old_vehicle_names); - return false; + throw; } + DEBUG(oldloader, 3, "Done, converting game data..."); FixTTDMapArray();