Changeset - r15577:a61e44bed2f3
[Not reviewed]
master
0 3 0
rubidium - 14 years ago 2010-07-30 22:57:46
rubidium@openttd.org
(svn r20247) -Fix: when it is known the loading an old savegame is going to fail, bail out immediately (using an exception) instead of going on until e.g. the expected number of byte is read
3 files changed with 25 insertions and 13 deletions:
0 comments (0 inline, 0 general)
src/saveload/oldloader.cpp
Show inline comments
 
@@ -19,12 +19,14 @@
 

	
 
#include "table/strings.h"
 

	
 
#include "saveload_internal.h"
 
#include "oldloader.h"
 

	
 
#include <exception>
 

	
 
static const int TTO_HEADER_SIZE = 41;
 
static const int TTD_HEADER_SIZE = 49;
 

	
 
uint32 _bump_assert_value;
 

	
 
static inline OldChunkType GetOldChunkType(OldChunkType type)     {return (OldChunkType)GB(type, 0, 4);}
 
@@ -46,19 +48,20 @@ static inline byte CalcOldVarLen(OldChun
 
 */
 
static byte ReadByteFromFile(LoadgameState *ls)
 
{
 
	/* 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;
 
		ls->buffer_cur   = 0;
 
	}
 

	
 
@@ -116,14 +119,12 @@ bool LoadChunk(LoadgameState *ls, void *
 
		}
 

	
 
		byte *ptr = (byte*)chunk->ptr;
 
		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)) {
 
					/* Just read the byte and forget about it */
 
					case OC_NULL: ReadByte(ls); break;
 

	
 
@@ -132,13 +133,13 @@ bool LoadChunk(LoadgameState *ls, void *
 
						 * are going to read */
 
						if (!chunk->proc(ls, i)) return false;
 
						break;
 

	
 
					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 {
 
				uint64 res = 0;
 

	
 
				/* Reading from the file: bits 16 to 23 have the FILE type */
 
@@ -186,13 +187,12 @@ bool LoadChunk(LoadgameState *ls, void *
 
 *
 
 */
 
static void InitLoading(LoadgameState *ls)
 
{
 
	ls->chunk_size   = 0;
 
	ls->total_read   = 0;
 
	ls->failed       = false;
 

	
 
	ls->decoding     = false;
 
	ls->decode_char  = 0;
 

	
 
	ls->buffer_cur   = 0;
 
	ls->buffer_count = 0;
 
@@ -298,13 +298,20 @@ bool LoadOldSaveGame(const char *file)
 
		case SGT_TTD: proc = &LoadTTDMain; break;
 
		default: break;
 
	}
 

	
 
	_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;
 
	}
 

	
 
	_pause_mode = 2;
src/saveload/oldloader.h
Show inline comments
 
@@ -28,13 +28,12 @@ struct LoadgameState {
 

	
 
	uint buffer_count;
 
	uint buffer_cur;
 
	byte buffer[BUFFER_SIZE];
 

	
 
	uint total_read;
 
	bool failed;
 
};
 

	
 
/* OldChunk-Type */
 
enum OldChunkType {
 
	OC_SIMPLE    = 0,
 
	OC_NULL      = 1,
src/saveload/oldloader_sl.cpp
Show inline comments
 
@@ -1476,13 +1476,13 @@ static bool LoadOldMapPart1(LoadgameStat
 
			_m[i * 4 + 1].m6 = GB(b, 2, 2);
 
			_m[i * 4 + 2].m6 = GB(b, 4, 2);
 
			_m[i * 4 + 3].m6 = GB(b, 6, 2);
 
		}
 
	}
 

	
 
	return !ls->failed;
 
	return true;
 
}
 

	
 
static bool LoadOldMapPart2(LoadgameState *ls, int num)
 
{
 
	uint i;
 

	
 
@@ -1490,13 +1490,13 @@ static bool LoadOldMapPart2(LoadgameStat
 
		_m[i].type_height = ReadByte(ls);
 
	}
 
	for (i = 0; i < OLD_MAP_SIZE; i++) {
 
		_m[i].m5 = ReadByte(ls);
 
	}
 

	
 
	return !ls->failed;
 
	return true;
 
}
 

	
 
static bool LoadTTDPatchExtraChunks(LoadgameState *ls, int num)
 
{
 
	ReadTTDPatchFlags();
 

	
 
@@ -1545,13 +1545,13 @@ static bool LoadTTDPatchExtraChunks(Load
 
				DEBUG(oldloader, 4, "Skipping unknown extra chunk %X", id);
 
				while (len-- != 0) ReadByte(ls);
 
				break;
 
		}
 
	}
 

	
 
	return !ls->failed;
 
	return true;
 
}
 

	
 
extern TileIndex _cur_tileloop_tile;
 
extern uint16 _disaster_delay;
 
extern byte _trees_tick_ctr;
 
static const OldChunks main_chunk[] = {
 
@@ -1731,17 +1731,23 @@ bool LoadTTDMain(LoadgameState *ls)
 

	
 
	DEBUG(oldloader, 3, "Reading main chunk...");
 
	/* Load the biggest chunk */
 
	SmallStackSafeStackAlloc<byte, OLD_MAP_SIZE * 2> 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();
 
	FixTTDDepots();
 

	
 
	/* Fix some general stuff */
0 comments (0 inline, 0 general)