mirror of https://github.com/OpenTTD/OpenTTD
(svn r20872) [1.0] -Backport from trunk:
- Fix: Road/water toolbars did not get updated when the first vehicle of their type becomes available [FS#4141] (r20856) - Fix: Smallmap legend buttons must all be equal in size, even if their contents is not (r20851) - Fix: Deadlock when aborting map generation on Windows [FS#3707] (r20822) - Fix: Be a bit more lenient w.r.t. invalid savegames; do not crash on saveload related NOT_REACHEDs, just show the user an error that the savegame is corrupted [FS#3714] (r20819) - Fix: Make the crash-on-saveload message clearer and more correct [FS#3791] (r20818)release/1.0
parent
e9b13f89a3
commit
ad4dd864f9
|
@ -172,6 +172,7 @@ struct BuildDocksToolbarWindow : Window {
|
||||||
BuildDocksToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
|
BuildDocksToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
|
||||||
{
|
{
|
||||||
this->InitNested(desc, window_number);
|
this->InitNested(desc, window_number);
|
||||||
|
this->OnInvalidateData();
|
||||||
if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
|
if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,9 +181,17 @@ struct BuildDocksToolbarWindow : Window {
|
||||||
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
|
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnInvalidateData(int data = 0)
|
||||||
|
{
|
||||||
|
this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_SHIP),
|
||||||
|
DTW_DEPOT,
|
||||||
|
DTW_STATION,
|
||||||
|
DTW_BUOY,
|
||||||
|
WIDGET_LIST_END);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void OnPaint()
|
virtual void OnPaint()
|
||||||
{
|
{
|
||||||
this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_SHIP), DTW_DEPOT, DTW_STATION, DTW_BUOY, WIDGET_LIST_END);
|
|
||||||
this->DrawWidgets();
|
this->DrawWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -581,6 +581,10 @@ static void AcceptEnginePreview(EngineID eid, CompanyID company)
|
||||||
if (company == _local_company) {
|
if (company == _local_company) {
|
||||||
AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type);
|
AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the toolbar. */
|
||||||
|
if (e->type == VEH_ROAD) InvalidateWindowData(WC_BUILD_TOOLBAR, TRANSPORT_ROAD);
|
||||||
|
if (e->type == VEH_SHIP) InvalidateWindowData(WC_BUILD_TOOLBAR, TRANSPORT_WATER);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CompanyID GetBestCompany(uint8 pp)
|
static CompanyID GetBestCompany(uint8 pp)
|
||||||
|
@ -713,6 +717,10 @@ static void NewVehicleAvailable(Engine *e)
|
||||||
SetDParam(0, GetEngineCategoryName(index));
|
SetDParam(0, GetEngineCategoryName(index));
|
||||||
SetDParam(1, index);
|
SetDParam(1, index);
|
||||||
AddNewsItem(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE, NS_NEW_VEHICLES, NR_ENGINE, index);
|
AddNewsItem(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE, NS_NEW_VEHICLES, NR_ENGINE, index);
|
||||||
|
|
||||||
|
/* Update the toolbar. */
|
||||||
|
if (e->type == VEH_ROAD) InvalidateWindowData(WC_BUILD_TOOLBAR, TRANSPORT_ROAD);
|
||||||
|
if (e->type == VEH_SHIP) InvalidateWindowData(WC_BUILD_TOOLBAR, TRANSPORT_WATER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnginesMonthlyLoop()
|
void EnginesMonthlyLoop()
|
||||||
|
|
|
@ -88,7 +88,6 @@ static void CleanupGeneration()
|
||||||
|
|
||||||
DeleteWindowById(WC_GENERATE_PROGRESS_WINDOW, 0);
|
DeleteWindowById(WC_GENERATE_PROGRESS_WINDOW, 0);
|
||||||
MarkWholeScreenDirty();
|
MarkWholeScreenDirty();
|
||||||
_genworld_mapgen_mutex->EndCritical();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -172,6 +171,7 @@ static void _GenerateWorld(void *)
|
||||||
IncreaseGeneratingWorldProgress(GWP_GAME_START);
|
IncreaseGeneratingWorldProgress(GWP_GAME_START);
|
||||||
|
|
||||||
CleanupGeneration();
|
CleanupGeneration();
|
||||||
|
_genworld_mapgen_mutex->EndCritical();
|
||||||
|
|
||||||
ShowNewGRFError();
|
ShowNewGRFError();
|
||||||
|
|
||||||
|
|
|
@ -413,11 +413,7 @@ struct BuildRoadToolbarWindow : Window {
|
||||||
RTW_ONE_WAY,
|
RTW_ONE_WAY,
|
||||||
WIDGET_LIST_END);
|
WIDGET_LIST_END);
|
||||||
|
|
||||||
this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_ROAD),
|
this->OnInvalidateData();
|
||||||
RTW_DEPOT,
|
|
||||||
RTW_BUS_STATION,
|
|
||||||
RTW_TRUCK_STATION,
|
|
||||||
WIDGET_LIST_END);
|
|
||||||
|
|
||||||
if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
|
if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
|
||||||
}
|
}
|
||||||
|
@ -427,6 +423,15 @@ struct BuildRoadToolbarWindow : Window {
|
||||||
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
|
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnInvalidateData(int data = 0)
|
||||||
|
{
|
||||||
|
this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_ROAD),
|
||||||
|
RTW_DEPOT,
|
||||||
|
RTW_BUS_STATION,
|
||||||
|
RTW_TRUCK_STATION,
|
||||||
|
WIDGET_LIST_END);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the remove button lowered state of the road toolbar
|
* Update the remove button lowered state of the road toolbar
|
||||||
*
|
*
|
||||||
|
|
|
@ -81,7 +81,7 @@ void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_wate
|
||||||
SetWaterClass(t, WATER_CLASS_INVALID);
|
SetWaterClass(t, WATER_CLASS_INVALID);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
NOT_REACHED();
|
SlErrorCorrupt("Invalid water class for dry tile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_wate
|
||||||
case WATER_CLASS_SEA: has_water = true; break;
|
case WATER_CLASS_SEA: has_water = true; break;
|
||||||
case WATER_CLASS_CANAL: has_canal = true; break;
|
case WATER_CLASS_CANAL: has_canal = true; break;
|
||||||
case WATER_CLASS_RIVER: has_river = true; break;
|
case WATER_CLASS_RIVER: has_river = true; break;
|
||||||
default: NOT_REACHED();
|
default: SlErrorCorrupt("Invalid water class for tile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -338,18 +338,25 @@ static void CDECL HandleSavegameLoadCrash(int signum)
|
||||||
|
|
||||||
char buffer[8192];
|
char buffer[8192];
|
||||||
char *p = buffer;
|
char *p = buffer;
|
||||||
|
p += seprintf(p, lastof(buffer), "Loading your savegame caused OpenTTD to crash.\n");
|
||||||
|
|
||||||
|
for (const GRFConfig *c = _grfconfig; !_saveload_crash_with_missing_newgrfs && c != NULL; c = c->next) {
|
||||||
|
_saveload_crash_with_missing_newgrfs = HasBit(c->flags, GCF_COMPATIBLE) || c->status == GCS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_saveload_crash_with_missing_newgrfs) {
|
||||||
p += seprintf(p, lastof(buffer),
|
p += seprintf(p, lastof(buffer),
|
||||||
"Loading your savegame caused OpenTTD to crash.\n"
|
"This is most likely caused by a missing NewGRF or a NewGRF that\n"
|
||||||
"This is most likely caused by a missing NewGRF or a NewGRF that has been\n"
|
"has been loaded as replacement for a missing NewGRF. OpenTTD\n"
|
||||||
"loaded as replacement for a missing NewGRF. OpenTTD cannot easily\n"
|
"cannot easily determine whether a replacement NewGRF is of a newer\n"
|
||||||
"determine whether a replacement NewGRF is of a newer or older version.\n"
|
"or older version.\n"
|
||||||
"It will load a NewGRF with the same GRF ID as the missing NewGRF. This\n"
|
"It will load a NewGRF with the same GRF ID as the missing NewGRF.\n"
|
||||||
"means that if the author makes incompatible NewGRFs with the same GRF ID\n"
|
"This means that if the author makes incompatible NewGRFs with the\n"
|
||||||
"OpenTTD cannot magically do the right thing. In most cases OpenTTD will\n"
|
"same GRF ID OpenTTD cannot magically do the right thing. In most\n"
|
||||||
"load the savegame and not crash, but this is an exception.\n"
|
"cases OpenTTD will load the savegame and not crash, but this is an\n"
|
||||||
"Please load the savegame with the appropriate NewGRFs. When loading a\n"
|
"exception.\n"
|
||||||
"savegame still crashes when all NewGRFs are found you should file a\n"
|
"Please load the savegame with the appropriate NewGRFs installed.\n"
|
||||||
"bug report. The missing NewGRFs are:\n");
|
"The missing/compatible NewGRFs are:\n");
|
||||||
|
|
||||||
for (const GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
|
for (const GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
|
||||||
if (HasBit(c->flags, GCF_COMPATIBLE)) {
|
if (HasBit(c->flags, GCF_COMPATIBLE)) {
|
||||||
|
@ -357,15 +364,18 @@ static void CDECL HandleSavegameLoadCrash(int signum)
|
||||||
char buf[40];
|
char buf[40];
|
||||||
md5sumToString(buf, lastof(buf), replaced->md5sum);
|
md5sumToString(buf, lastof(buf), replaced->md5sum);
|
||||||
p += seprintf(p, lastof(buffer), "NewGRF %08X (checksum %s) not found.\n Loaded NewGRF \"%s\" with same GRF ID instead.\n", BSWAP32(c->grfid), buf, c->filename);
|
p += seprintf(p, lastof(buffer), "NewGRF %08X (checksum %s) not found.\n Loaded NewGRF \"%s\" with same GRF ID instead.\n", BSWAP32(c->grfid), buf, c->filename);
|
||||||
_saveload_crash_with_missing_newgrfs = true;
|
|
||||||
}
|
}
|
||||||
if (c->status == GCS_NOT_FOUND) {
|
if (c->status == GCS_NOT_FOUND) {
|
||||||
char buf[40];
|
char buf[40];
|
||||||
md5sumToString(buf, lastof(buf), c->md5sum);
|
md5sumToString(buf, lastof(buf), c->md5sum);
|
||||||
p += seprintf(p, lastof(buffer), "NewGRF %08X (%s) not found; checksum %s.\n", BSWAP32(c->grfid), c->filename, buf);
|
p += seprintf(p, lastof(buffer), "NewGRF %08X (%s) not found; checksum %s.\n", BSWAP32(c->grfid), c->filename, buf);
|
||||||
_saveload_crash_with_missing_newgrfs = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
p += seprintf(p, lastof(buffer),
|
||||||
|
"This is probably caused by a corruption in the savegame.\n"
|
||||||
|
"Please file a bug report and attach this savegame.\n");
|
||||||
|
}
|
||||||
|
|
||||||
ShowInfo(buffer);
|
ShowInfo(buffer);
|
||||||
|
|
||||||
|
@ -840,7 +850,7 @@ bool AfterLoadGame()
|
||||||
case MP_ROAD:
|
case MP_ROAD:
|
||||||
SB(_m[t].m5, 6, 2, GB(_m[t].m5, 4, 2));
|
SB(_m[t].m5, 6, 2, GB(_m[t].m5, 4, 2));
|
||||||
switch (GetRoadTileType(t)) {
|
switch (GetRoadTileType(t)) {
|
||||||
default: NOT_REACHED();
|
default: SlErrorCorrupt("Invalid road tile type");
|
||||||
case ROAD_TILE_NORMAL:
|
case ROAD_TILE_NORMAL:
|
||||||
SB(_m[t].m4, 0, 4, GB(_m[t].m5, 0, 4));
|
SB(_m[t].m4, 0, 4, GB(_m[t].m5, 0, 4));
|
||||||
SB(_m[t].m4, 4, 4, 0);
|
SB(_m[t].m4, 4, 4, 0);
|
||||||
|
@ -881,7 +891,7 @@ bool AfterLoadGame()
|
||||||
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_me[t].m7, 5, 3));
|
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_me[t].m7, 5, 3));
|
||||||
SB(_me[t].m7, 5, 1, GB(_m[t].m3, 7, 1)); // snow/desert
|
SB(_me[t].m7, 5, 1, GB(_m[t].m3, 7, 1)); // snow/desert
|
||||||
switch (GetRoadTileType(t)) {
|
switch (GetRoadTileType(t)) {
|
||||||
default: NOT_REACHED();
|
default: SlErrorCorrupt("Invalid road tile type");
|
||||||
case ROAD_TILE_NORMAL:
|
case ROAD_TILE_NORMAL:
|
||||||
SB(_me[t].m7, 0, 4, GB(_m[t].m3, 0, 4)); // road works
|
SB(_me[t].m7, 0, 4, GB(_m[t].m3, 0, 4)); // road works
|
||||||
SB(_m[t].m6, 3, 3, GB(_m[t].m3, 4, 3)); // ground
|
SB(_m[t].m6, 3, 3, GB(_m[t].m3, 4, 3)); // ground
|
||||||
|
@ -1000,7 +1010,7 @@ bool AfterLoadGame()
|
||||||
|
|
||||||
if (dir != DirToDiagDir(v->direction)) continue;
|
if (dir != DirToDiagDir(v->direction)) continue;
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
default: NOT_REACHED();
|
default: SlErrorCorrupt("Invalid vehicle direction");
|
||||||
case DIAGDIR_NE: if ((v->x_pos & 0xF) != 0) continue; break;
|
case DIAGDIR_NE: if ((v->x_pos & 0xF) != 0) continue; break;
|
||||||
case DIAGDIR_SE: if ((v->y_pos & 0xF) != TILE_SIZE - 1) continue; break;
|
case DIAGDIR_SE: if ((v->y_pos & 0xF) != TILE_SIZE - 1) continue; break;
|
||||||
case DIAGDIR_SW: if ((v->x_pos & 0xF) != TILE_SIZE - 1) continue; break;
|
case DIAGDIR_SW: if ((v->x_pos & 0xF) != TILE_SIZE - 1) continue; break;
|
||||||
|
|
|
@ -178,7 +178,7 @@ static bool LoadObjects()
|
||||||
case SQSL_ARRAY_TABLE_END:
|
case SQSL_ARRAY_TABLE_END:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
default: NOT_REACHED();
|
default: SlErrorCorrupt("Invalid AI data type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1098,7 +1098,7 @@ static bool LoadOldVehicleUnion(LoadgameState *ls, int num)
|
||||||
res = LoadChunk(ls, NULL, vehicle_empty_chunk);
|
res = LoadChunk(ls, NULL, vehicle_empty_chunk);
|
||||||
} else {
|
} else {
|
||||||
switch (v->type) {
|
switch (v->type) {
|
||||||
default: NOT_REACHED();
|
default: SlErrorCorrupt("Invalid vehicle type");
|
||||||
case VEH_TRAIN : res = LoadChunk(ls, v, vehicle_train_chunk); break;
|
case VEH_TRAIN : res = LoadChunk(ls, v, vehicle_train_chunk); break;
|
||||||
case VEH_ROAD : res = LoadChunk(ls, v, vehicle_road_chunk); break;
|
case VEH_ROAD : res = LoadChunk(ls, v, vehicle_road_chunk); break;
|
||||||
case VEH_SHIP : res = LoadChunk(ls, v, vehicle_ship_chunk); break;
|
case VEH_SHIP : res = LoadChunk(ls, v, vehicle_ship_chunk); break;
|
||||||
|
@ -1298,7 +1298,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
|
||||||
} else {
|
} else {
|
||||||
/* Read the vehicle type and allocate the right vehicle */
|
/* Read the vehicle type and allocate the right vehicle */
|
||||||
switch (ReadByte(ls)) {
|
switch (ReadByte(ls)) {
|
||||||
default: NOT_REACHED();
|
default: SlErrorCorrupt("Invalid vehicle type");
|
||||||
case 0x00 /* VEH_INVALID */: v = NULL; break;
|
case 0x00 /* VEH_INVALID */: v = NULL; break;
|
||||||
case 0x10 /* VEH_TRAIN */: v = new (_current_vehicle_id) Train(); break;
|
case 0x10 /* VEH_TRAIN */: v = new (_current_vehicle_id) Train(); break;
|
||||||
case 0x11 /* VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break;
|
case 0x11 /* VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break;
|
||||||
|
|
|
@ -203,6 +203,18 @@ static void NORETURN SlError(StringID string, const char *extra_msg = NULL)
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error handler for corrupt savegames. Sets everything up to show the
|
||||||
|
* error message and to clean up the mess of a partial savegame load.
|
||||||
|
* @param msg Location the corruption has been spotted.
|
||||||
|
* @note This function does never return as it throws an exception to
|
||||||
|
* break out of all the saveload code.
|
||||||
|
*/
|
||||||
|
void NORETURN SlErrorCorrupt(const char *msg)
|
||||||
|
{
|
||||||
|
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
|
||||||
|
}
|
||||||
|
|
||||||
typedef void (*AsyncSaveFinishProc)();
|
typedef void (*AsyncSaveFinishProc)();
|
||||||
static AsyncSaveFinishProc _async_save_finish = NULL;
|
static AsyncSaveFinishProc _async_save_finish = NULL;
|
||||||
static ThreadObject *_save_thread;
|
static ThreadObject *_save_thread;
|
||||||
|
@ -242,7 +254,7 @@ void ProcessAsyncSaveFinish()
|
||||||
static void SlReadFill()
|
static void SlReadFill()
|
||||||
{
|
{
|
||||||
size_t len = _sl.read_bytes();
|
size_t len = _sl.read_bytes();
|
||||||
if (len == 0) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unexpected end of chunk");
|
if (len == 0) SlErrorCorrupt("Unexpected end of chunk");
|
||||||
|
|
||||||
_sl.bufp = _sl.buf;
|
_sl.bufp = _sl.buf;
|
||||||
_sl.bufe = _sl.buf + len;
|
_sl.bufe = _sl.buf + len;
|
||||||
|
@ -390,7 +402,7 @@ static uint SlReadSimpleGamma()
|
||||||
if (HasBit(i, 5)) {
|
if (HasBit(i, 5)) {
|
||||||
i &= ~0x20;
|
i &= ~0x20;
|
||||||
if (HasBit(i, 4))
|
if (HasBit(i, 4))
|
||||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unsupported gamma");
|
SlErrorCorrupt("Unsupported gamma");
|
||||||
i = (i << 8) | SlReadByte();
|
i = (i << 8) | SlReadByte();
|
||||||
}
|
}
|
||||||
i = (i << 8) | SlReadByte();
|
i = (i << 8) | SlReadByte();
|
||||||
|
@ -462,7 +474,7 @@ int SlIterateArray()
|
||||||
|
|
||||||
/* After reading in the whole array inside the loop
|
/* After reading in the whole array inside the loop
|
||||||
* we must have read in all the data, so we must be at end of current block. */
|
* we must have read in all the data, so we must be at end of current block. */
|
||||||
if (_next_offs != 0 && SlGetOffs() != _next_offs) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk size");
|
if (_next_offs != 0 && SlGetOffs() != _next_offs) SlErrorCorrupt("Invalid chunk size");
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
uint length = SlReadArrayLength();
|
uint length = SlReadArrayLength();
|
||||||
|
@ -1098,7 +1110,7 @@ void SlAutolength(AutolengthProc *proc, void *arg)
|
||||||
/* And write the stuff */
|
/* And write the stuff */
|
||||||
proc(arg);
|
proc(arg);
|
||||||
|
|
||||||
if (offs != SlGetOffs()) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk size");
|
if (offs != SlGetOffs()) SlErrorCorrupt("Invalid chunk size");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1130,9 +1142,9 @@ static void SlLoadChunk(const ChunkHandler *ch)
|
||||||
_sl.obj_len = len;
|
_sl.obj_len = len;
|
||||||
endoffs = SlGetOffs() + len;
|
endoffs = SlGetOffs() + len;
|
||||||
ch->load_proc();
|
ch->load_proc();
|
||||||
if (SlGetOffs() != endoffs) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk size");
|
if (SlGetOffs() != endoffs) SlErrorCorrupt("Invalid chunk size");
|
||||||
} else {
|
} else {
|
||||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk type");
|
SlErrorCorrupt("Invalid chunk type");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1216,7 +1228,7 @@ static void SlLoadChunks()
|
||||||
DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
|
DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
|
||||||
|
|
||||||
ch = SlFindChunkHandler(id);
|
ch = SlFindChunkHandler(id);
|
||||||
if (ch == NULL) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unknown chunk type");
|
if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
|
||||||
SlLoadChunk(ch);
|
SlLoadChunk(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1269,13 +1281,13 @@ static size_t ReadLZO()
|
||||||
size = TO_BE32(size);
|
size = TO_BE32(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size >= sizeof(out)) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Inconsistent size");
|
if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size");
|
||||||
|
|
||||||
/* Read block */
|
/* Read block */
|
||||||
if (fread(out + sizeof(uint32), size, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
|
if (fread(out + sizeof(uint32), size, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
|
||||||
|
|
||||||
/* Verify checksum */
|
/* Verify checksum */
|
||||||
if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Bad checksum");
|
if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
|
||||||
|
|
||||||
/* Decompress */
|
/* Decompress */
|
||||||
lzo1x_decompress(out + sizeof(uint32) * 1, size, _sl.buf, &len, NULL);
|
lzo1x_decompress(out + sizeof(uint32) * 1, size, _sl.buf, &len, NULL);
|
||||||
|
@ -1564,38 +1576,38 @@ static void *IntToReference(size_t index, SLRefType rt)
|
||||||
switch (rt) {
|
switch (rt) {
|
||||||
case REF_ORDERLIST:
|
case REF_ORDERLIST:
|
||||||
if (OrderList::IsValidID(index)) return OrderList::Get(index);
|
if (OrderList::IsValidID(index)) return OrderList::Get(index);
|
||||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid OrderList");
|
SlErrorCorrupt("Referencing invalid OrderList");
|
||||||
|
|
||||||
case REF_ORDER:
|
case REF_ORDER:
|
||||||
if (Order::IsValidID(index)) return Order::Get(index);
|
if (Order::IsValidID(index)) return Order::Get(index);
|
||||||
/* in old versions, invalid order was used to mark end of order list */
|
/* in old versions, invalid order was used to mark end of order list */
|
||||||
if (CheckSavegameVersionOldStyle(5, 2)) return NULL;
|
if (CheckSavegameVersionOldStyle(5, 2)) return NULL;
|
||||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Order");
|
SlErrorCorrupt("Referencing invalid Order");
|
||||||
|
|
||||||
case REF_VEHICLE_OLD:
|
case REF_VEHICLE_OLD:
|
||||||
case REF_VEHICLE:
|
case REF_VEHICLE:
|
||||||
if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
|
if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
|
||||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Vehicle");
|
SlErrorCorrupt("Referencing invalid Vehicle");
|
||||||
|
|
||||||
case REF_STATION:
|
case REF_STATION:
|
||||||
if (Station::IsValidID(index)) return Station::Get(index);
|
if (Station::IsValidID(index)) return Station::Get(index);
|
||||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Station");
|
SlErrorCorrupt("Referencing invalid Station");
|
||||||
|
|
||||||
case REF_TOWN:
|
case REF_TOWN:
|
||||||
if (Town::IsValidID(index)) return Town::Get(index);
|
if (Town::IsValidID(index)) return Town::Get(index);
|
||||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Town");
|
SlErrorCorrupt("Referencing invalid Town");
|
||||||
|
|
||||||
case REF_ROADSTOPS:
|
case REF_ROADSTOPS:
|
||||||
if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
|
if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
|
||||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid RoadStop");
|
SlErrorCorrupt("Referencing invalid RoadStop");
|
||||||
|
|
||||||
case REF_ENGINE_RENEWS:
|
case REF_ENGINE_RENEWS:
|
||||||
if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
|
if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
|
||||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid EngineRenew");
|
SlErrorCorrupt("Referencing invalid EngineRenew");
|
||||||
|
|
||||||
case REF_CARGO_PACKET:
|
case REF_CARGO_PACKET:
|
||||||
if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
|
if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
|
||||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid CargoPacket");
|
SlErrorCorrupt("Referencing invalid CargoPacket");
|
||||||
|
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -1766,7 +1778,7 @@ static SaveOrLoadResult SaveFileToDisk(bool threaded)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
if (_ts.count != _sl.offs_base) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unexpected size of chunk");
|
if (_ts.count != _sl.offs_base) SlErrorCorrupt("Unexpected size of chunk");
|
||||||
for (i = 0; i != _memory_savegame.Length() - 1; i++) {
|
for (i = 0; i != _memory_savegame.Length() - 1; i++) {
|
||||||
_sl.buf = _memory_savegame[i];
|
_sl.buf = _memory_savegame[i];
|
||||||
fmt->writer(MEMORY_CHUNK_SIZE);
|
fmt->writer(MEMORY_CHUNK_SIZE);
|
||||||
|
@ -1779,7 +1791,7 @@ static SaveOrLoadResult SaveFileToDisk(bool threaded)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt->uninit_write();
|
fmt->uninit_write();
|
||||||
if (_ts.count != _sl.offs_base) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unexpected size of chunk");
|
if (_ts.count != _sl.offs_base) SlErrorCorrupt("Unexpected size of chunk");
|
||||||
UnInitMem();
|
UnInitMem();
|
||||||
fclose(_sl.fh);
|
fclose(_sl.fh);
|
||||||
|
|
||||||
|
|
|
@ -333,6 +333,7 @@ void SlGlobList(const SaveLoadGlobVarList *sldg);
|
||||||
void SlArray(void *array, size_t length, VarType conv);
|
void SlArray(void *array, size_t length, VarType conv);
|
||||||
void SlObject(void *object, const SaveLoad *sld);
|
void SlObject(void *object, const SaveLoad *sld);
|
||||||
bool SlObjectMember(void *object, const SaveLoad *sld);
|
bool SlObjectMember(void *object, const SaveLoad *sld);
|
||||||
|
void NORETURN SlErrorCorrupt(const char *msg);
|
||||||
|
|
||||||
bool SaveloadCrashWithMissingNewGRFs();
|
bool SaveloadCrashWithMissingNewGRFs();
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ void ConvertOldMultiheadToNew()
|
||||||
u->SetWagon();
|
u->SetWagon();
|
||||||
u->SetFreeWagon();
|
u->SetFreeWagon();
|
||||||
break;
|
break;
|
||||||
default: NOT_REACHED();
|
default: SlErrorCorrupt("Invalid train subtype");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -716,7 +716,7 @@ void Load_VEHS()
|
||||||
case VEH_EFFECT: v = new (index) EffectVehicle(); break;
|
case VEH_EFFECT: v = new (index) EffectVehicle(); break;
|
||||||
case VEH_DISASTER: v = new (index) DisasterVehicle(); break;
|
case VEH_DISASTER: v = new (index) DisasterVehicle(); break;
|
||||||
case VEH_INVALID: // Savegame shouldn't contain invalid vehicles
|
case VEH_INVALID: // Savegame shouldn't contain invalid vehicles
|
||||||
default: NOT_REACHED();
|
default: SlErrorCorrupt("Invalid vehicle type");
|
||||||
}
|
}
|
||||||
|
|
||||||
SlObject(v, GetVehicleDescription(vtype));
|
SlObject(v, GetVehicleDescription(vtype));
|
||||||
|
|
|
@ -1424,19 +1424,29 @@ static const NWidgetPart _nested_smallmap_bar[] = {
|
||||||
NWidget(NWID_VERTICAL),
|
NWidget(NWID_VERTICAL),
|
||||||
/* Top button row. */
|
/* Top button row. */
|
||||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||||
NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_ZOOM_IN), SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
|
NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_ZOOM_IN),
|
||||||
NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_CENTERMAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER),
|
SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN), SetFill(1, 1),
|
||||||
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_CONTOUR), SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP),
|
NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_CENTERMAP),
|
||||||
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEHICLES), SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP),
|
SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER), SetFill(1, 1),
|
||||||
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_INDUSTRIES), SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP),
|
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_CONTOUR),
|
||||||
|
SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP), SetFill(1, 1),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEHICLES),
|
||||||
|
SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP), SetFill(1, 1),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_INDUSTRIES),
|
||||||
|
SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP), SetFill(1, 1),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
/* Bottom button row. */
|
/* Bottom button row. */
|
||||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||||
NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_ZOOM_OUT), SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
|
NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_ZOOM_OUT),
|
||||||
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_TOGGLETOWNNAME), SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF),
|
SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), SetFill(1, 1),
|
||||||
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_ROUTES), SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON),
|
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_TOGGLETOWNNAME),
|
||||||
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEGETATION), SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP),
|
SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF), SetFill(1, 1),
|
||||||
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_OWNERS), SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP),
|
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_ROUTES),
|
||||||
|
SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON), SetFill(1, 1),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEGETATION),
|
||||||
|
SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP), SetFill(1, 1),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_OWNERS),
|
||||||
|
SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP), SetFill(1, 1),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
NWidget(NWID_SPACER), SetResize(0, 1),
|
NWidget(NWID_SPACER), SetResize(0, 1),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
|
|
Loading…
Reference in New Issue