openttd.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 
00014 #include "blitter/factory.hpp"
00015 #include "sound/sound_driver.hpp"
00016 #include "music/music_driver.hpp"
00017 #include "video/video_driver.hpp"
00018 
00019 #include "fontcache.h"
00020 #include "gui.h"
00021 #include "sound_func.h"
00022 #include "window_func.h"
00023 
00024 #include "base_media_base.h"
00025 #include "saveload/saveload.h"
00026 #include "company_func.h"
00027 #include "command_func.h"
00028 #include "news_func.h"
00029 #include "fios.h"
00030 #include "aircraft.h"
00031 #include "roadveh.h"
00032 #include "train.h"
00033 #include "ship.h"
00034 #include "console_func.h"
00035 #include "screenshot.h"
00036 #include "network/network.h"
00037 #include "network/network_func.h"
00038 #include "signs_base.h"
00039 #include "ai/ai.hpp"
00040 #include "ai/ai_config.hpp"
00041 #include "settings_func.h"
00042 #include "genworld.h"
00043 #include "group.h"
00044 #include "strings_func.h"
00045 #include "date_func.h"
00046 #include "vehicle_func.h"
00047 #include "gamelog.h"
00048 #include "animated_tile_func.h"
00049 #include "roadstop_base.h"
00050 #include "elrail_func.h"
00051 #include "rev.h"
00052 #include "highscore.h"
00053 #include "thread/thread.h"
00054 #include "station_base.h"
00055 #include "crashlog.h"
00056 #include "engine_func.h"
00057 #include "core/random_func.hpp"
00058 #include "rail_gui.h"
00059 #include "core/backup_type.hpp"
00060 #include "hotkeys.h"
00061 #include "newgrf.h"
00062 #include "misc/getoptdata.h"
00063 
00064 
00065 #include "town.h"
00066 #include "industry.h"
00067 
00068 #include <stdarg.h>
00069 
00070 #include "table/strings.h"
00071 
00073 StringID _switch_mode_errorstr;
00074 
00075 void CallLandscapeTick();
00076 void IncreaseDate();
00077 void DoPaletteAnimations();
00078 void MusicLoop();
00079 void ResetMusic();
00080 void CallWindowTickEvent();
00081 
00082 extern void SetDifficultyLevel(int mode, DifficultySettings *gm_opt);
00083 extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY);
00084 extern void ShowOSErrorBox(const char *buf, bool system);
00085 extern char *_config_file;
00086 
00092 void CDECL usererror(const char *s, ...)
00093 {
00094   va_list va;
00095   char buf[512];
00096 
00097   va_start(va, s);
00098   vsnprintf(buf, lengthof(buf), s, va);
00099   va_end(va);
00100 
00101   ShowOSErrorBox(buf, false);
00102   if (_video_driver != NULL) _video_driver->Stop();
00103 
00104   exit(1);
00105 }
00106 
00112 void CDECL error(const char *s, ...)
00113 {
00114   va_list va;
00115   char buf[512];
00116 
00117   va_start(va, s);
00118   vsnprintf(buf, lengthof(buf), s, va);
00119   va_end(va);
00120 
00121   ShowOSErrorBox(buf, true);
00122 
00123   /* Set the error message for the crash log and then invoke it. */
00124   CrashLog::SetErrorMessage(buf);
00125   abort();
00126 }
00127 
00132 void CDECL ShowInfoF(const char *str, ...)
00133 {
00134   va_list va;
00135   char buf[1024];
00136   va_start(va, str);
00137   vsnprintf(buf, lengthof(buf), str, va);
00138   va_end(va);
00139   ShowInfo(buf);
00140 }
00141 
00145 static void ShowHelp()
00146 {
00147   char buf[8192];
00148   char *p = buf;
00149 
00150   p += seprintf(p, lastof(buf), "OpenTTD %s\n", _openttd_revision);
00151   p = strecpy(p,
00152     "\n"
00153     "\n"
00154     "Command line options:\n"
00155     "  -v drv              = Set video driver (see below)\n"
00156     "  -s drv              = Set sound driver (see below) (param bufsize,hz)\n"
00157     "  -m drv              = Set music driver (see below)\n"
00158     "  -b drv              = Set the blitter to use (see below)\n"
00159     "  -r res              = Set resolution (for instance 800x600)\n"
00160     "  -h                  = Display this help text\n"
00161     "  -t year             = Set starting year\n"
00162     "  -d [[fac=]lvl[,...]]= Debug mode\n"
00163     "  -e                  = Start Editor\n"
00164     "  -g [savegame]       = Start new/save game immediately\n"
00165     "  -G seed             = Set random seed\n"
00166 #if defined(ENABLE_NETWORK)
00167     "  -n [ip:port#company]= Start networkgame\n"
00168     "  -p password         = Password to join server\n"
00169     "  -P password         = Password to join company\n"
00170     "  -D [ip][:port]      = Start dedicated server\n"
00171     "  -l ip[:port]        = Redirect DEBUG()\n"
00172 #if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32)
00173     "  -f                  = Fork into the background (dedicated only)\n"
00174 #endif
00175 #endif /* ENABLE_NETWORK */
00176     "  -I graphics_set     = Force the graphics set (see below)\n"
00177     "  -S sounds_set       = Force the sounds set (see below)\n"
00178     "  -M music_set        = Force the music set (see below)\n"
00179     "  -c config_file      = Use 'config_file' instead of 'openttd.cfg'\n"
00180     "  -x                  = Do not automatically save to config file on exit\n"
00181     "\n",
00182     lastof(buf)
00183   );
00184 
00185   /* List the graphics packs */
00186   p = BaseGraphics::GetSetsList(p, lastof(buf));
00187 
00188   /* List the sounds packs */
00189   p = BaseSounds::GetSetsList(p, lastof(buf));
00190 
00191   /* List the music packs */
00192   p = BaseMusic::GetSetsList(p, lastof(buf));
00193 
00194   /* List the drivers */
00195   p = VideoDriverFactoryBase::GetDriversInfo(p, lastof(buf));
00196 
00197   /* List the blitters */
00198   p = BlitterFactoryBase::GetBlittersInfo(p, lastof(buf));
00199 
00200   /* We need to initialize the AI, so it finds the AIs */
00201   TarScanner::DoScan();
00202   AI::Initialize();
00203   p = AI::GetConsoleList(p, lastof(buf), true);
00204   AI::Uninitialize(true);
00205 
00206   /* ShowInfo put output to stderr, but version information should go
00207    * to stdout; this is the only exception */
00208 #if !defined(WIN32) && !defined(WIN64)
00209   printf("%s\n", buf);
00210 #else
00211   ShowInfo(buf);
00212 #endif
00213 }
00214 
00215 
00222 static void ParseResolution(Dimension *res, const char *s)
00223 {
00224   const char *t = strchr(s, 'x');
00225   if (t == NULL) {
00226     ShowInfoF("Invalid resolution '%s'", s);
00227     return;
00228   }
00229 
00230   res->width  = max(strtoul(s, NULL, 0), 64UL);
00231   res->height = max(strtoul(t + 1, NULL, 0), 64UL);
00232 }
00233 
00234 static void InitializeDynamicVariables()
00235 {
00236   /* Dynamic stuff needs to be initialized somewhere... */
00237   _engine_mngr.ResetToDefaultMapping();
00238   _house_mngr.ResetMapping();
00239   _industry_mngr.ResetMapping();
00240   _industile_mngr.ResetMapping();
00241   _airport_mngr.ResetMapping();
00242   _airporttile_mngr.ResetMapping();
00243 }
00244 
00245 
00250 static void ShutdownGame()
00251 {
00252   IConsoleFree();
00253 
00254   if (_network_available) NetworkShutDown(); // Shut down the network and close any open connections
00255 
00256   DriverFactoryBase::ShutdownDrivers();
00257 
00258   UnInitWindowSystem();
00259 
00260   /* stop the AI */
00261   AI::Uninitialize(false);
00262 
00263   /* Uninitialize variables that are allocated dynamically */
00264   GamelogReset();
00265 
00266 #ifdef ENABLE_NETWORK
00267   free(_config_file);
00268 #endif
00269 
00270   PoolBase::Clean(PT_ALL);
00271 
00272   ResetNewGRFData();
00273 
00274   /* Close all and any open filehandles */
00275   FioCloseAll();
00276 }
00277 
00278 static void LoadIntroGame()
00279 {
00280   _game_mode = GM_MENU;
00281 
00282   ResetGRFConfig(false);
00283 
00284   /* Setup main window */
00285   ResetWindowSystem();
00286   SetupColoursAndInitialWindow();
00287 
00288   /* Load the default opening screen savegame */
00289   if (SaveOrLoad("opntitle.dat", SL_LOAD, DATA_DIR) != SL_OK) {
00290     GenerateWorld(GWM_EMPTY, 64, 64); // if failed loading, make empty world.
00291     WaitTillGeneratedWorld();
00292     SetLocalCompany(COMPANY_SPECTATOR);
00293   } else {
00294     SetLocalCompany(COMPANY_FIRST);
00295   }
00296 
00297   _pause_mode = PM_UNPAUSED;
00298   _cursor.fix_at = false;
00299 
00300   CheckForMissingSprites();
00301   CheckForMissingGlyphsInLoadedLanguagePack();
00302 
00303   /* Play main theme */
00304   if (_music_driver->IsSongPlaying()) ResetMusic();
00305 }
00306 
00307 void MakeNewgameSettingsLive()
00308 {
00309 #ifdef ENABLE_AI
00310   for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00311     if (_settings_game.ai_config[c] != NULL) {
00312       delete _settings_game.ai_config[c];
00313     }
00314   }
00315 #endif /* ENABLE_AI */
00316 
00317   _settings_game = _settings_newgame;
00318 
00319 #ifdef ENABLE_AI
00320   for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00321     _settings_game.ai_config[c] = NULL;
00322     if (_settings_newgame.ai_config[c] != NULL) {
00323       _settings_game.ai_config[c] = new AIConfig(_settings_newgame.ai_config[c]);
00324     }
00325   }
00326 #endif /* ENABLE_AI */
00327 }
00328 
00329 #if defined(UNIX) && !defined(__MORPHOS__)
00330 extern void DedicatedFork();
00331 #endif
00332 
00334 static const OptionData _options[] = {
00335    GETOPT_SHORT_VALUE('I'),
00336    GETOPT_SHORT_VALUE('S'),
00337    GETOPT_SHORT_VALUE('M'),
00338    GETOPT_SHORT_VALUE('m'),
00339    GETOPT_SHORT_VALUE('s'),
00340    GETOPT_SHORT_VALUE('v'),
00341    GETOPT_SHORT_VALUE('b'),
00342 #if defined(ENABLE_NETWORK)
00343   GETOPT_SHORT_OPTVAL('D'),
00344   GETOPT_SHORT_OPTVAL('n'),
00345    GETOPT_SHORT_VALUE('l'),
00346    GETOPT_SHORT_VALUE('p'),
00347    GETOPT_SHORT_VALUE('P'),
00348 #if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32)
00349    GETOPT_SHORT_NOVAL('f'),
00350 #endif
00351 #endif /* ENABLE_NETWORK */
00352    GETOPT_SHORT_VALUE('r'),
00353    GETOPT_SHORT_VALUE('t'),
00354   GETOPT_SHORT_OPTVAL('d'),
00355    GETOPT_SHORT_NOVAL('e'),
00356   GETOPT_SHORT_OPTVAL('g'),
00357    GETOPT_SHORT_VALUE('G'),
00358    GETOPT_SHORT_VALUE('c'),
00359    GETOPT_SHORT_NOVAL('x'),
00360    GETOPT_SHORT_NOVAL('h'),
00361   GETOPT_END()
00362 };
00363 
00364 
00365 int ttd_main(int argc, char *argv[])
00366 {
00367   char *musicdriver = NULL;
00368   char *sounddriver = NULL;
00369   char *videodriver = NULL;
00370   char *blitter = NULL;
00371   char *graphics_set = NULL;
00372   char *sounds_set = NULL;
00373   char *music_set = NULL;
00374   Dimension resolution = {0, 0};
00375   Year startyear = INVALID_YEAR;
00376   uint generation_seed = GENERATE_NEW_SEED;
00377   bool save_config = true;
00378 #if defined(ENABLE_NETWORK)
00379   bool dedicated = false;
00380   bool network   = false;
00381   char *network_conn = NULL;
00382   char *debuglog_conn = NULL;
00383   char *dedicated_host = NULL;
00384   uint16 dedicated_port = 0;
00385   char *join_server_password = NULL;
00386   char *join_company_password = NULL;
00387 
00388   extern bool _dedicated_forks;
00389   _dedicated_forks = false;
00390 #endif /* ENABLE_NETWORK */
00391 
00392   _game_mode = GM_MENU;
00393   _switch_mode = SM_MENU;
00394   _switch_mode_errorstr = INVALID_STRING_ID;
00395   _config_file = NULL;
00396 
00397   GetOptData mgo(argc - 1, argv + 1, _options);
00398 
00399   int i;
00400   while ((i = mgo.GetOpt()) != -1) {
00401     switch (i) {
00402     case 'I': free(graphics_set); graphics_set = strdup(mgo.opt); break;
00403     case 'S': free(sounds_set); sounds_set = strdup(mgo.opt); break;
00404     case 'M': free(music_set); music_set = strdup(mgo.opt); break;
00405     case 'm': free(musicdriver); musicdriver = strdup(mgo.opt); break;
00406     case 's': free(sounddriver); sounddriver = strdup(mgo.opt); break;
00407     case 'v': free(videodriver); videodriver = strdup(mgo.opt); break;
00408     case 'b': free(blitter); blitter = strdup(mgo.opt); break;
00409 #if defined(ENABLE_NETWORK)
00410     case 'D':
00411       free(musicdriver);
00412       free(sounddriver);
00413       free(videodriver);
00414       free(blitter);
00415       musicdriver = strdup("null");
00416       sounddriver = strdup("null");
00417       videodriver = strdup("dedicated");
00418       blitter = strdup("null");
00419       dedicated = true;
00420       SetDebugString("net=6");
00421       if (mgo.opt != NULL) {
00422         /* Use the existing method for parsing (openttd -n).
00423          * However, we do ignore the #company part. */
00424         const char *temp = NULL;
00425         const char *port = NULL;
00426         ParseConnectionString(&temp, &port, mgo.opt);
00427         if (!StrEmpty(mgo.opt)) dedicated_host = mgo.opt;
00428         if (port != NULL) dedicated_port = atoi(port);
00429       }
00430       break;
00431     case 'f': _dedicated_forks = true; break;
00432     case 'n':
00433       network = true;
00434       network_conn = mgo.opt; // optional IP parameter, NULL if unset
00435       break;
00436     case 'l':
00437       debuglog_conn = mgo.opt;
00438       break;
00439     case 'p':
00440       join_server_password = mgo.opt;
00441       break;
00442     case 'P':
00443       join_company_password = mgo.opt;
00444       break;
00445 #endif /* ENABLE_NETWORK */
00446     case 'r': ParseResolution(&resolution, mgo.opt); break;
00447     case 't': startyear = atoi(mgo.opt); break;
00448     case 'd': {
00449 #if defined(WIN32)
00450         CreateConsole();
00451 #endif
00452         if (mgo.opt != NULL) SetDebugString(mgo.opt);
00453         break;
00454       }
00455     case 'e': _switch_mode = SM_EDITOR; break;
00456     case 'g':
00457       if (mgo.opt != NULL) {
00458         strecpy(_file_to_saveload.name, mgo.opt, lastof(_file_to_saveload.name));
00459         _switch_mode = SM_LOAD_GAME;
00460         _file_to_saveload.mode = SL_LOAD;
00461 
00462         /* if the file doesn't exist or it is not a valid savegame, let the saveload code show an error */
00463         const char *t = strrchr(_file_to_saveload.name, '.');
00464         if (t != NULL) {
00465           FiosType ft = FiosGetSavegameListCallback(SLD_LOAD_GAME, _file_to_saveload.name, t, NULL, NULL);
00466           if (ft != FIOS_TYPE_INVALID) SetFiosType(ft);
00467         }
00468 
00469         break;
00470       }
00471 
00472       _switch_mode = SM_NEWGAME;
00473       /* Give a random map if no seed has been given */
00474       if (generation_seed == GENERATE_NEW_SEED) {
00475         generation_seed = InteractiveRandom();
00476       }
00477       break;
00478     case 'G': generation_seed = atoi(mgo.opt); break;
00479     case 'c': _config_file = strdup(mgo.opt); break;
00480     case 'x': save_config = false; break;
00481     case 'h':
00482       i = -2; // Force printing of help.
00483       break;
00484     }
00485     if (i == -2) break;
00486   }
00487 
00488   if (i == -2 || mgo.numleft > 0) {
00489     /* Either the user typed '-h', he made an error, or he added unrecognized command line arguments.
00490      * In all cases, print the help, and exit.
00491      *
00492      * The next two functions are needed to list the graphics sets. We can't do them earlier
00493      * because then we cannot show it on the debug console as that hasn't been configured yet. */
00494     DeterminePaths(argv[0]);
00495     BaseGraphics::FindSets();
00496     BaseSounds::FindSets();
00497     BaseMusic::FindSets();
00498     ShowHelp();
00499     return 0;
00500   }
00501 
00502 #if defined(WINCE) && defined(_DEBUG)
00503   /* Switch on debug lvl 4 for WinCE if Debug release, as you can't give params, and you most likely do want this information */
00504   SetDebugString("4");
00505 #endif
00506 
00507   DeterminePaths(argv[0]);
00508   BaseGraphics::FindSets();
00509   BaseSounds::FindSets();
00510   BaseMusic::FindSets();
00511 
00512 #if defined(ENABLE_NETWORK) && defined(UNIX) && !defined(__MORPHOS__)
00513   /* We must fork here, or we'll end up without some resources we need (like sockets) */
00514   if (_dedicated_forks) DedicatedFork();
00515 #endif
00516 
00517   TarScanner::DoScan();
00518   AI::Initialize();
00519   LoadFromConfig();
00520   AI::Uninitialize(true);
00521   CheckConfig();
00522   LoadFromHighScore();
00523   LoadHotkeysFromConfig();
00524 
00525   if (resolution.width != 0) { _cur_resolution = resolution; }
00526   if (startyear != INVALID_YEAR) _settings_newgame.game_creation.starting_year = startyear;
00527   if (generation_seed != GENERATE_NEW_SEED) _settings_newgame.game_creation.generation_seed = generation_seed;
00528 
00529   /*
00530    * The width and height must be at least 1 pixel and width times
00531    * height must still fit within a 32 bits integer, this way all
00532    * internal drawing routines work correctly.
00533    */
00534   _cur_resolution.width  = ClampU(_cur_resolution.width,  1, UINT16_MAX);
00535   _cur_resolution.height = ClampU(_cur_resolution.height, 1, UINT16_MAX);
00536 
00537 #if defined(ENABLE_NETWORK)
00538   if (dedicated) DEBUG(net, 0, "Starting dedicated version %s", _openttd_revision);
00539   if (dedicated_host != NULL) {
00540     _network_bind_list.Clear();
00541     *_network_bind_list.Append() = strdup(dedicated_host);
00542   }
00543   if (dedicated_port != 0) _settings_client.network.server_port = dedicated_port;
00544   if (_dedicated_forks && !dedicated) _dedicated_forks = false;
00545 #endif /* ENABLE_NETWORK */
00546 
00547   /* enumerate language files */
00548   InitializeLanguagePacks();
00549 
00550   /* initialize screenshot formats */
00551   InitializeScreenshotFormats();
00552 
00553   /* initialize all variables that are allocated dynamically */
00554   InitializeDynamicVariables();
00555 
00556   /* Initialize FreeType */
00557   InitFreeType();
00558 
00559   /* This must be done early, since functions use the SetWindowDirty* calls */
00560   InitWindowSystem();
00561 
00562   /* Look for the sounds before the graphics. Otherwise none would be set and
00563    * the first initialisation of the video happens on the wrong data. Now it
00564    * can do the first initialisation right. */
00565   if (sounds_set == NULL && BaseSounds::ini_set != NULL) sounds_set = strdup(BaseSounds::ini_set);
00566   if (!BaseSounds::SetSet(sounds_set)) {
00567     StrEmpty(sounds_set) ?
00568       usererror("Failed to find a sounds set. Please acquire a sounds set for OpenTTD. See section 4.1 of readme.txt.") :
00569       usererror("Failed to select requested sounds set '%s'", sounds_set);
00570   }
00571   free(sounds_set);
00572 
00573   if (graphics_set == NULL && BaseGraphics::ini_set != NULL) graphics_set = strdup(BaseGraphics::ini_set);
00574   if (!BaseGraphics::SetSet(graphics_set)) {
00575     StrEmpty(graphics_set) ?
00576       usererror("Failed to find a graphics set. Please acquire a graphics set for OpenTTD. See section 4.1 of readme.txt.") :
00577       usererror("Failed to select requested graphics set '%s'", graphics_set);
00578   }
00579   free(graphics_set);
00580 
00581   if (music_set == NULL && BaseMusic::ini_set != NULL) music_set = strdup(BaseMusic::ini_set);
00582   if (!BaseMusic::SetSet(music_set)) {
00583     StrEmpty(music_set) ?
00584       usererror("Failed to find a music set. Please acquire a music set for OpenTTD. See section 4.1 of readme.txt.") :
00585       usererror("Failed to select requested music set '%s'", music_set);
00586   }
00587   free(music_set);
00588 
00589   /* Initialize game palette */
00590   GfxInitPalettes();
00591 
00592   DEBUG(misc, 1, "Loading blitter...");
00593   if (blitter == NULL && _ini_blitter != NULL) blitter = strdup(_ini_blitter);
00594   if (BlitterFactoryBase::SelectBlitter(blitter) == NULL) {
00595     StrEmpty(blitter) ?
00596       usererror("Failed to autoprobe blitter") :
00597       usererror("Failed to select requested blitter '%s'; does it exist?", blitter);
00598   }
00599   free(blitter);
00600 
00601   DEBUG(driver, 1, "Loading drivers...");
00602 
00603   if (sounddriver == NULL && _ini_sounddriver != NULL) sounddriver = strdup(_ini_sounddriver);
00604   _sound_driver = (SoundDriver*)SoundDriverFactoryBase::SelectDriver(sounddriver, Driver::DT_SOUND);
00605   if (_sound_driver == NULL) {
00606     StrEmpty(sounddriver) ?
00607       usererror("Failed to autoprobe sound driver") :
00608       usererror("Failed to select requested sound driver '%s'", sounddriver);
00609   }
00610   free(sounddriver);
00611 
00612   if (videodriver == NULL && _ini_videodriver != NULL) videodriver = strdup(_ini_videodriver);
00613   _video_driver = (VideoDriver*)VideoDriverFactoryBase::SelectDriver(videodriver, Driver::DT_VIDEO);
00614   if (_video_driver == NULL) {
00615     StrEmpty(videodriver) ?
00616       usererror("Failed to autoprobe video driver") :
00617       usererror("Failed to select requested video driver '%s'", videodriver);
00618   }
00619   free(videodriver);
00620 
00621   if (musicdriver == NULL && _ini_musicdriver != NULL) musicdriver = strdup(_ini_musicdriver);
00622   _music_driver = (MusicDriver*)MusicDriverFactoryBase::SelectDriver(musicdriver, Driver::DT_MUSIC);
00623   if (_music_driver == NULL) {
00624     StrEmpty(musicdriver) ?
00625       usererror("Failed to autoprobe music driver") :
00626       usererror("Failed to select requested music driver '%s'", musicdriver);
00627   }
00628   free(musicdriver);
00629 
00630   /* Initialize the zoom level of the screen to normal */
00631   _screen.zoom = ZOOM_LVL_NORMAL;
00632 
00633   /* restore saved music volume */
00634   _music_driver->SetVolume(_settings_client.music.music_vol);
00635 
00636   NetworkStartUp(); // initialize network-core
00637 
00638 #if defined(ENABLE_NETWORK)
00639   if (debuglog_conn != NULL && _network_available) {
00640     const char *not_used = NULL;
00641     const char *port = NULL;
00642     uint16 rport;
00643 
00644     rport = NETWORK_DEFAULT_DEBUGLOG_PORT;
00645 
00646     ParseConnectionString(&not_used, &port, debuglog_conn);
00647     if (port != NULL) rport = atoi(port);
00648 
00649     NetworkStartDebugLog(NetworkAddress(debuglog_conn, rport));
00650   }
00651 #endif /* ENABLE_NETWORK */
00652 
00653   ScanNewGRFFiles();
00654 
00655   ResetGRFConfig(false);
00656 
00657   /* Make sure _settings is filled with _settings_newgame if we switch to a game directly */
00658   if (_switch_mode != SM_NONE) MakeNewgameSettingsLive();
00659 
00660   /* initialize the ingame console */
00661   IConsoleInit();
00662   _cursor.in_window = true;
00663   InitializeGUI();
00664   IConsoleCmdExec("exec scripts/autoexec.scr 0");
00665 
00666   /* Take our initial lock on whatever we might want to do! */
00667   _genworld_paint_mutex->BeginCritical();
00668   _genworld_mapgen_mutex->BeginCritical();
00669 
00670   GenerateWorld(GWM_EMPTY, 64, 64); // Make the viewport initialization happy
00671   WaitTillGeneratedWorld();
00672 
00673   CheckForMissingGlyphsInLoadedLanguagePack();
00674 
00675 #ifdef ENABLE_NETWORK
00676   if (network && _network_available) {
00677     if (network_conn != NULL) {
00678       const char *port = NULL;
00679       const char *company = NULL;
00680       uint16 rport = NETWORK_DEFAULT_PORT;
00681       CompanyID join_as = COMPANY_NEW_COMPANY;
00682 
00683       ParseConnectionString(&company, &port, network_conn);
00684 
00685       if (company != NULL) {
00686         join_as = (CompanyID)atoi(company);
00687 
00688         if (join_as != COMPANY_SPECTATOR) {
00689           join_as--;
00690           if (join_as >= MAX_COMPANIES) return false;
00691         }
00692       }
00693       if (port != NULL) rport = atoi(port);
00694 
00695       LoadIntroGame();
00696       _switch_mode = SM_NONE;
00697       NetworkClientConnectGame(NetworkAddress(network_conn, rport), join_as, join_server_password, join_company_password);
00698     }
00699   }
00700 #endif /* ENABLE_NETWORK */
00701 
00702   _video_driver->MainLoop();
00703 
00704   WaitTillSaved();
00705 
00706   /* only save config if we have to */
00707   if (save_config) {
00708     SaveToConfig();
00709     SaveHotkeysToConfig();
00710     SaveToHighScore();
00711   }
00712 
00713   /* Reset windowing system, stop drivers, free used memory, ... */
00714   ShutdownGame();
00715 
00716   free(const_cast<char *>(BaseGraphics::ini_set));
00717   free(const_cast<char *>(BaseSounds::ini_set));
00718   free(const_cast<char *>(BaseMusic::ini_set));
00719   free(_ini_musicdriver);
00720   free(_ini_sounddriver);
00721   free(_ini_videodriver);
00722   free(_ini_blitter);
00723 
00724   return 0;
00725 }
00726 
00727 void HandleExitGameRequest()
00728 {
00729   if (_game_mode == GM_MENU) { // do not ask to quit on the main screen
00730     _exit_game = true;
00731   } else if (_settings_client.gui.autosave_on_exit) {
00732     DoExitSave();
00733     _exit_game = true;
00734   } else {
00735     AskExitGame();
00736   }
00737 }
00738 
00739 static void MakeNewGameDone()
00740 {
00741   SettingsDisableElrail(_settings_game.vehicle.disable_elrails);
00742 
00743   /* In a dedicated server, the server does not play */
00744   if (_network_dedicated || BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 0) {
00745     SetLocalCompany(COMPANY_SPECTATOR);
00746     IConsoleCmdExec("exec scripts/game_start.scr 0");
00747     return;
00748   }
00749 
00750   /* Create a single company */
00751   DoStartupNewCompany(false);
00752 
00753   Company *c = Company::Get(COMPANY_FIRST);
00754   c->settings = _settings_client.company;
00755 
00756   IConsoleCmdExec("exec scripts/game_start.scr 0");
00757 
00758   SetLocalCompany(COMPANY_FIRST);
00759 
00760   InitializeRailGUI();
00761 
00762 #ifdef ENABLE_NETWORK
00763   /* We are the server, we start a new company (not dedicated),
00764    * so set the default password *if* needed. */
00765   if (_network_server && !StrEmpty(_settings_client.network.default_company_pass)) {
00766     NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass);
00767   }
00768 #endif /* ENABLE_NETWORK */
00769 
00770   if (_settings_client.gui.pause_on_newgame) DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE);
00771 
00772   MarkWholeScreenDirty();
00773 }
00774 
00775 static void MakeNewGame(bool from_heightmap, bool reset_settings)
00776 {
00777   _game_mode = GM_NORMAL;
00778 
00779   ResetGRFConfig(true);
00780   InitializeDynamicVariables();
00781 
00782   GenerateWorldSetCallback(&MakeNewGameDone);
00783   GenerateWorld(from_heightmap ? GWM_HEIGHTMAP : GWM_NEWGAME, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y, reset_settings);
00784 }
00785 
00786 static void MakeNewEditorWorldDone()
00787 {
00788   SetLocalCompany(OWNER_NONE);
00789 }
00790 
00791 static void MakeNewEditorWorld()
00792 {
00793   _game_mode = GM_EDITOR;
00794 
00795   ResetGRFConfig(true);
00796 
00797   GenerateWorldSetCallback(&MakeNewEditorWorldDone);
00798   GenerateWorld(GWM_EMPTY, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
00799 }
00800 
00811 bool SafeLoad(const char *filename, int mode, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = NULL)
00812 {
00813   assert(mode == SL_LOAD || (lf == NULL && mode == SL_OLD_LOAD));
00814   GameMode ogm = _game_mode;
00815 
00816   _game_mode = newgm;
00817 
00818   switch (lf == NULL ? SaveOrLoad(filename, mode, subdir) : LoadWithFilter(lf)) {
00819     case SL_OK: return true;
00820 
00821     case SL_REINIT:
00822 #ifdef ENABLE_NETWORK
00823       if (_network_dedicated) {
00824         /*
00825          * We need to reinit a network map...
00826          * We can't simply load the intro game here as that game has many
00827          * special cases which make clients desync immediately. So we fall
00828          * back to just generating a new game with the current settings.
00829          */
00830         DEBUG(net, 0, "Loading game failed, so a new (random) game will be started!");
00831         MakeNewGame(false, true);
00832         return false;
00833       }
00834       if (_network_server) {
00835         /* We can't load the intro game as server, so disconnect first. */
00836         NetworkDisconnect();
00837       }
00838 #endif /* ENABLE_NETWORK */
00839 
00840       switch (ogm) {
00841         default:
00842         case GM_MENU:   LoadIntroGame();      break;
00843         case GM_EDITOR: MakeNewEditorWorld(); break;
00844       }
00845       return false;
00846 
00847     default:
00848       _game_mode = ogm;
00849       return false;
00850   }
00851 }
00852 
00853 void SwitchToMode(SwitchMode new_mode)
00854 {
00855 #ifdef ENABLE_NETWORK
00856   /* If we are saving something, the network stays in his current state */
00857   if (new_mode != SM_SAVE_GAME) {
00858     /* If the network is active, make it not-active */
00859     if (_networking) {
00860       if (_network_server && (new_mode == SM_LOAD_GAME || new_mode == SM_NEWGAME || new_mode == SM_RESTARTGAME)) {
00861         NetworkReboot();
00862       } else {
00863         NetworkDisconnect();
00864       }
00865     }
00866 
00867     /* If we are a server, we restart the server */
00868     if (_is_network_server) {
00869       /* But not if we are going to the menu */
00870       if (new_mode != SM_MENU) {
00871         /* check if we should reload the config */
00872         if (_settings_client.network.reload_cfg) {
00873           LoadFromConfig();
00874           MakeNewgameSettingsLive();
00875           ResetGRFConfig(false);
00876         }
00877         NetworkServerStart();
00878       } else {
00879         /* This client no longer wants to be a network-server */
00880         _is_network_server = false;
00881       }
00882     }
00883   }
00884 #endif /* ENABLE_NETWORK */
00885   /* Make sure all AI controllers are gone at quiting game */
00886   if (new_mode != SM_SAVE_GAME) AI::KillAll();
00887 
00888   switch (new_mode) {
00889     case SM_EDITOR: // Switch to scenario editor
00890       MakeNewEditorWorld();
00891       break;
00892 
00893     case SM_RESTARTGAME: // Restart --> 'Random game' with current settings
00894     case SM_NEWGAME: // New Game --> 'Random game'
00895 #ifdef ENABLE_NETWORK
00896       if (_network_server) {
00897         snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "Random Map");
00898       }
00899 #endif /* ENABLE_NETWORK */
00900       MakeNewGame(false, new_mode == SM_NEWGAME);
00901       break;
00902 
00903     case SM_LOAD_GAME: { // Load game, Play Scenario
00904       ResetGRFConfig(true);
00905       ResetWindowSystem();
00906 
00907       if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL, NO_DIRECTORY)) {
00908         SetDParamStr(0, GetSaveLoadErrorString());
00909         ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
00910       } else {
00911         if (_saveload_mode == SLD_LOAD_SCENARIO) {
00912           StartupEngines();
00913         }
00914         /* Update the local company for a loaded game. It is either always
00915          * company #1 (eg 0) or in the case of a dedicated server a spectator */
00916         SetLocalCompany(_network_dedicated ? COMPANY_SPECTATOR : COMPANY_FIRST);
00917         /* Execute the game-start script */
00918         IConsoleCmdExec("exec scripts/game_start.scr 0");
00919         /* Decrease pause counter (was increased from opening load dialog) */
00920         DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE);
00921 #ifdef ENABLE_NETWORK
00922         if (_network_server) {
00923           snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Loaded game)", _file_to_saveload.title);
00924         }
00925 #endif /* ENABLE_NETWORK */
00926       }
00927       break;
00928     }
00929 
00930     case SM_START_HEIGHTMAP: // Load a heightmap and start a new game from it
00931 #ifdef ENABLE_NETWORK
00932       if (_network_server) {
00933         snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Heightmap)", _file_to_saveload.title);
00934       }
00935 #endif /* ENABLE_NETWORK */
00936       MakeNewGame(true, true);
00937       break;
00938 
00939     case SM_LOAD_HEIGHTMAP: // Load heightmap from scenario editor
00940       SetLocalCompany(OWNER_NONE);
00941 
00942       GenerateWorld(GWM_HEIGHTMAP, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
00943       MarkWholeScreenDirty();
00944       break;
00945 
00946     case SM_LOAD_SCENARIO: { // Load scenario from scenario editor
00947       if (SafeLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR, NO_DIRECTORY)) {
00948         SetLocalCompany(OWNER_NONE);
00949         _settings_newgame.game_creation.starting_year = _cur_year;
00950         /* Cancel the saveload pausing */
00951         DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE);
00952       } else {
00953         SetDParamStr(0, GetSaveLoadErrorString());
00954         ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
00955       }
00956       break;
00957     }
00958 
00959     case SM_MENU: // Switch to game intro menu
00960       LoadIntroGame();
00961       if (BaseSounds::ini_set == NULL && BaseSounds::GetUsedSet()->fallback) {
00962         ShowErrorMessage(STR_WARNING_FALLBACK_SOUNDSET, INVALID_STRING_ID, WL_CRITICAL);
00963         BaseSounds::ini_set = strdup(BaseSounds::GetUsedSet()->name);
00964       }
00965       break;
00966 
00967     case SM_SAVE_GAME: // Save game.
00968       /* Make network saved games on pause compatible to singleplayer */
00969       if (SaveOrLoad(_file_to_saveload.name, SL_SAVE, NO_DIRECTORY) != SL_OK) {
00970         SetDParamStr(0, GetSaveLoadErrorString());
00971         ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
00972       } else {
00973         DeleteWindowById(WC_SAVELOAD, 0);
00974       }
00975       break;
00976 
00977     case SM_SAVE_HEIGHTMAP: // Save heightmap.
00978       MakeHeightmapScreenshot(_file_to_saveload.name);
00979       DeleteWindowById(WC_SAVELOAD, 0);
00980       break;
00981 
00982     case SM_GENRANDLAND: // Generate random land within scenario editor
00983       SetLocalCompany(OWNER_NONE);
00984       GenerateWorld(GWM_RANDOM, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
00985       /* XXX: set date */
00986       MarkWholeScreenDirty();
00987       break;
00988 
00989     default: NOT_REACHED();
00990   }
00991 
00992   if (_switch_mode_errorstr != INVALID_STRING_ID) {
00993     ShowErrorMessage(_switch_mode_errorstr, INVALID_STRING_ID, WL_CRITICAL);
00994     _switch_mode_errorstr = INVALID_STRING_ID;
00995   }
00996 }
00997 
00998 
01005 static void CheckCaches()
01006 {
01007   /* Return here so it is easy to add checks that are run
01008    * always to aid testing of caches. */
01009   if (_debug_desync_level <= 1) return;
01010 
01011   /* Strict checking of the road stop cache entries */
01012   const RoadStop *rs;
01013   FOR_ALL_ROADSTOPS(rs) {
01014     if (IsStandardRoadStopTile(rs->xy)) continue;
01015 
01016     assert(rs->GetEntry(DIAGDIR_NE) != rs->GetEntry(DIAGDIR_NW));
01017     rs->GetEntry(DIAGDIR_NE)->CheckIntegrity(rs);
01018     rs->GetEntry(DIAGDIR_NW)->CheckIntegrity(rs);
01019   }
01020 
01021   Vehicle *v;
01022   FOR_ALL_VEHICLES(v) {
01023     extern void FillNewGRFVehicleCache(const Vehicle *v);
01024     if (v != v->First() || v->vehstatus & VS_CRASHED || !v->IsPrimaryVehicle()) continue;
01025 
01026     uint length = 0;
01027     for (const Vehicle *u = v; u != NULL; u = u->Next()) length++;
01028 
01029     NewGRFCache        *grf_cache = CallocT<NewGRFCache>(length);
01030     VehicleCache       *veh_cache = CallocT<VehicleCache>(length);
01031     GroundVehicleCache *gro_cache = CallocT<GroundVehicleCache>(length);
01032     TrainCache         *tra_cache = CallocT<TrainCache>(length);
01033 
01034     length = 0;
01035     for (const Vehicle *u = v; u != NULL; u = u->Next()) {
01036       FillNewGRFVehicleCache(u);
01037       grf_cache[length] = u->grf_cache;
01038       veh_cache[length] = u->vcache;
01039       switch (u->type) {
01040         case VEH_TRAIN:
01041           gro_cache[length] = Train::From(u)->gcache;
01042           tra_cache[length] = Train::From(u)->tcache;
01043           break;
01044         case VEH_ROAD:
01045           gro_cache[length] = RoadVehicle::From(u)->gcache;
01046           break;
01047         default:
01048           break;
01049       }
01050       length++;
01051     }
01052 
01053     switch (v->type) {
01054       case VEH_TRAIN:    Train::From(v)->ConsistChanged(true);     break;
01055       case VEH_ROAD:     RoadVehUpdateCache(RoadVehicle::From(v)); break;
01056       case VEH_AIRCRAFT: UpdateAircraftCache(Aircraft::From(v));   break;
01057       case VEH_SHIP:     Ship::From(v)->UpdateCache();             break;
01058       default: break;
01059     }
01060 
01061     length = 0;
01062     for (const Vehicle *u = v; u != NULL; u = u->Next()) {
01063       FillNewGRFVehicleCache(u);
01064       if (memcmp(&grf_cache[length], &u->grf_cache, sizeof(NewGRFCache)) != 0) {
01065         DEBUG(desync, 2, "newgrf cache mismatch: type %i, vehicle %i, company %i, unit number %i, wagon %i", (int)v->type, v->index, (int)v->owner, v->unitnumber, length);
01066       }
01067       if (memcmp(&veh_cache[length], &u->vcache, sizeof(VehicleCache)) != 0) {
01068         DEBUG(desync, 2, "vehicle cache mismatch: type %i, vehicle %i, company %i, unit number %i, wagon %i", (int)v->type, v->index, (int)v->owner, v->unitnumber, length);
01069       }
01070       switch (u->type) {
01071         case VEH_TRAIN:
01072           if (memcmp(&gro_cache[length], &Train::From(u)->gcache, sizeof(GroundVehicleCache)) != 0) {
01073             DEBUG(desync, 2, "train ground vehicle cache mismatch: vehicle %i, company %i, unit number %i, wagon %i", v->index, (int)v->owner, v->unitnumber, length);
01074           }
01075           if (memcmp(&tra_cache[length], &Train::From(u)->tcache, sizeof(TrainCache)) != 0) {
01076             DEBUG(desync, 2, "train cache mismatch: vehicle %i, company %i, unit number %i, wagon %i", v->index, (int)v->owner, v->unitnumber, length);
01077           }
01078           break;
01079         case VEH_ROAD:
01080           if (memcmp(&gro_cache[length], &RoadVehicle::From(u)->gcache, sizeof(GroundVehicleCache)) != 0) {
01081             DEBUG(desync, 2, "road vehicle ground vehicle cache mismatch: vehicle %i, company %i, unit number %i, wagon %i", v->index, (int)v->owner, v->unitnumber, length);
01082           }
01083           break;
01084         default:
01085           break;
01086       }
01087       length++;
01088     }
01089 
01090     free(grf_cache);
01091     free(veh_cache);
01092     free(gro_cache);
01093     free(tra_cache);
01094   }
01095 
01096   /* Check whether the caches are still valid */
01097   FOR_ALL_VEHICLES(v) {
01098     byte buff[sizeof(VehicleCargoList)];
01099     memcpy(buff, &v->cargo, sizeof(VehicleCargoList));
01100     v->cargo.InvalidateCache();
01101     assert(memcmp(&v->cargo, buff, sizeof(VehicleCargoList)) == 0);
01102   }
01103 
01104   Station *st;
01105   FOR_ALL_STATIONS(st) {
01106     for (CargoID c = 0; c < NUM_CARGO; c++) {
01107       byte buff[sizeof(StationCargoList)];
01108       memcpy(buff, &st->goods[c].cargo, sizeof(StationCargoList));
01109       st->goods[c].cargo.InvalidateCache();
01110       assert(memcmp(&st->goods[c].cargo, buff, sizeof(StationCargoList)) == 0);
01111     }
01112   }
01113 }
01114 
01120 void StateGameLoop()
01121 {
01122   /* dont execute the state loop during pause */
01123   if (_pause_mode != PM_UNPAUSED) {
01124     UpdateLandscapingLimits();
01125     CallWindowTickEvent();
01126     return;
01127   }
01128   if (IsGeneratingWorld()) return;
01129 
01130   ClearStorageChanges(false);
01131 
01132   if (_game_mode == GM_EDITOR) {
01133     RunTileLoop();
01134     CallVehicleTicks();
01135     CallLandscapeTick();
01136     ClearStorageChanges(true);
01137     UpdateLandscapingLimits();
01138 
01139     CallWindowTickEvent();
01140     NewsLoop();
01141   } else {
01142     if (_debug_desync_level > 2 && _date_fract == 0 && (_date & 0x1F) == 0) {
01143       /* Save the desync savegame if needed. */
01144       char name[MAX_PATH];
01145       snprintf(name, lengthof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
01146       SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR, false);
01147     }
01148 
01149     CheckCaches();
01150 
01151     /* All these actions has to be done from OWNER_NONE
01152      *  for multiplayer compatibility */
01153     Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
01154 
01155     AnimateAnimatedTiles();
01156     IncreaseDate();
01157     RunTileLoop();
01158     CallVehicleTicks();
01159     CallLandscapeTick();
01160     ClearStorageChanges(true);
01161 
01162     AI::GameLoop();
01163     UpdateLandscapingLimits();
01164 
01165     CallWindowTickEvent();
01166     NewsLoop();
01167     cur_company.Restore();
01168   }
01169 
01170   assert(IsLocalCompany());
01171 }
01172 
01177 static void DoAutosave()
01178 {
01179   char buf[MAX_PATH];
01180 
01181 #if defined(PSP)
01182   /* Autosaving in networking is too time expensive for the PSP */
01183   if (_networking) return;
01184 #endif /* PSP */
01185 
01186   if (_settings_client.gui.keep_all_autosave) {
01187     GenerateDefaultSaveName(buf, lastof(buf));
01188     strecat(buf, ".sav", lastof(buf));
01189   } else {
01190     static int _autosave_ctr = 0;
01191 
01192     /* generate a savegame name and number according to _settings_client.gui.max_num_autosaves */
01193     snprintf(buf, sizeof(buf), "autosave%d.sav", _autosave_ctr);
01194 
01195     if (++_autosave_ctr >= _settings_client.gui.max_num_autosaves) _autosave_ctr = 0;
01196   }
01197 
01198   DEBUG(sl, 2, "Autosaving to '%s'", buf);
01199   if (SaveOrLoad(buf, SL_SAVE, AUTOSAVE_DIR) != SL_OK) {
01200     ShowErrorMessage(STR_ERROR_AUTOSAVE_FAILED, INVALID_STRING_ID, WL_ERROR);
01201   }
01202 }
01203 
01204 void GameLoop()
01205 {
01206   ProcessAsyncSaveFinish();
01207 
01208   /* autosave game? */
01209   if (_do_autosave) {
01210     _do_autosave = false;
01211     DoAutosave();
01212     SetWindowDirty(WC_STATUS_BAR, 0);
01213   }
01214 
01215   /* switch game mode? */
01216   if (_switch_mode != SM_NONE) {
01217     SwitchToMode(_switch_mode);
01218     _switch_mode = SM_NONE;
01219   }
01220 
01221   IncreaseSpriteLRU();
01222   InteractiveRandom();
01223 
01224   extern int _caret_timer;
01225   _caret_timer += 3;
01226   CursorTick();
01227 
01228 #ifdef ENABLE_NETWORK
01229   /* Check for UDP stuff */
01230   if (_network_available) NetworkUDPGameLoop();
01231 
01232   if (_networking && !IsGeneratingWorld()) {
01233     /* Multiplayer */
01234     NetworkGameLoop();
01235   } else {
01236     if (_network_reconnect > 0 && --_network_reconnect == 0) {
01237       /* This means that we want to reconnect to the last host
01238        * We do this here, because it means that the network is really closed */
01239       NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), COMPANY_SPECTATOR);
01240     }
01241     /* Singleplayer */
01242     StateGameLoop();
01243   }
01244 
01245   /* Check chat messages roughly once a second. */
01246   static uint check_message = 0;
01247   if (++check_message > 1000 / MILLISECONDS_PER_TICK) {
01248     check_message = 0;
01249     NetworkChatMessageLoop();
01250   }
01251 #else
01252   StateGameLoop();
01253 #endif /* ENABLE_NETWORK */
01254 
01255   if (!_pause_mode && HasBit(_display_opt, DO_FULL_ANIMATION)) DoPaletteAnimations();
01256 
01257   if (!_pause_mode || _game_mode == GM_EDITOR || _settings_game.construction.command_pause_level > CMDPL_NO_CONSTRUCTION) MoveAllTextEffects();
01258 
01259   InputLoop();
01260 
01261   _sound_driver->MainLoop();
01262   MusicLoop();
01263 }

Generated on Fri Jun 3 05:18:55 2011 for OpenTTD by  doxygen 1.6.1