summaryrefslogtreecommitdiff
path: root/openttd.c
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2007-01-02 19:19:48 +0000
committerrubidium <rubidium@openttd.org>2007-01-02 19:19:48 +0000
commit66bbf336c6af7353ef0aeed58002c46543b30635 (patch)
treead4a63860df2626b22f77e7dac712e958bea54cb /openttd.c
parentccc0a3f4dbf58c005b22341ac8874252924690cd (diff)
downloadopenttd-66bbf336c6af7353ef0aeed58002c46543b30635.tar.xz
(svn r7759) -Merge: makefile rewrite. This merge features:
- A proper ./configure, so everything needs to be configured only once, not for every make. - Usage of makedepend when available. This greatly reduces the time needed for generating the dependencies. - A generator for all project files. There is a single file with sources, which is used to generate Makefiles and the project files for MSVC. - Proper support for OSX universal binaries. - Object files for non-MSVC compiles are also placed in separate directories, making is faster to switch between debug and release compiles and it does not touch the directory with the source files. - Functionality to make a bundle of all needed files for for example a nightly or distribution of a binary with all needed GRFs and language files. Note: as this merge moves almost all files, it is recommended to make a backup of your working copy before updating your working copy.
Diffstat (limited to 'openttd.c')
-rw-r--r--openttd.c1685
1 files changed, 0 insertions, 1685 deletions
diff --git a/openttd.c b/openttd.c
deleted file mode 100644
index 3f15a944e..000000000
--- a/openttd.c
+++ /dev/null
@@ -1,1685 +0,0 @@
-/* $Id$ */
-
-#include "stdafx.h"
-#include "string.h"
-#include "table/strings.h"
-#include "debug.h"
-#include "driver.h"
-#include "saveload.h"
-#include "strings.h"
-#include "map.h"
-#include "tile.h"
-#include "void_map.h"
-
-#define VARDEF
-#include "openttd.h"
-#include "bridge_map.h"
-#include "functions.h"
-#include "mixer.h"
-#include "spritecache.h"
-#include "strings.h"
-#include "gfx.h"
-#include "gfxinit.h"
-#include "gui.h"
-#include "station.h"
-#include "station_map.h"
-#include "town_map.h"
-#include "tunnel_map.h"
-#include "vehicle.h"
-#include "viewport.h"
-#include "window.h"
-#include "player.h"
-#include "command.h"
-#include "town.h"
-#include "industry.h"
-#include "news.h"
-#include "engine.h"
-#include "sound.h"
-#include "economy.h"
-#include "fileio.h"
-#include "hal.h"
-#include "airport.h"
-#include "console.h"
-#include "screenshot.h"
-#include "network/network.h"
-#include "signs.h"
-#include "depot.h"
-#include "waypoint.h"
-#include "ai/ai.h"
-#include "train.h"
-#include "yapf/yapf.h"
-#include "settings.h"
-#include "genworld.h"
-#include "date.h"
-#include "clear_map.h"
-#include "fontcache.h"
-#include "newgrf_config.h"
-
-#include "bridge_map.h"
-#include "clear_map.h"
-#include "rail_map.h"
-#include "road_map.h"
-#include "water_map.h"
-#include "industry_map.h"
-
-#include <stdarg.h>
-
-void CallLandscapeTick(void);
-void IncreaseDate(void);
-void DoPaletteAnimations(void);
-void MusicLoop(void);
-void ResetMusic(void);
-void InitializeStations(void);
-void DeleteAllPlayerStations(void);
-
-extern void SetDifficultyLevel(int mode, GameOptions *gm_opt);
-extern void DoStartupNewPlayer(bool is_ai);
-extern void ShowOSErrorBox(const char *buf);
-
-/* TODO: usrerror() for errors which are not of an internal nature but
- * caused by the user, i.e. missing files or fatal configuration errors.
- * Post-0.4.0 since Celestar doesn't want this in SVN before. --pasky */
-
-void CDECL error(const char *s, ...)
-{
- va_list va;
- char buf[512];
-
- va_start(va, s);
- vsnprintf(buf, lengthof(buf), s, va);
- va_end(va);
-
- ShowOSErrorBox(buf);
- if (_video_driver != NULL) _video_driver->stop();
-
- assert(0);
- exit(1);
-}
-
-void CDECL ShowInfoF(const char *str, ...)
-{
- va_list va;
- char buf[1024];
- va_start(va, str);
- vsnprintf(buf, lengthof(buf), str, va);
- va_end(va);
- ShowInfo(buf);
-}
-
-
-void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize)
-{
- FILE *in;
- byte *mem;
- size_t len;
-
- in = fopen(filename, "rb");
- if (in == NULL) return NULL;
-
- fseek(in, 0, SEEK_END);
- len = ftell(in);
- fseek(in, 0, SEEK_SET);
- if (len > maxsize || (mem = malloc(len + 1)) == NULL) {
- fclose(in);
- return NULL;
- }
- mem[len] = 0;
- if (fread(mem, len, 1, in) != 1) {
- fclose(in);
- free(mem);
- return NULL;
- }
- fclose(in);
-
- *lenp = len;
- return mem;
-}
-
-static void showhelp(void)
-{
- extern const char _openttd_revision[];
- char buf[4096], *p;
-
- p = buf;
-
- p += snprintf(p, lengthof(buf), "OpenTTD %s\n", _openttd_revision);
- p = strecpy(p,
- "\n"
- "\n"
- "Command line options:\n"
- " -v drv = Set video driver (see below)\n"
- " -s drv = Set sound driver (see below)\n"
- " -m drv = Set music driver (see below)\n"
- " -r res = Set resolution (for instance 800x600)\n"
- " -h = Display this help text\n"
- " -t year = Set starting year\n"
- " -d [[fac=]lvl[,...]]= Debug mode\n"
- " -e = Start Editor\n"
- " -g [savegame] = Start new/save game immediately\n"
- " -G seed = Set random seed\n"
- " -n [ip:port#player] = Start networkgame\n"
- " -D = Start dedicated server\n"
-#if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32)
- " -f = Fork into the background (dedicated only)\n"
-#endif
- " -i = Force to use the DOS palette\n"
- " (use this if you see a lot of pink)\n"
- " -c config_file = Use 'config_file' instead of 'openttd.cfg'\n"
- "\n",
- lastof(buf)
- );
-
- p = GetDriverList(p, lastof(buf));
-
- ShowInfo(buf);
-}
-
-
-typedef struct {
- char *opt;
- int numleft;
- char **argv;
- const char *options;
- char *cont;
-} MyGetOptData;
-
-static void MyGetOptInit(MyGetOptData *md, int argc, char **argv, const char *options)
-{
- md->cont = NULL;
- md->numleft = argc;
- md->argv = argv;
- md->options = options;
-}
-
-static int MyGetOpt(MyGetOptData *md)
-{
- char *s,*r,*t;
-
- s = md->cont;
- if (s != NULL)
- goto md_continue_here;
-
- for (;;) {
- if (--md->numleft < 0) return -1;
-
- s = *md->argv++;
- if (*s == '-') {
-md_continue_here:;
- s++;
- if (*s != 0) {
- // Found argument, try to locate it in options.
- if (*s == ':' || (r = strchr(md->options, *s)) == NULL) {
- // ERROR!
- return -2;
- }
- if (r[1] == ':') {
- // Item wants an argument. Check if the argument follows, or if it comes as a separate arg.
- if (!*(t = s + 1)) {
- // It comes as a separate arg. Check if out of args?
- if (--md->numleft < 0 || *(t = *md->argv) == '-') {
- // Check if item is optional?
- if (r[2] != ':')
- return -2;
- md->numleft++;
- t = NULL;
- } else {
- md->argv++;
- }
- }
- md->opt = t;
- md->cont = NULL;
- return *s;
- }
- md->opt = NULL;
- md->cont = s;
- return *s;
- }
- } else {
- // This is currently not supported.
- return -2;
- }
- }
-}
-
-
-static void ParseResolution(int res[2], const char *s)
-{
- char *t = strchr(s, 'x');
- if (t == NULL) {
- ShowInfoF("Invalid resolution '%s'", s);
- return;
- }
-
- res[0] = clamp(strtoul(s, NULL, 0), 64, MAX_SCREEN_WIDTH);
- res[1] = clamp(strtoul(t + 1, NULL, 0), 64, MAX_SCREEN_HEIGHT);
-}
-
-static void InitializeDynamicVariables(void)
-{
- /* Dynamic stuff needs to be initialized somewhere... */
- _town_sort = NULL;
- _industry_sort = NULL;
-}
-
-static void UnInitializeDynamicVariables(void)
-{
- /* Dynamic stuff needs to be free'd somewhere... */
- CleanPool(&_Town_pool);
- CleanPool(&_Industry_pool);
- CleanPool(&_Station_pool);
- CleanPool(&_Vehicle_pool);
- CleanPool(&_Sign_pool);
- CleanPool(&_Order_pool);
-
- free((void*)_town_sort);
- free((void*)_industry_sort);
-}
-
-static void UnInitializeGame(void)
-{
- UnInitWindowSystem();
-
- free(_config_file);
-}
-
-static void LoadIntroGame(void)
-{
- char filename[256];
-
- _game_mode = GM_MENU;
- CLRBITS(_display_opt, DO_TRANS_BUILDINGS); // don't make buildings transparent in intro
- _opt_ptr = &_opt_newgame;
- ResetGRFConfig(false);
-
- // Setup main window
- ResetWindowSystem();
- SetupColorsAndInitialWindow();
-
- // Generate a world.
- snprintf(filename, lengthof(filename), "%sopntitle.dat", _paths.data_dir);
-#if defined SECOND_DATA_DIR
- if (SaveOrLoad(filename, SL_LOAD) != SL_OK) {
- snprintf(filename, lengthof(filename), "%sopntitle.dat", _paths.second_data_dir);
- }
-#endif
- if (SaveOrLoad(filename, SL_LOAD) != SL_OK) {
- GenerateWorld(GW_EMPTY, 64, 64); // if failed loading, make empty world.
- WaitTillGeneratedWorld();
- }
-
- _pause = 0;
- SetLocalPlayer(0);
- /* Make sure you can't scroll in the menu */
- _scrolling_viewport = 0;
- _cursor.fix_at = false;
- MarkWholeScreenDirty();
-
- // Play main theme
- if (_music_driver->is_song_playing()) ResetMusic();
-}
-
-#if defined(UNIX) && !defined(__MORPHOS__)
-extern void DedicatedFork(void);
-#endif
-
-int ttd_main(int argc, char *argv[])
-{
- MyGetOptData mgo;
- int i;
- const char *optformat;
- char musicdriver[16], sounddriver[16], videodriver[16];
- int resolution[2] = {0,0};
- Year startyear = INVALID_YEAR;
- uint generation_seed = GENERATE_NEW_SEED;
- bool dedicated = false;
- bool network = false;
- char *network_conn = NULL;
-
- musicdriver[0] = sounddriver[0] = videodriver[0] = 0;
-
- _game_mode = GM_MENU;
- _switch_mode = SM_MENU;
- _switch_mode_errorstr = INVALID_STRING_ID;
- _dedicated_forks = false;
- _config_file = NULL;
-
- // The last param of the following function means this:
- // a letter means: it accepts that param (e.g.: -h)
- // a ':' behind it means: it need a param (e.g.: -m<driver>)
- // a '::' behind it means: it can optional have a param (e.g.: -d<debug>)
- optformat = "m:s:v:hDn::eit:d::r:g::G:c:"
-#if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32)
- "f"
-#endif
- ;
-
- MyGetOptInit(&mgo, argc-1, argv+1, optformat);
- while ((i = MyGetOpt(&mgo)) != -1) {
- switch (i) {
- case 'm': ttd_strlcpy(musicdriver, mgo.opt, sizeof(musicdriver)); break;
- case 's': ttd_strlcpy(sounddriver, mgo.opt, sizeof(sounddriver)); break;
- case 'v': ttd_strlcpy(videodriver, mgo.opt, sizeof(videodriver)); break;
- case 'D':
- strcpy(musicdriver, "null");
- strcpy(sounddriver, "null");
- strcpy(videodriver, "dedicated");
- dedicated = true;
- break;
- case 'f': _dedicated_forks = true; break;
- case 'n':
- network = true;
- network_conn = mgo.opt; // optional IP parameter, NULL if unset
- break;
- case 'r': ParseResolution(resolution, mgo.opt); break;
- case 't': startyear = atoi(mgo.opt); break;
- case 'd': {
-#if defined(WIN32)
- CreateConsole();
-#endif
- if (mgo.opt != NULL) SetDebugString(mgo.opt);
- } break;
- case 'e': _switch_mode = SM_EDITOR; break;
- case 'i': _use_dos_palette = true; break;
- case 'g':
- if (mgo.opt != NULL) {
- strcpy(_file_to_saveload.name, mgo.opt);
- _switch_mode = SM_LOAD;
- } else {
- _switch_mode = SM_NEWGAME;
- }
- break;
- case 'G': generation_seed = atoi(mgo.opt); break;
- case 'c': _config_file = strdup(mgo.opt); break;
- case -2:
- case 'h':
- showhelp();
- return 0;
- }
- }
-
- DeterminePaths();
- CheckExternalFiles();
-
-#if defined(UNIX) && !defined(__MORPHOS__)
- // We must fork here, or we'll end up without some resources we need (like sockets)
- if (_dedicated_forks)
- DedicatedFork();
-#endif
-
- LoadFromConfig();
- CheckConfig();
- LoadFromHighScore();
-
- // override config?
- if (musicdriver[0]) ttd_strlcpy(_ini_musicdriver, musicdriver, sizeof(_ini_musicdriver));
- if (sounddriver[0]) ttd_strlcpy(_ini_sounddriver, sounddriver, sizeof(_ini_sounddriver));
- if (videodriver[0]) ttd_strlcpy(_ini_videodriver, videodriver, sizeof(_ini_videodriver));
- if (resolution[0]) { _cur_resolution[0] = resolution[0]; _cur_resolution[1] = resolution[1]; }
- if (startyear != INVALID_YEAR) _patches_newgame.starting_year = startyear;
- if (generation_seed != GENERATE_NEW_SEED) _patches_newgame.generation_seed = generation_seed;
-
- if (_dedicated_forks && !dedicated) _dedicated_forks = false;
-
- // enumerate language files
- InitializeLanguagePacks();
-
- // initialize screenshot formats
- InitializeScreenshotFormats();
-
- // initialize airport state machines
- InitializeAirports();
-
- /* initialize all variables that are allocated dynamically */
- InitializeDynamicVariables();
-
- /* start the AI */
- AI_Initialize();
-
- // Sample catalogue
- DEBUG(misc, 1, "Loading sound effects...");
- MxInitialize(11025);
- SoundInitialize("sample.cat");
-
- /* Initialize FreeType */
- InitFreeType();
-
- // This must be done early, since functions use the InvalidateWindow* calls
- InitWindowSystem();
-
- /* Initialize game palette */
- GfxInitPalettes();
-
- DEBUG(driver, 1, "Loading drivers...");
- LoadDriver(SOUND_DRIVER, _ini_sounddriver);
- LoadDriver(MUSIC_DRIVER, _ini_musicdriver);
- LoadDriver(VIDEO_DRIVER, _ini_videodriver); // load video last, to prevent an empty window while sound and music loads
- _savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING;
-
- // restore saved music volume
- _music_driver->set_volume(msf.music_vol);
-
- NetworkStartUp(); // initialize network-core
-
- ScanNewGRFFiles();
-
- _opt_ptr = &_opt_newgame;
- ResetGRFConfig(false);
-
- /* XXX - ugly hack, if diff_level is 9, it means we got no setting from the config file */
- if (_opt_newgame.diff_level == 9) SetDifficultyLevel(0, &_opt_newgame);
-
- /* Make sure _patches is filled with _patches_newgame if we switch to a game directly */
- if (_switch_mode != SM_NONE) {
- _opt = _opt_newgame;
- UpdatePatches();
- }
-
- // initialize the ingame console
- IConsoleInit();
- _cursor.in_window = true;
- InitializeGUI();
- IConsoleCmdExec("exec scripts/autoexec.scr 0");
-
- GenerateWorld(GW_EMPTY, 64, 64); // Make the viewport initialization happy
- WaitTillGeneratedWorld();
-
-#ifdef ENABLE_NETWORK
- if (network && _network_available) {
- if (network_conn != NULL) {
- const char *port = NULL;
- const char *player = NULL;
- uint16 rport;
-
- rport = NETWORK_DEFAULT_PORT;
- _network_playas = PLAYER_NEW_COMPANY;
-
- ParseConnectionString(&player, &port, network_conn);
-
- if (player != NULL) {
- _network_playas = atoi(player);
-
- if (_network_playas != PLAYER_SPECTATOR) {
- _network_playas--;
- if (!IsValidPlayer(_network_playas)) return false;
- }
- }
- if (port != NULL) rport = atoi(port);
-
- LoadIntroGame();
- _switch_mode = SM_NONE;
- NetworkClientConnectGame(network_conn, rport);
- }
- }
-#endif /* ENABLE_NETWORK */
-
- _video_driver->main_loop();
-
- WaitTillSaved();
- IConsoleFree();
-
- if (_network_available) NetworkShutDown(); // Shut down the network and close any open connections
-
- _video_driver->stop();
- _music_driver->stop();
- _sound_driver->stop();
-
- SaveToConfig();
- SaveToHighScore();
-
- // uninitialize airport state machines
- UnInitializeAirports();
-
- /* uninitialize variables that are allocated dynamic */
- UnInitializeDynamicVariables();
-
- /* stop the AI */
- AI_Uninitialize();
-
- /* Close all and any open filehandles */
- FioCloseAll();
- UnInitializeGame();
-
- return 0;
-}
-
-void HandleExitGameRequest(void)
-{
- if (_game_mode == GM_MENU) { // do not ask to quit on the main screen
- _exit_game = true;
- } else if (_patches.autosave_on_exit) {
- DoExitSave();
- _exit_game = true;
- } else {
- AskExitGame();
- }
-}
-
-
-/** Mutex so that only one thread can communicate with the main program
- * at any given time */
-static ThreadMsg _message = MSG_OTTD_NO_MESSAGE;
-
-static inline void OTTD_ReleaseMutex(void) {_message = MSG_OTTD_NO_MESSAGE;}
-static inline ThreadMsg OTTD_PollThreadEvent(void) {return _message;}
-
-/** Called by running thread to execute some action in the main game.
- * It will stall as long as the mutex is not freed (handled) by the game */
-void OTTD_SendThreadMessage(ThreadMsg msg)
-{
- if (_exit_game) return;
- while (_message != MSG_OTTD_NO_MESSAGE) CSleep(10);
-
- _message = msg;
-}
-
-
-/** Handle the user-messages sent to us
- * @param message message sent
- */
-static void ProcessSentMessage(ThreadMsg message)
-{
- switch (message) {
- case MSG_OTTD_SAVETHREAD_DONE: SaveFileDone(); break;
- case MSG_OTTD_SAVETHREAD_ERROR: SaveFileError(); break;
- default: NOT_REACHED();
- }
-
- OTTD_ReleaseMutex(); // release mutex so that other threads, messages can be handled
-}
-
-static void ShowScreenshotResult(bool b)
-{
- if (b) {
- SetDParamStr(0, _screenshot_name);
- ShowErrorMessage(INVALID_STRING_ID, STR_031B_SCREENSHOT_SUCCESSFULLY, 0, 0);
- } else {
- ShowErrorMessage(INVALID_STRING_ID, STR_031C_SCREENSHOT_FAILED, 0, 0);
- }
-
-}
-
-static void MakeNewGameDone(void)
-{
- /* In a dedicated server, the server does not play */
- if (_network_dedicated) {
- SetLocalPlayer(PLAYER_SPECTATOR);
- return;
- }
-
- /* Create a single player */
- DoStartupNewPlayer(false);
-
- SetLocalPlayer(0);
- _current_player = _local_player;
- DoCommandP(0, (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, _patches.autorenew_money, NULL, CMD_SET_AUTOREPLACE);
-
- SettingsDisableElrail(_patches.disable_elrails);
-
- MarkWholeScreenDirty();
-}
-
-static void MakeNewGame(bool from_heightmap)
-{
- _game_mode = GM_NORMAL;
-
- ResetGRFConfig(true);
-
- GenerateWorldSetCallback(&MakeNewGameDone);
- GenerateWorld(from_heightmap ? GW_HEIGHTMAP : GW_NEWGAME, 1 << _patches.map_x, 1 << _patches.map_y);
-}
-
-static void MakeNewEditorWorldDone(void)
-{
- SetLocalPlayer(OWNER_NONE);
-
- MarkWholeScreenDirty();
-}
-
-static void MakeNewEditorWorld(void)
-{
- _game_mode = GM_EDITOR;
-
- ResetGRFConfig(true);
-
- GenerateWorldSetCallback(&MakeNewEditorWorldDone);
- GenerateWorld(GW_EMPTY, 1 << _patches.map_x, 1 << _patches.map_y);
-}
-
-void StartupPlayers(void);
-void StartupDisasters(void);
-extern void StartupEconomy(void);
-
-/**
- * Start Scenario starts a new game based on a scenario.
- * Eg 'New Game' --> select a preset scenario
- * This starts a scenario based on your current difficulty settings
- */
-static void StartScenario(void)
-{
- _game_mode = GM_NORMAL;
-
- // invalid type
- if (_file_to_saveload.mode == SL_INVALID) {
- DEBUG(sl, 0, "Savegame is obsolete or invalid format: '%s'", _file_to_saveload.name);
- ShowErrorMessage(INVALID_STRING_ID, STR_4009_GAME_LOAD_FAILED, 0, 0);
- _game_mode = GM_MENU;
- return;
- }
-
- // Reinitialize windows
- ResetWindowSystem();
-
- SetupColorsAndInitialWindow();
-
- ResetGRFConfig(true);
-
- // Load game
- if (SaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode) != SL_OK) {
- LoadIntroGame();
- ShowErrorMessage(INVALID_STRING_ID, STR_4009_GAME_LOAD_FAILED, 0, 0);
- }
-
- _opt_ptr = &_opt;
- _opt_ptr->diff = _opt_newgame.diff;
- _opt.diff_level = _opt_newgame.diff_level;
-
- // Inititalize data
- StartupEconomy();
- StartupPlayers();
- StartupEngines();
- StartupDisasters();
-
- SetLocalPlayer(0);
- _current_player = _local_player;
- DoCommandP(0, (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, _patches.autorenew_money, NULL, CMD_SET_AUTOREPLACE);
-
- MarkWholeScreenDirty();
-}
-
-bool SafeSaveOrLoad(const char *filename, int mode, int newgm)
-{
- byte ogm = _game_mode;
-
- _game_mode = newgm;
- switch (SaveOrLoad(filename, mode)) {
- case SL_OK: return true;
-
- case SL_REINIT:
- switch (ogm) {
- case GM_MENU: LoadIntroGame(); break;
- case GM_EDITOR: MakeNewEditorWorld(); break;
- default: MakeNewGame(false); break;
- }
- return false;
-
- default:
- _game_mode = ogm;
- return false;
- }
-}
-
-void SwitchMode(int new_mode)
-{
-#ifdef ENABLE_NETWORK
- // If we are saving something, the network stays in his current state
- if (new_mode != SM_SAVE) {
- // If the network is active, make it not-active
- if (_networking) {
- if (_network_server && (new_mode == SM_LOAD || new_mode == SM_NEWGAME)) {
- NetworkReboot();
- NetworkUDPClose();
- } else {
- NetworkDisconnect();
- NetworkUDPClose();
- }
- }
-
- // If we are a server, we restart the server
- if (_is_network_server) {
- // But not if we are going to the menu
- if (new_mode != SM_MENU) {
- NetworkServerStart();
- } else {
- // This client no longer wants to be a network-server
- _is_network_server = false;
- }
- }
- }
-#endif /* ENABLE_NETWORK */
-
- switch (new_mode) {
- case SM_EDITOR: /* Switch to scenario editor */
- MakeNewEditorWorld();
- break;
-
- case SM_NEWGAME: /* New Game --> 'Random game' */
-#ifdef ENABLE_NETWORK
- if (_network_server) {
- snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "Random Map");
- }
-#endif /* ENABLE_NETWORK */
- MakeNewGame(false);
- break;
-
- case SM_START_SCENARIO: /* New Game --> Choose one of the preset scenarios */
-#ifdef ENABLE_NETWORK
- if (_network_server) {
- snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Loaded scenario)", _file_to_saveload.title);
- }
-#endif /* ENABLE_NETWORK */
- StartScenario();
- break;
-
- case SM_LOAD: { /* Load game, Play Scenario */
- _opt_ptr = &_opt;
- ResetGRFConfig(true);
-
- if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL)) {
- LoadIntroGame();
- ShowErrorMessage(INVALID_STRING_ID, STR_4009_GAME_LOAD_FAILED, 0, 0);
- } else {
- /* Update the local player for a loaded game. It is either always
- * player #1 (eg 0) or in the case of a dedicated server a spectator */
- SetLocalPlayer(_network_dedicated ? PLAYER_SPECTATOR : 0);
- DoCommandP(0, 0, 0, NULL, CMD_PAUSE); // decrease pause counter (was increased from opening load dialog)
-#ifdef ENABLE_NETWORK
- if (_network_server) {
- snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Loaded game)", _file_to_saveload.title);
- }
-#endif /* ENABLE_NETWORK */
- }
- break;
- }
-
- case SM_START_HEIGHTMAP: /* Load a heightmap and start a new game from it */
-#ifdef ENABLE_NETWORK
- if (_network_server) {
- snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Heightmap)", _file_to_saveload.title);
- }
-#endif /* ENABLE_NETWORK */
- MakeNewGame(true);
- break;
-
- case SM_LOAD_HEIGHTMAP: /* Load heightmap from scenario editor */
- SetLocalPlayer(OWNER_NONE);
-
- GenerateWorld(GW_HEIGHTMAP, 1 << _patches.map_x, 1 << _patches.map_y);
- MarkWholeScreenDirty();
- break;
-
- case SM_LOAD_SCENARIO: { /* Load scenario from scenario editor */
- if (SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR)) {
- Player *p;
-
- _opt_ptr = &_opt;
-
- SetLocalPlayer(OWNER_NONE);
- _generating_world = true;
- /* Delete all players */
- FOR_ALL_PLAYERS(p) {
- if (p->is_active) {
- ChangeOwnershipOfPlayerItems(p->index, PLAYER_SPECTATOR);
- p->is_active = false;
- }
- }
- _generating_world = false;
- _patches_newgame.starting_year = _cur_year;
- // delete all stations owned by a player
- DeleteAllPlayerStations();
- } else {
- ShowErrorMessage(INVALID_STRING_ID, STR_4009_GAME_LOAD_FAILED, 0, 0);
- }
- break;
- }
-
- case SM_MENU: /* Switch to game intro menu */
- LoadIntroGame();
- break;
-
- case SM_SAVE: /* Save game */
- if (SaveOrLoad(_file_to_saveload.name, SL_SAVE) != SL_OK) {
- ShowErrorMessage(INVALID_STRING_ID, STR_4007_GAME_SAVE_FAILED, 0, 0);
- } else {
- DeleteWindowById(WC_SAVELOAD, 0);
- }
- break;
-
- case SM_GENRANDLAND: /* Generate random land within scenario editor */
- SetLocalPlayer(OWNER_NONE);
- GenerateWorld(GW_RANDOM, 1 << _patches.map_x, 1 << _patches.map_y);
- // XXX: set date
- MarkWholeScreenDirty();
- break;
- }
-
- if (_switch_mode_errorstr != INVALID_STRING_ID) {
- ShowErrorMessage(INVALID_STRING_ID, _switch_mode_errorstr, 0, 0);
- }
-}
-
-
-// State controlling game loop.
-// The state must not be changed from anywhere
-// but here.
-// That check is enforced in DoCommand.
-void StateGameLoop(void)
-{
- // dont execute the state loop during pause
- if (_pause) return;
- if (IsGeneratingWorld()) return;
-
- if (_game_mode == GM_EDITOR) {
- RunTileLoop();
- CallVehicleTicks();
- CallLandscapeTick();
- CallWindowTickEvent();
- NewsLoop();
- } else {
- // All these actions has to be done from OWNER_NONE
- // for multiplayer compatibility
- PlayerID p = _current_player;
- _current_player = OWNER_NONE;
-
- AnimateAnimatedTiles();
- IncreaseDate();
- RunTileLoop();
- CallVehicleTicks();
- CallLandscapeTick();
-
- AI_RunGameLoop();
-
- CallWindowTickEvent();
- NewsLoop();
- _current_player = p;
- }
-}
-
-static void DoAutosave(void)
-{
- char buf[200];
-
- if (_patches.keep_all_autosave && _local_player != PLAYER_SPECTATOR) {
- const Player *p = GetPlayer(_local_player);
- char* s = buf;
-
- s += snprintf(buf, lengthof(buf), "%s%s", _paths.autosave_dir, PATHSEP);
-
- SetDParam(0, p->name_1);
- SetDParam(1, p->name_2);
- SetDParam(2, _date);
- s = GetString(s, STR_4004, lastof(buf));
- strecpy(s, ".sav", lastof(buf));
- } else { /* generate a savegame name and number according to _patches.max_num_autosaves */
- snprintf(buf, lengthof(buf), "%s%sautosave%d.sav", _paths.autosave_dir, PATHSEP, _autosave_ctr);
-
- _autosave_ctr++;
- if (_autosave_ctr >= _patches.max_num_autosaves) {
- // we reached the limit for numbers of autosaves. We will start over
- _autosave_ctr = 0;
- }
- }
-
- DEBUG(sl, 2, "Autosaving to '%s'", buf);
- if (SaveOrLoad(buf, SL_SAVE) != SL_OK)
- ShowErrorMessage(INVALID_STRING_ID, STR_AUTOSAVE_FAILED, 0, 0);
-}
-
-static void ScrollMainViewport(int x, int y)
-{
- if (_game_mode != GM_MENU) {
- Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
- assert(w);
-
- WP(w,vp_d).scrollpos_x += x << w->viewport->zoom;
- WP(w,vp_d).scrollpos_y += y << w->viewport->zoom;
- }
-}
-
-static const int8 scrollamt[16][2] = {
- { 0, 0},
- {-2, 0}, // 1 : left
- { 0, -2}, // 2 : up
- {-2, -1}, // 3 : left + up
- { 2, 0}, // 4 : right
- { 0, 0}, // 5 : left + right
- { 2, -1}, // 6 : right + up
- { 0, -2}, // 7 : left + right + up = up
- { 0 ,2}, // 8 : down
- {-2 ,1}, // 9 : down+left
- { 0, 0}, // 10 : impossible
- {-2, 0}, // 11 : left + up + down = left
- { 2, 1}, // 12 : down+right
- { 0, 2}, // 13 : left + right + down = down
- { 0, -2}, // 14 : left + right + up = up
- { 0, 0}, // 15 : impossible
-};
-
-static void HandleKeyScrolling(void)
-{
- if (_dirkeys && !_no_scroll) {
- int factor = _shift_pressed ? 50 : 10;
- ScrollMainViewport(scrollamt[_dirkeys][0] * factor, scrollamt[_dirkeys][1] * factor);
- }
-}
-
-void GameLoop(void)
-{
- ThreadMsg message;
-
- if ((message = OTTD_PollThreadEvent()) != 0) ProcessSentMessage(message);
-
- // autosave game?
- if (_do_autosave) {
- _do_autosave = false;
- DoAutosave();
- RedrawAutosave();
- }
-
- // handle scrolling of the main window
- HandleKeyScrolling();
-
- // make a screenshot?
- if (IsScreenshotRequested()) ShowScreenshotResult(MakeScreenshot());
-
- // switch game mode?
- if (_switch_mode != SM_NONE) {
- SwitchMode(_switch_mode);
- _switch_mode = SM_NONE;
- }
-
- IncreaseSpriteLRU();
- InteractiveRandom();
-
- if (_scroller_click_timeout > 3) {
- _scroller_click_timeout -= 3;
- } else {
- _scroller_click_timeout = 0;
- }
-
- _caret_timer += 3;
- _timer_counter += 8;
- CursorTick();
-
-#ifdef ENABLE_NETWORK
- // Check for UDP stuff
- if (_network_available) NetworkUDPGameLoop();
-
- if (_networking && !IsGeneratingWorld()) {
- // Multiplayer
- NetworkGameLoop();
- } else {
- if (_network_reconnect > 0 && --_network_reconnect == 0) {
- // This means that we want to reconnect to the last host
- // We do this here, because it means that the network is really closed
- NetworkClientConnectGame(_network_last_host, _network_last_port);
- }
- // Singleplayer
- StateGameLoop();
- }
-#else
- StateGameLoop();
-#endif /* ENABLE_NETWORK */
-
- if (!_pause && _display_opt & DO_FULL_ANIMATION) DoPaletteAnimations();
-
- if (!_pause || _cheats.build_in_pause.value) MoveAllTextEffects();
-
- InputLoop();
-
- MusicLoop();
-}
-
-void BeforeSaveGame(void)
-{
- const Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
-
- if (w != NULL) {
- _saved_scrollpos_x = WP(w, const vp_d).scrollpos_x;
- _saved_scrollpos_y = WP(w, const vp_d).scrollpos_y;
- _saved_scrollpos_zoom = w->viewport->zoom;
- }
-}
-
-static void ConvertTownOwner(void)
-{
- TileIndex tile;
-
- for (tile = 0; tile != MapSize(); tile++) {
- switch (GetTileType(tile)) {
- case MP_STREET:
- if (IsLevelCrossing(tile) && GetCrossingRoadOwner(tile) & 0x80) {
- SetCrossingRoadOwner(tile, OWNER_TOWN);
- }
- /* FALLTHROUGH */
-
- case MP_TUNNELBRIDGE:
- if (GetTileOwner(tile) & 0x80) SetTileOwner(tile, OWNER_TOWN);
- break;
-
- default: break;
- }
- }
-}
-
-// before savegame version 4, the name of the company determined if it existed
-static void CheckIsPlayerActive(void)
-{
- Player *p;
-
- FOR_ALL_PLAYERS(p) {
- if (p->name_1 != 0) p->is_active = true;
- }
-}
-
-// since savegame version 4.1, exclusive transport rights are stored at towns
-static void UpdateExclusiveRights(void)
-{
- Town *t;
-
- FOR_ALL_TOWNS(t) {
- t->exclusivity = (byte)-1;
- }
-
- /* FIXME old exclusive rights status is not being imported (stored in s->blocked_months_obsolete)
- * could be implemented this way:
- * 1.) Go through all stations
- * Build an array town_blocked[ town_id ][ player_id ]
- * that stores if at least one station in that town is blocked for a player
- * 2.) Go through that array, if you find a town that is not blocked for
- * one player, but for all others, then give him exclusivity.
- */
-}
-
-static const byte convert_currency[] = {
- 0, 1, 12, 8, 3,
- 10, 14, 19, 4, 5,
- 9, 11, 13, 6, 17,
- 16, 22, 21, 7, 15,
- 18, 2, 20, };
-
-// since savegame version 4.2 the currencies are arranged differently
-static void UpdateCurrencies(void)
-{
- _opt.currency = convert_currency[_opt.currency];
-}
-
-/* Up to revision 1413 the invisible tiles at the southern border have not been
- * MP_VOID, even though they should have. This is fixed by this function
- */
-static void UpdateVoidTiles(void)
-{
- uint i;
-
- for (i = 0; i < MapMaxY(); ++i) MakeVoid(i * MapSizeX() + MapMaxX());
- for (i = 0; i < MapSizeX(); ++i) MakeVoid(MapSizeX() * MapMaxY() + i);
-}
-
-// since savegame version 6.0 each sign has an "owner", signs without owner (from old games are set to 255)
-static void UpdateSignOwner(void)
-{
- Sign *si;
-
- FOR_ALL_SIGNS(si) si->owner = OWNER_NONE;
-}
-
-extern void UpdateOldAircraft( void );
-extern void UpdateOilRig( void );
-
-
-static inline RailType UpdateRailType(RailType rt, RailType min)
-{
- return rt >= min ? (RailType)(rt + 1): rt;
-}
-
-bool AfterLoadGame(void)
-{
- Window *w;
- ViewPort *vp;
- Player *p;
-
- // in version 2.1 of the savegame, town owner was unified.
- if (CheckSavegameVersionOldStyle(2, 1)) ConvertTownOwner();
-
- // from version 4.1 of the savegame, exclusive rights are stored at towns
- if (CheckSavegameVersionOldStyle(4, 1)) UpdateExclusiveRights();
-
- // from version 4.2 of the savegame, currencies are in a different order
- if (CheckSavegameVersionOldStyle(4, 2)) UpdateCurrencies();
-
- // from version 6.1 of the savegame, signs have an "owner"
- if (CheckSavegameVersionOldStyle(6, 1)) UpdateSignOwner();
-
- /* In old version there seems to be a problem that water is owned by
- OWNER_NONE, not OWNER_WATER.. I can't replicate it for the current
- (4.3) version, so I just check when versions are older, and then
- walk through the whole map.. */
- if (CheckSavegameVersionOldStyle(4, 3)) {
- TileIndex tile = TileXY(0, 0);
- uint w = MapSizeX();
- uint h = MapSizeY();
-
- BEGIN_TILE_LOOP(tile_cur, w, h, tile)
- if (IsTileType(tile_cur, MP_WATER) && GetTileOwner(tile_cur) >= MAX_PLAYERS)
- SetTileOwner(tile_cur, OWNER_WATER);
- END_TILE_LOOP(tile_cur, w, h, tile)
- }
-
- // convert road side to my format.
- if (_opt.road_side) _opt.road_side = 1;
-
- /* Check all NewGRFs are present */
- if (!IsGoodGRFConfigList()) return false;
-
- /* Update current year
- * must be done before loading sprites as some newgrfs check it */
- SetDate(_date);
-
- // Load the sprites
- GfxLoadSprites();
- LoadStringWidthTable();
-
- /* Connect front and rear engines of multiheaded trains and converts
- * subtype to the new format */
- if (CheckSavegameVersionOldStyle(17, 1)) ConvertOldMultiheadToNew();
-
- /* Connect front and rear engines of multiheaded trains */
- ConnectMultiheadedTrains();
-
- // reinit the landscape variables (landscape might have changed)
- InitializeLandscapeVariables(true);
-
- // Update all vehicles
- AfterLoadVehicles();
-
- // Update all waypoints
- if (CheckSavegameVersion(12)) FixOldWaypoints();
-
- UpdateAllWaypointSigns();
-
- // in version 2.2 of the savegame, we have new airports
- if (CheckSavegameVersionOldStyle(2, 2)) UpdateOldAircraft();
-
- UpdateAllStationVirtCoord();
-
- // Setup town coords
- AfterLoadTown();
- UpdateAllSignVirtCoords();
-
- // make sure there is a town in the game
- if (_game_mode == GM_NORMAL && !ClosestTownFromTile(0, (uint)-1)) {
- _error_message = STR_NO_TOWN_IN_SCENARIO;
- return false;
- }
-
- // Initialize windows
- ResetWindowSystem();
- SetupColorsAndInitialWindow();
-
- w = FindWindowById(WC_MAIN_WINDOW, 0);
-
- WP(w,vp_d).scrollpos_x = _saved_scrollpos_x;
- WP(w,vp_d).scrollpos_y = _saved_scrollpos_y;
-
- vp = w->viewport;
- vp->zoom = _saved_scrollpos_zoom;
- vp->virtual_width = vp->width << vp->zoom;
- vp->virtual_height = vp->height << vp->zoom;
-
- // in version 4.1 of the savegame, is_active was introduced to determine
- // if a player does exist, rather then checking name_1
- if (CheckSavegameVersionOldStyle(4, 1)) CheckIsPlayerActive();
-
- // the void tiles on the southern border used to belong to a wrong class (pre 4.3).
- if (CheckSavegameVersionOldStyle(4, 3)) UpdateVoidTiles();
-
- // If Load Scenario / New (Scenario) Game is used,
- // a player does not exist yet. So create one here.
- // 1 exeption: network-games. Those can have 0 players
- // But this exeption is not true for network_servers!
- if (!_players[0].is_active && (!_networking || (_networking && _network_server)))
- DoStartupNewPlayer(false);
-
- DoZoomInOutWindow(ZOOM_NONE, w); // update button status
- MarkWholeScreenDirty();
-
- // In 5.1, Oilrigs have been moved (again)
- if (CheckSavegameVersionOldStyle(5, 1)) UpdateOilRig();
-
- /* In version 6.1 we put the town index in the map-array. To do this, we need
- * to use m2 (16bit big), so we need to clean m2, and that is where this is
- * all about ;) */
- if (CheckSavegameVersionOldStyle(6, 1)) {
- BEGIN_TILE_LOOP(tile, MapSizeX(), MapSizeY(), 0) {
- switch (GetTileType(tile)) {
- case MP_HOUSE:
- _m[tile].m4 = _m[tile].m2;
- SetTownIndex(tile, CalcClosestTownFromTile(tile, (uint)-1)->index);
- break;
-
- case MP_STREET:
- _m[tile].m4 |= (_m[tile].m2 << 4);
- if (IsTileOwner(tile, OWNER_TOWN)) {
- SetTownIndex(tile, CalcClosestTownFromTile(tile, (uint)-1)->index);
- } else {
- SetTownIndex(tile, 0);
- }
- break;
-
- default: break;
- }
- } END_TILE_LOOP(tile, MapSizeX(), MapSizeY(), 0);
- }
-
- /* From version 9.0, we update the max passengers of a town (was sometimes negative
- * before that. */
- if (CheckSavegameVersion(9)) {
- Town *t;
- FOR_ALL_TOWNS(t) UpdateTownMaxPass(t);
- }
-
- /* From version 16.0, we included autorenew on engines, which are now saved, but
- * of course, we do need to initialize them for older savegames. */
- if (CheckSavegameVersion(16)) {
- FOR_ALL_PLAYERS(p) {
- p->engine_renew_list = NULL;
- p->engine_renew = false;
- p->engine_renew_months = -6;
- p->engine_renew_money = 100000;
- }
-
- /* When loading a game, _local_player is not yet set to the correct value.
- * However, in a dedicated server we are a spectator, so nothing needs to
- * happen. In case we are not a dedicated server, the local player always
- * becomes player 0, unless we are in the scenario editor where all the
- * players are 'invalid'.
- */
- if (!_network_dedicated && IsValidPlayer(0)) {
- p = GetPlayer(0);
- p->engine_renew = _patches.autorenew;
- p->engine_renew_months = _patches.autorenew_months;
- p->engine_renew_money = _patches.autorenew_money;
- }
- }
-
- if (CheckSavegameVersion(42)) {
- TileIndex map_end = MapSize();
- TileIndex tile;
- Vehicle* v;
-
- for (tile = 0; tile != map_end; tile++) {
- if (MayHaveBridgeAbove(tile)) ClearBridgeMiddle(tile);
- if (IsBridgeTile(tile)) {
- if (HASBIT(_m[tile].m5, 6)) { // middle part
- Axis axis = (Axis)GB(_m[tile].m5, 0, 1);
-
- if (HASBIT(_m[tile].m5, 5)) { // transport route under bridge?
- if (GB(_m[tile].m5, 3, 2) == TRANSPORT_RAIL) {
- MakeRailNormal(
- tile,
- GetTileOwner(tile),
- axis == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X,
- GetRailType(tile)
- );
- } else {
- TownID town = IsTileOwner(tile, OWNER_TOWN) ? ClosestTownFromTile(tile, (uint)-1)->index : 0;
-
- MakeRoadNormal(
- tile,
- GetTileOwner(tile),
- axis == AXIS_X ? ROAD_Y : ROAD_X,
- town
- );
- }
- } else {
- if (GB(_m[tile].m5, 3, 2) == 0) {
- MakeClear(tile, CLEAR_GRASS, 3);
- } else {
- MakeCanal(tile, GetTileOwner(tile));
- }
- }
- SetBridgeMiddle(tile, axis);
- } else { // ramp
- Axis axis = (Axis)GB(_m[tile].m5, 0, 1);
- uint north_south = GB(_m[tile].m5, 5, 1);
- DiagDirection dir = ReverseDiagDir(XYNSToDiagDir(axis, north_south));
- TransportType type = (TransportType)GB(_m[tile].m5, 1, 2);
-
- _m[tile].m5 = 1 << 7 | type << 2 | dir;
- }
- }
- }
-
- FOR_ALL_VEHICLES(v) {
- if (v->type != VEH_Train && v->type != VEH_Road) continue;
- if (IsBridgeTile(v->tile)) {
- DiagDirection dir = GetBridgeRampDirection(v->tile);
-
- if (dir != DirToDiagDir(v->direction)) continue;
- switch (dir) {
- default: NOT_REACHED();
- 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_SW: if ((v->x_pos & 0xF) != TILE_SIZE - 1) continue; break;
- case DIAGDIR_NW: if ((v->y_pos & 0xF) != 0) continue; break;
- }
- } else if (v->z_pos > GetSlopeZ(v->x_pos, v->y_pos)) {
- v->tile = GetNorthernBridgeEnd(v->tile);
- } else {
- continue;
- }
- if (v->type == VEH_Train) {
- v->u.rail.track = 0x40;
- } else {
- v->u.road.state = 0xFF;
- }
- }
- }
-
- /* Elrails got added in rev 24 */
- if (CheckSavegameVersion(24)) {
- Vehicle *v;
- uint i;
- TileIndex t;
- RailType min_rail = RAILTYPE_ELECTRIC;
-
- for (i = 0; i < lengthof(_engines); i++) {
- Engine *e = GetEngine(i);
- if (e->type == VEH_Train &&
- (e->railtype != RAILTYPE_RAIL || RailVehInfo(i)->engclass == 2)) {
- e->railtype++;
- }
- }
-
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_Train) {
- RailType rt = GetEngine(v->engine_type)->railtype;
-
- v->u.rail.railtype = rt;
- if (rt == RAILTYPE_ELECTRIC) min_rail = RAILTYPE_RAIL;
- }
- }
-
- /* .. so we convert the entire map from normal to elrail (so maintain "fairness") */
- for (t = 0; t < MapSize(); t++) {
- switch (GetTileType(t)) {
- case MP_RAILWAY:
- SetRailType(t, UpdateRailType(GetRailType(t), min_rail));
- break;
-
- case MP_STREET:
- if (IsLevelCrossing(t)) {
- SetRailTypeCrossing(t, UpdateRailType(GetRailTypeCrossing(t), min_rail));
- }
- break;
-
- case MP_STATION:
- if (IsRailwayStation(t)) {
- SetRailType(t, UpdateRailType(GetRailType(t), min_rail));
- }
- break;
-
- case MP_TUNNELBRIDGE:
- if (IsTunnel(t)) {
- if (GetTunnelTransportType(t) == TRANSPORT_RAIL) {
- SetRailType(t, UpdateRailType(GetRailType(t), min_rail));
- }
- } else {
- if (GetBridgeTransportType(t) == TRANSPORT_RAIL) {
- SetRailType(t, UpdateRailType(GetRailType(t), min_rail));
- }
- }
- break;
-
- default:
- break;
- }
- }
-
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_Train && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged(v);
- }
-
- }
-
- /* In version 16.1 of the savegame a player can decide if trains, which get
- * replaced, shall keep their old length. In all prior versions, just default
- * to false */
- if (CheckSavegameVersionOldStyle(16, 1)) {
- FOR_ALL_PLAYERS(p) p->renew_keep_length = false;
- }
-
- /* In version 17, ground type is moved from m2 to m4 for depots and
- * waypoints to make way for storing the index in m2. The custom graphics
- * id which was stored in m4 is now saved as a grf/id reference in the
- * waypoint struct. */
- if (CheckSavegameVersion(17)) {
- Waypoint *wp;
-
- FOR_ALL_WAYPOINTS(wp) {
- if (wp->deleted == 0) {
- const StationSpec *statspec = NULL;
-
- if (HASBIT(_m[wp->xy].m3, 4))
- statspec = GetCustomStationSpec(STAT_CLASS_WAYP, _m[wp->xy].m4 + 1);
-
- if (statspec != NULL) {
- wp->stat_id = _m[wp->xy].m4 + 1;
- wp->grfid = statspec->grfid;
- wp->localidx = statspec->localidx;
- } else {
- // No custom graphics set, so set to default.
- wp->stat_id = 0;
- wp->grfid = 0;
- wp->localidx = 0;
- }
-
- // Move ground type bits from m2 to m4.
- _m[wp->xy].m4 = GB(_m[wp->xy].m2, 0, 4);
- // Store waypoint index in the tile.
- _m[wp->xy].m2 = wp->index;
- }
- }
- } else {
- /* As of version 17, we recalculate the custom graphic ID of waypoints
- * from the GRF ID / station index. */
- AfterLoadWaypoints();
- }
-
- /* From version 15, we moved a semaphore bit from bit 2 to bit 3 in m4, making
- * room for PBS. Now in version 21 move it back :P. */
- if (CheckSavegameVersion(21) && !CheckSavegameVersion(15)) {
- BEGIN_TILE_LOOP(tile, MapSizeX(), MapSizeY(), 0) {
- if (IsTileType(tile, MP_RAILWAY)) {
- if (HasSignals(tile)) {
- // convert PBS signals to combo-signals
- if (HASBIT(_m[tile].m4, 2)) SetSignalType(tile, SIGTYPE_COMBO);
-
- // move the signal variant back
- SetSignalVariant(tile, HASBIT(_m[tile].m4, 3) ? SIG_SEMAPHORE : SIG_ELECTRIC);
- CLRBIT(_m[tile].m4, 3);
- }
-
- // Clear PBS reservation on track
- if (!IsTileDepotType(tile, TRANSPORT_RAIL)) {
- SB(_m[tile].m4, 4, 4, 0);
- } else {
- CLRBIT(_m[tile].m3, 6);
- }
- }
-
- // Clear PBS reservation on crossing
- if (IsTileType(tile, MP_STREET) && IsLevelCrossing(tile))
- CLRBIT(_m[tile].m5, 0);
-
- // Clear PBS reservation on station
- if (IsTileType(tile, MP_STATION))
- CLRBIT(_m[tile].m3, 6);
- } END_TILE_LOOP(tile, MapSizeX(), MapSizeY(), 0);
- }
-
- if (CheckSavegameVersion(22)) UpdatePatches();
-
- if (CheckSavegameVersion(25)) {
- Vehicle *v;
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_Road) {
- v->vehstatus &= ~0x40;
- v->u.road.slot = NULL;
- v->u.road.slot_age = 0;
- }
- }
- }
-
- if (CheckSavegameVersion(26)) {
- Station *st;
- FOR_ALL_STATIONS(st) {
- st->last_vehicle_type = VEH_Invalid;
- }
- }
-
- YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
-
- if (CheckSavegameVersion(34)) FOR_ALL_PLAYERS(p) ResetPlayerLivery(p);
-
- FOR_ALL_PLAYERS(p) p->avail_railtypes = GetPlayerRailtypes(p->index);
-
- if (!CheckSavegameVersion(27)) AfterLoadStations();
-
- {
- /* Set up the engine count for all players */
- Player *players[MAX_PLAYERS];
- int i;
- const Vehicle *v;
-
- for (i = 0; i < MAX_PLAYERS; i++) players[i] = GetPlayer(i);
-
- FOR_ALL_VEHICLES(v) {
- if (!IsEngineCountable(v)) continue;
- players[v->owner]->num_engines[v->engine_type]++;
- }
- }
-
- /* Time starts at 0 instead of 1920.
- * Account for this in older games by adding an offset */
- if (CheckSavegameVersion(31)) {
- Station *st;
- Waypoint *wp;
- Engine *e;
- Player *player;
- Industry *i;
- Vehicle *v;
-
- _date += DAYS_TILL_ORIGINAL_BASE_YEAR;
- _cur_year += ORIGINAL_BASE_YEAR;
-
- FOR_ALL_STATIONS(st) st->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
- FOR_ALL_WAYPOINTS(wp) wp->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
- FOR_ALL_ENGINES(e) e->intro_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
- FOR_ALL_PLAYERS(player) player->inaugurated_year += ORIGINAL_BASE_YEAR;
- FOR_ALL_INDUSTRIES(i) i->last_prod_year += ORIGINAL_BASE_YEAR;
-
- FOR_ALL_VEHICLES(v) {
- v->date_of_last_service += DAYS_TILL_ORIGINAL_BASE_YEAR;
- v->build_year += ORIGINAL_BASE_YEAR;
- }
- }
-
- /* From 32 on we save the industry who made the farmland.
- * To give this prettyness to old savegames, we remove all farmfields and
- * plant new ones. */
- if (CheckSavegameVersion(32)) {
- Industry *i;
-
- BEGIN_TILE_LOOP(tile_cur, MapSizeX(), MapSizeY(), 0) {
- if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS)) {
- MakeClear(tile_cur, CLEAR_GRASS, 3);
- }
- } END_TILE_LOOP(tile_cur, MapSizeX(), MapSizeY(), 0)
-
- FOR_ALL_INDUSTRIES(i) {
- uint j;
-
- if (i->type == IT_FARM || i->type == IT_FARM_2) {
- for (j = 0; j != 50; j++) PlantRandomFarmField(i);
- }
- }
- }
-
- /* Setting no refit flags to all orders in savegames from before refit in orders were added */
- if (CheckSavegameVersion(36)) {
- Order *order;
- Vehicle *v;
-
- FOR_ALL_ORDERS(order) {
- order->refit_cargo = CT_NO_REFIT;
- order->refit_subtype = CT_NO_REFIT;
- }
-
- FOR_ALL_VEHICLES(v) {
- v->current_order.refit_cargo = CT_NO_REFIT;
- v->current_order.refit_subtype = CT_NO_REFIT;
- }
- }
-
- if (CheckSavegameVersion(37)) {
- ConvertNameArray();
- }
-
- /* from version 38 we have optional elrails, since we cannot know the
- * preference of a user, let elrails enabled; it can be disabled manually */
- if (CheckSavegameVersion(38)) {
- _patches.disable_elrails = false; // enable elrails
- /* do the same as when elrails were enabled/disabled manually just now */
- SettingsDisableElrail(_patches.disable_elrails);
- }
-
- if (CheckSavegameVersion(43)) {
- BEGIN_TILE_LOOP(tile_cur, MapSizeX(), MapSizeY(), 0) {
- if (IsTileType(tile_cur, MP_INDUSTRY)) {
- switch (GetIndustryGfx(tile_cur)) {
- case GFX_POWERPLANT_SPARKS:
- SetIndustryAnimationState(tile_cur, GB(_m[tile_cur].m1, 2, 5));
- break;
-
- case GFX_OILWELL_ANIMATED_1:
- case GFX_OILWELL_ANIMATED_2:
- case GFX_OILWELL_ANIMATED_3:
- SetIndustryAnimationState(tile_cur, GB(_m[tile_cur].m1, 0, 2));
- break;
-
- case GFX_COAL_MINE_TOWER_ANIMATED:
- case GFX_COPPER_MINE_TOWER_ANIMATED:
- case GFX_GOLD_MINE_TOWER_ANIMATED:
- SetIndustryAnimationState(tile_cur, _m[tile_cur].m1);
- break;
-
- default: /* No animation states to change */
- break;
- }
- }
- } END_TILE_LOOP(tile_cur, MapSizeX(), MapSizeY(), 0)
- }
-
- return true;
-}
-
-/** Reload all NewGRF files during a running game. This is a cut-down
- * version of AfterLoadGame().
- * XXX - We need to reset the vehicle position hash because with a non-empty
- * hash AfterLoadVehicles() will loop infinitely. We need AfterLoadVehicles()
- * to recalculate vehicle data as some NewGRF vehicle sets could have been
- * removed or added and changed statistics */
-void ReloadNewGRFData(void)
-{
- /* reload grf data */
- GfxLoadSprites();
- LoadStringWidthTable();
- /* reload vehicles */
- ResetVehiclePosHash();
- AfterLoadVehicles();
- /* update station and waypoint graphics */
- AfterLoadWaypoints();
- AfterLoadStations();
- /* redraw the whole screen */
- MarkWholeScreenDirty();
-}