Analysis (probably the last stacktrace and the conclusion below it is the most interesting one):
Obviously, the intro game doesn´t know anything about more heightlevels. According to gdb, the game crashes in the first return statement of
Code: Select all
static inline uint TileHeight(TileIndex tile)
{
assert(tile < MapSize());
if (AllowMoreHeightlevels()) {
return _map_heightdata[tile].heightlevel;
} else {
return GB(_m[tile].type_height, 0, 4);
}
}
So, AllowMoreHeightlevels() returns true here. That function returns the setting _settings_game.construction.allow_more_heightlevels, so this setting is true here. That setting being true is the error, it should be false when loading a game without more heightlevels. Now, I wonder what I did wrong. First, settings.ini says
Code: Select all
[SDT_BOOL]
base = GameSettings
var = construction.allow_more_heightlevels
from = MORE_HEIGHTLEVEL_SAVEGAME_VERSION
to = SL_MAX_VERSION
guiflags = SGF_NO_NETWORK
def = false
str = STR_CONFIG_SETTING_MORE_HEIGHTLEVELS
proc = AfterChangeOfAllowMoreHeightlevels
Second, in AfterLoadGame(), I have the code
Code: Select all
if (IsSavegameVersionBefore(MORE_HEIGHTLEVEL_SAVEGAME_VERSION)) {
/* Maybe it is still filled from the previous game. If the currently loaded
* game was saved with an OpenTTD version where the allow more heightlevels
* patch was not yet introduced, we know for sure that it was NOT filled
* during SlLoadChunks (because no MAPH chunk can exist in such a savegame). */
free(_map_heightdata);
_map_heightdata = NULL;
/* Also, the default for such a game is that this patch is turned off.
* However, the player may turn it on using the menu afterwards. */
_settings_game.construction.allow_more_heightlevels = false;
}
And, MORE_HEIGHTLEVEL_SAVEGAME_VERSION is
Code: Select all
#define MORE_HEIGHTLEVEL_SAVEGAME_VERSION 250
So, allow_more_heightlevels is set correctly by AfterLoadGame. But, my stacktrace says:
Code: Select all
#0 0x0839a1fe in TileHeight (tile=8224, h=0xbffff0cc) at /home/wol/openttd/_trunk_test/src/tile_map.h:81
#1 GetTileSlope (tile=8224, h=0xbffff0cc) at /home/wol/openttd/_trunk_test/src/tile_map.cpp:69
#2 0x083c0e77 in GetSlopeZ_Trees (tile=8224, x=512, y=512) at /home/wol/openttd/_trunk_test/src/tree_cmd.cpp:522
#3 0x08264f6a in GetSlopeZ (x=512, y=512) at /home/wol/openttd/_trunk_test/src/landscape.cpp:281
#4 0x083e115f in InitializeWindowViewport (w=0xb23332a0, x=0, y=0, width=848, height=480, follow_flags=8224, zoom=ZOOM_LVL_BEGIN) at /home/wol/openttd/_trunk_test/src/viewport.cpp:213
#5 0x083f5a8f in NWidgetViewport::InitializeViewport (this=0xb2333310, w=0xb23332a0, follow_flags=8224, zoom=ZOOM_LVL_BEGIN) at /home/wol/openttd/_trunk_test/src/widget.cpp:1812
#6 0x08268486 in MainWindow () at /home/wol/openttd/_trunk_test/src/main_gui.cpp:250
#7 SetupColoursAndInitialWindow () at /home/wol/openttd/_trunk_test/src/main_gui.cpp:526
#8 0x082db83f in LoadIntroGame (load_newgrfs=<value optimized out>) at /home/wol/openttd/_trunk_test/src/openttd.cpp:280
#9 0x082dd5b6 in SwitchToMode (new_mode=SM_MENU) at /home/wol/openttd/_trunk_test/src/openttd.cpp:984
#10 0x0823c6ef in DrawDirtyBlocks () at /home/wol/openttd/_trunk_test/src/gfx.cpp:1571
#11 0x083fb01d in UpdateWindows () at /home/wol/openttd/_trunk_test/src/window.cpp:2456
#12 0x083df84a in VideoDriver_SDL::MainLoop (this=0x862d008) at /home/wol/openttd/_trunk_test/src/video/sdl_v.cpp:581
#13 0x082dcd51 in ttd_main (argc=1, argv=0xbffff534) at /home/wol/openttd/_trunk_test/src/openttd.cpp:727
#14 0x0813b928 in main (argc=1, argv=0xbffff534) at /home/wol/openttd/_trunk_test/src/os/unix/unix.cpp:266
So, TileHeight is called indirectly from SetupColoursAndInitialWindow, which is called just _above_ SaveOrLoad which triggers AfterLoadGame.
Now, my question to the experts is: Why? Why is TileHeight called before the game is loaded? Do I deal correctly with allow_more_heightlevels, do I make some other mistake, or is this some bug independent from more heightlevels?
(EDIT: Added missing lines of stacktrace. Looking on it again: Is it possible that the first call of LoadIntroGame generates a landscape, the second one (that stacktrace is apparently from another call of LoadIntroGame) reinitializes the allow_more_heightlevels variable for some reason, but leaves the map array as it is, and in this situation calling TileHeight is harmful?)