1
0
Fork 0

(svn r16355) [0.7] -Backport from trunk:

- Fix: Invalid read when OTTD savegame contains VEH_INVALID (r16353)
- Fix: Signal handler could end in endless loop (r16351)
- Fix: [NewGRF] When overriding 'original sounds', only allow overriding of the 'original sounds' and not any other that is already loaded (r16339)
- Fix: Desyncs when removing lots of stations/towns (r16329, r16328)
[0.7] -Cleanup: unify style of changelog
release/0.7
rubidium 2009-05-18 20:17:28 +00:00
parent ab7b117c50
commit 498e5989d1
15 changed files with 937 additions and 960 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2038,8 +2038,8 @@ static ChangeInfoResult SoundEffectChangeInfo(uint sid, int numinfo, int prop, b
case 0x0A: { // Override old sound case 0x0A: { // Override old sound
uint orig_sound = grf_load_byte(&buf); uint orig_sound = grf_load_byte(&buf);
if (orig_sound >= GetNumSounds()) { if (orig_sound >= ORIGINAL_SAMPLE_COUNT) {
grfmsg(1, "SoundEffectChangeInfo: Original sound %d not defined (max %d)", orig_sound, GetNumSounds()); grfmsg(1, "SoundEffectChangeInfo: Original sound %d not defined (max %d)", orig_sound, ORIGINAL_SAMPLE_COUNT);
} else { } else {
FileEntry *newfe = GetSound(sound); FileEntry *newfe = GetSound(sound);
FileEntry *oldfe = GetSound(orig_sound); FileEntry *oldfe = GetSound(orig_sound);

View File

@ -235,14 +235,41 @@ static bool InitializeWindowsAndCaches()
return true; return true;
} }
typedef void (CDECL *SignalHandlerPointer)(int);
static SignalHandlerPointer _prev_segfault = NULL;
static SignalHandlerPointer _prev_abort = NULL;
static void CDECL HandleSavegameLoadCrash(int signum);
/**
* Replaces signal handlers of SIGSEGV and SIGABRT
* and stores pointers to original handlers in memory.
*/
static void SetSignalHandlers()
{
_prev_segfault = signal(SIGSEGV, HandleSavegameLoadCrash);
_prev_abort = signal(SIGABRT, HandleSavegameLoadCrash);
}
/**
* Resets signal handlers back to original handlers.
*/
static void ResetSignalHandlers()
{
signal(SIGSEGV, _prev_segfault);
signal(SIGABRT, _prev_abort);
}
/** /**
* Signal handler used to give a user a more useful report for crashes during * Signal handler used to give a user a more useful report for crashes during
* the savegame loading process; especially when there's problems with the * the savegame loading process; especially when there's problems with the
* NewGRFs that are required by the savegame. * NewGRFs that are required by the savegame.
* @param unused well... unused * @param signum received signal
*/ */
void CDECL HandleSavegameLoadCrash(int unused) static void CDECL HandleSavegameLoadCrash(int signum)
{ {
ResetSignalHandlers();
char buffer[8192]; char buffer[8192];
char *p = buffer; char *p = buffer;
p += seprintf(p, lastof(buffer), p += seprintf(p, lastof(buffer),
@ -272,6 +299,9 @@ void CDECL HandleSavegameLoadCrash(int unused)
} }
ShowInfo(buffer); ShowInfo(buffer);
SignalHandlerPointer call = signum == SIGSEGV ? _prev_segfault : _prev_abort;
if (call != NULL) call(signum);
} }
/** /**
@ -322,9 +352,7 @@ static void FixOwnerOfRailTrack(TileIndex t)
bool AfterLoadGame() bool AfterLoadGame()
{ {
typedef void (CDECL *SignalHandlerPointer)(int); SetSignalHandlers();
SignalHandlerPointer prev_segfault = signal(SIGSEGV, HandleSavegameLoadCrash);
SignalHandlerPointer prev_abort = signal(SIGABRT, HandleSavegameLoadCrash);
TileIndex map_size = MapSize(); TileIndex map_size = MapSize();
Company *c; Company *c;
@ -433,8 +461,7 @@ bool AfterLoadGame()
if (_networking && gcf_res != GLC_ALL_GOOD) { if (_networking && gcf_res != GLC_ALL_GOOD) {
SetSaveLoadError(STR_NETWORK_ERR_CLIENT_NEWGRF_MISMATCH); SetSaveLoadError(STR_NETWORK_ERR_CLIENT_NEWGRF_MISMATCH);
/* Restore the signals */ /* Restore the signals */
signal(SIGSEGV, prev_segfault); ResetSignalHandlers();
signal(SIGABRT, prev_abort);
return false; return false;
} }
@ -486,8 +513,7 @@ bool AfterLoadGame()
if (_game_mode == GM_NORMAL && !ClosestTownFromTile(0, UINT_MAX)) { if (_game_mode == GM_NORMAL && !ClosestTownFromTile(0, UINT_MAX)) {
SetSaveLoadError(STR_NO_TOWN_IN_SCENARIO); SetSaveLoadError(STR_NO_TOWN_IN_SCENARIO);
/* Restore the signals */ /* Restore the signals */
signal(SIGSEGV, prev_segfault); ResetSignalHandlers();
signal(SIGABRT, prev_abort);
return false; return false;
} }
@ -550,8 +576,7 @@ bool AfterLoadGame()
SetStationGfx(t, gfx - 170 + GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET); SetStationGfx(t, gfx - 170 + GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET);
} else { } else {
/* Restore the signals */ /* Restore the signals */
signal(SIGSEGV, prev_segfault); ResetSignalHandlers();
signal(SIGABRT, prev_abort);
return false; return false;
} }
SB(_m[t].m6, 3, 3, st); SB(_m[t].m6, 3, 3, st);
@ -1801,8 +1826,7 @@ bool AfterLoadGame()
bool ret = InitializeWindowsAndCaches(); bool ret = InitializeWindowsAndCaches();
/* Restore the signals */ /* Restore the signals */
signal(SIGSEGV, prev_segfault); ResetSignalHandlers();
signal(SIGABRT, prev_abort);
return ret; return ret;
} }

View File

@ -65,17 +65,17 @@ static const SaveLoadGlobVarList _date_desc[] = {
SLEG_CONDVAR(_cur_tileloop_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), SLEG_CONDVAR(_cur_tileloop_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
SLEG_CONDVAR(_cur_tileloop_tile, SLE_UINT32, 6, SL_MAX_VERSION), SLEG_CONDVAR(_cur_tileloop_tile, SLE_UINT32, 6, SL_MAX_VERSION),
SLEG_VAR(_disaster_delay, SLE_UINT16), SLEG_VAR(_disaster_delay, SLE_UINT16),
SLEG_VAR(_station_tick_ctr, SLE_UINT16), SLE_CONDNULL(2, 0, 119),
SLEG_VAR(_random.state[0], SLE_UINT32), SLEG_VAR(_random.state[0], SLE_UINT32),
SLEG_VAR(_random.state[1], SLE_UINT32), SLEG_VAR(_random.state[1], SLE_UINT32),
SLEG_CONDVAR(_cur_town_ctr, SLE_FILE_U8 | SLE_VAR_U32, 0, 9), SLE_CONDNULL(1, 0, 9),
SLEG_CONDVAR(_cur_town_ctr, SLE_UINT32, 10, SL_MAX_VERSION), SLE_CONDNULL(4, 10, 119),
SLEG_VAR(_cur_company_tick_index, SLE_FILE_U8 | SLE_VAR_U32), SLEG_VAR(_cur_company_tick_index, SLE_FILE_U8 | SLE_VAR_U32),
SLEG_CONDVAR(_next_competitor_start, SLE_FILE_U16 | SLE_VAR_U32, 0, 108), SLEG_CONDVAR(_next_competitor_start, SLE_FILE_U16 | SLE_VAR_U32, 0, 108),
SLEG_CONDVAR(_next_competitor_start, SLE_UINT32, 109, SL_MAX_VERSION), SLEG_CONDVAR(_next_competitor_start, SLE_UINT32, 109, SL_MAX_VERSION),
SLEG_VAR(_trees_tick_ctr, SLE_UINT8), SLEG_VAR(_trees_tick_ctr, SLE_UINT8),
SLEG_CONDVAR(_pause_game, SLE_UINT8, 4, SL_MAX_VERSION), SLEG_CONDVAR(_pause_game, SLE_UINT8, 4, SL_MAX_VERSION),
SLEG_CONDVAR(_cur_town_iter, SLE_UINT32, 11, SL_MAX_VERSION), SLE_CONDNULL(4, 11, 119),
SLEG_END() SLEG_END()
}; };

View File

@ -1260,7 +1260,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
uint type = ReadByte(ls); uint type = ReadByte(ls);
switch (type) { switch (type) {
default: return false; default: return false;
case 0x00 /* VEH_INVALID */: v = new (_current_vehicle_id) InvalidVehicle(); break; case 0x00 /* VEH_INVALID */: v = new (_current_vehicle_id) InvalidVehicle(); break;
case 0x25 /* MONORAIL */: case 0x25 /* MONORAIL */:
case 0x20 /* VEH_TRAIN */: v = new (_current_vehicle_id) Train(); break; case 0x20 /* VEH_TRAIN */: v = new (_current_vehicle_id) Train(); break;
case 0x21 /* VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break; case 0x21 /* VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break;
@ -1583,7 +1583,6 @@ static bool LoadTTDPatchExtraChunks(LoadgameState *ls, int num)
} }
extern TileIndex _cur_tileloop_tile; extern TileIndex _cur_tileloop_tile;
static uint32 _old_cur_town_ctr;
static const OldChunks main_chunk[] = { static const OldChunks main_chunk[] = {
OCL_ASSERT( OC_TTD, 0 ), OCL_ASSERT( OC_TTD, 0 ),
OCL_ASSERT( OC_TTO, 0 ), OCL_ASSERT( OC_TTO, 0 ),
@ -1618,7 +1617,7 @@ static const OldChunks main_chunk[] = {
OCL_ASSERT( OC_TTD, 0x4B26 ), OCL_ASSERT( OC_TTD, 0x4B26 ),
OCL_ASSERT( OC_TTO, 0x3A20 ), OCL_ASSERT( OC_TTO, 0x3A20 ),
OCL_VAR ( OC_UINT32, 1, &_old_cur_town_ctr ), OCL_NULL( 4 ), ///< town counter, no longer in use
OCL_NULL( 2 ), ///< timer_counter, no longer in use OCL_NULL( 2 ), ///< timer_counter, no longer in use
OCL_NULL( 2 ), ///< land_code, no longer in use OCL_NULL( 2 ), ///< land_code, no longer in use
@ -1707,8 +1706,7 @@ static const OldChunks main_chunk[] = {
OCL_CNULL( OC_TTD, 144 ), ///< AI cargo-stuff, calculated in InitializeLandscapeVariables OCL_CNULL( OC_TTD, 144 ), ///< AI cargo-stuff, calculated in InitializeLandscapeVariables
OCL_NULL( 2 ), ///< Company indexes of companies, no longer in use OCL_NULL( 2 ), ///< Company indexes of companies, no longer in use
OCL_NULL( 1 ), ///< Station tick counter, no longer in use
OCL_VAR ( OC_FILE_U8 | OC_VAR_U16, 1, &_station_tick_ctr ),
OCL_VAR ( OC_UINT8, 1, &_settings_game.locale.currency ), OCL_VAR ( OC_UINT8, 1, &_settings_game.locale.currency ),
OCL_VAR ( OC_UINT8, 1, &_settings_game.locale.units ), OCL_VAR ( OC_UINT8, 1, &_settings_game.locale.units ),
@ -1775,9 +1773,6 @@ bool LoadTTDMain(LoadgameState *ls)
/* Fix some general stuff */ /* Fix some general stuff */
_settings_game.game_creation.landscape = _settings_game.game_creation.landscape & 0xF; _settings_game.game_creation.landscape = _settings_game.game_creation.landscape & 0xF;
/* Remap some pointers */
_cur_town_ctr = RemapTownIndex(_old_cur_town_ctr);
/* Fix the game to be compatible with OpenTTD */ /* Fix the game to be compatible with OpenTTD */
FixOldTowns(); FixOldTowns();
FixOldVehicles(); FixOldVehicles();
@ -1814,8 +1809,6 @@ bool LoadTTOMain(LoadgameState *ls)
_settings_game.game_creation.landscape = 0; _settings_game.game_creation.landscape = 0;
_trees_tick_ctr = 0xFF; _trees_tick_ctr = 0xFF;
_cur_town_ctr = RemapTownIndex(_old_cur_town_ctr);
if (!FixTTOMapArray() || !FixTTOEngines()) { if (!FixTTOMapArray() || !FixTTOEngines()) {
DEBUG(oldloader, 0, "Conversion failed"); DEBUG(oldloader, 0, "Conversion failed");
return false; return false;

View File

@ -195,9 +195,6 @@ static void Load_STNS()
SaveLoad_STNS(st); SaveLoad_STNS(st);
} }
/* This is to ensure all pointers are within the limits of _stations_size */
if (_station_tick_ctr > GetMaxStationIndex()) _station_tick_ctr = 0;
} }
static void Save_ROADSTOP() static void Save_ROADSTOP()

View File

@ -189,11 +189,6 @@ static void Load_TOWN()
_total_towns++; _total_towns++;
} }
/* This is to ensure all pointers are within the limits of
* the size of the TownPool */
if (_cur_town_ctr > GetMaxTownIndex())
_cur_town_ctr = 0;
} }
extern const ChunkHandler _town_chunk_handlers[] = { extern const ChunkHandler _town_chunk_handlers[] = {

View File

@ -698,7 +698,7 @@ void Load_VEHS()
case VEH_AIRCRAFT: v = new (index) Aircraft(); break; case VEH_AIRCRAFT: v = new (index) Aircraft(); break;
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: v = new (index) InvalidVehicle(); break; case VEH_INVALID: /* Savegame shouldn't contain invalid vehicles */
default: NOT_REACHED(); default: NOT_REACHED();
} }

View File

@ -20,9 +20,6 @@ MusicFileSettings msf;
/* Number of levels of panning per side */ /* Number of levels of panning per side */
#define PANNING_LEVELS 16 #define PANNING_LEVELS 16
/** The number of sounds in the original sample.cat */
static const uint ORIGINAL_SAMPLE_COUNT = 73;
static void OpenBankFile(const char *filename) static void OpenBankFile(const char *filename)
{ {
FileEntry *fe = CallocT<FileEntry>(ORIGINAL_SAMPLE_COUNT); FileEntry *fe = CallocT<FileEntry>(ORIGINAL_SAMPLE_COUNT);

View File

@ -110,4 +110,7 @@ enum SoundFx {
template <> struct EnumPropsT<SoundFx> : MakeEnumPropsT<SoundFx, byte, SND_BEGIN, SND_END, SND_END> {}; template <> struct EnumPropsT<SoundFx> : MakeEnumPropsT<SoundFx, byte, SND_BEGIN, SND_END, SND_END> {};
typedef TinyEnumT<SoundFx> SoundFxByte; typedef TinyEnumT<SoundFx> SoundFxByte;
/** The number of sounds in the original sample.cat */
static const uint ORIGINAL_SAMPLE_COUNT = 73;
#endif /* SOUND_TYPE_H */ #endif /* SOUND_TYPE_H */

View File

@ -2086,8 +2086,8 @@ bool HasStationInUse(StationID station, CompanyID company)
static CommandCost RemoveBuoy(Station *st, DoCommandFlag flags) static CommandCost RemoveBuoy(Station *st, DoCommandFlag flags)
{ {
/* XXX: strange stuff */ /* XXX: strange stuff, allow clearing as invalid company when clearing landscape */
if (!IsValidCompanyID(_current_company)) return_cmd_error(INVALID_STRING_ID); if (!IsValidCompanyID(_current_company) && !(flags & DC_BANKRUPT)) return_cmd_error(INVALID_STRING_ID);
TileIndex tile = st->dock_tile; TileIndex tile = st->dock_tile;
@ -2689,7 +2689,11 @@ static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, i
return VETSB_CONTINUE; return VETSB_CONTINUE;
} }
/* this function is called for one station each tick */ /**
* This function is called for each station once every 250 ticks.
* Not all stations will get the tick at the same time.
* @param st the station receiving the tick.
*/
static void StationHandleBigTick(Station *st) static void StationHandleBigTick(Station *st)
{ {
UpdateStationAcceptance(st, true); UpdateStationAcceptance(st, true);
@ -2829,11 +2833,6 @@ void OnTick_Station()
{ {
if (_game_mode == GM_EDITOR) return; if (_game_mode == GM_EDITOR) return;
uint i = _station_tick_ctr;
if (++_station_tick_ctr > GetMaxStationIndex()) _station_tick_ctr = 0;
if (IsValidStationID(i)) StationHandleBigTick(GetStation(i));
Station *st; Station *st;
FOR_ALL_STATIONS(st) { FOR_ALL_STATIONS(st) {
StationHandleSmallTick(st); StationHandleSmallTick(st);
@ -2842,6 +2841,7 @@ void OnTick_Station()
* Station index is included so that triggers are not all done * Station index is included so that triggers are not all done
* at the same time. */ * at the same time. */
if ((_tick_counter + st->index) % 250 == 0) { if ((_tick_counter + st->index) % 250 == 0) {
StationHandleBigTick(st);
StationAnimationTrigger(st, st->xy, STAT_ANIM_250_TICKS); StationAnimationTrigger(st, st->xy, STAT_ANIM_250_TICKS);
} }
} }
@ -3201,8 +3201,6 @@ void InitializeStations()
/* Clean the roadstop pool and create 1 block in it */ /* Clean the roadstop pool and create 1 block in it */
_RoadStop_pool.CleanPool(); _RoadStop_pool.CleanPool();
_RoadStop_pool.AddBlockToPool(); _RoadStop_pool.AddBlockToPool();
_station_tick_ctr = 0;
} }
static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new) static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new)

View File

@ -589,8 +589,8 @@ static void ResetLandscapeConfirmationCallback(Window *w, bool confirmed)
Station *st; Station *st;
FOR_ALL_STATIONS(st) { FOR_ALL_STATIONS(st) {
/* There can be buoys, remove them */ /* There can be buoys, remove them */
if (IsBuoyTile(st->xy)) DoCommand(st->xy, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); if (st->IsBuoy() && IsBuoyTile(st->xy)) DoCommand(st->xy, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
delete st; if (st->facilities == 0) delete st;
} }
/* The same for waypoints */ /* The same for waypoints */

View File

@ -352,8 +352,6 @@ Town *CalcClosestTownFromTile(TileIndex tile, uint threshold = UINT_MAX);
extern Town *_cleared_town; extern Town *_cleared_town;
extern int _cleared_town_rating; extern int _cleared_town_rating;
extern uint32 _cur_town_ctr;
extern uint32 _cur_town_iter;
void ResetHouses(); void ResetHouses();

View File

@ -683,17 +683,12 @@ void OnTick_Town()
{ {
if (_game_mode == GM_EDITOR) return; if (_game_mode == GM_EDITOR) return;
/* Make sure each town's tickhandler invocation frequency is about the Town *t;
* same - TOWN_GROWTH_FREQUENCY - independent on the number of towns. */ FOR_ALL_TOWNS(t) {
for (_cur_town_iter += GetMaxTownIndex() + 1; /* Run town tick at regular intervals, but not all at once. */
_cur_town_iter >= TOWN_GROWTH_FREQUENCY; if ((_tick_counter + t->index) % TOWN_GROWTH_FREQUENCY == 0) {
_cur_town_iter -= TOWN_GROWTH_FREQUENCY) { TownTickHandler(t);
uint32 i = _cur_town_ctr; }
if (++_cur_town_ctr > GetMaxTownIndex())
_cur_town_ctr = 0;
if (IsValidTownID(i)) TownTickHandler(GetTown(i));
} }
} }
@ -2751,8 +2746,6 @@ void InitializeTowns()
s->cargo_type = CT_INVALID; s->cargo_type = CT_INVALID;
} }
_cur_town_ctr = 0;
_cur_town_iter = 0;
_total_towns = 0; _total_towns = 0;
} }

View File

@ -18,10 +18,6 @@ VARDEF byte _age_cargo_skip_counter;
/* Also save scrollpos_x, scrollpos_y and zoom */ /* Also save scrollpos_x, scrollpos_y and zoom */
VARDEF uint16 _disaster_delay; VARDEF uint16 _disaster_delay;
/* Determines what station to operate on in the
* tick handler. */
VARDEF uint16 _station_tick_ctr;
/* Determines how often to run the tree loop */ /* Determines how often to run the tree loop */
VARDEF byte _trees_tick_ctr; VARDEF byte _trees_tick_ctr;