00001
00002
00003
00004
00005
00006
00007
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 "progress.h"
00044 #include "group.h"
00045 #include "strings_func.h"
00046 #include "date_func.h"
00047 #include "vehicle_func.h"
00048 #include "gamelog.h"
00049 #include "animated_tile_func.h"
00050 #include "roadstop_base.h"
00051 #include "elrail_func.h"
00052 #include "rev.h"
00053 #include "highscore.h"
00054 #include "thread/thread.h"
00055 #include "station_base.h"
00056 #include "crashlog.h"
00057 #include "engine_func.h"
00058 #include "core/random_func.hpp"
00059 #include "rail_gui.h"
00060 #include "core/backup_type.hpp"
00061 #include "hotkeys.h"
00062 #include "newgrf.h"
00063 #include "misc/getoptdata.h"
00064
00065
00066 #include "town.h"
00067 #include "industry.h"
00068
00069 #include "linkgraph/linkgraph.h"
00070
00071 #include <stdarg.h>
00072
00073 #include "table/strings.h"
00074
00076 StringID _switch_mode_errorstr;
00077
00078 void CallLandscapeTick();
00079 void IncreaseDate();
00080 void DoPaletteAnimations();
00081 void MusicLoop();
00082 void ResetMusic();
00083 void CallWindowTickEvent();
00084 bool HandleBootstrap();
00085
00086 extern void SetDifficultyLevel(int mode, DifficultySettings *gm_opt);
00087 extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY);
00088 extern void ShowOSErrorBox(const char *buf, bool system);
00089 extern char *_config_file;
00090
00096 void CDECL usererror(const char *s, ...)
00097 {
00098 va_list va;
00099 char buf[512];
00100
00101 va_start(va, s);
00102 vsnprintf(buf, lengthof(buf), s, va);
00103 va_end(va);
00104
00105 ShowOSErrorBox(buf, false);
00106 if (_video_driver != NULL) _video_driver->Stop();
00107
00108 exit(1);
00109 }
00110
00116 void CDECL error(const char *s, ...)
00117 {
00118 va_list va;
00119 char buf[512];
00120
00121 va_start(va, s);
00122 vsnprintf(buf, lengthof(buf), s, va);
00123 va_end(va);
00124
00125 ShowOSErrorBox(buf, true);
00126
00127
00128 CrashLog::SetErrorMessage(buf);
00129 abort();
00130 }
00131
00136 void CDECL ShowInfoF(const char *str, ...)
00137 {
00138 va_list va;
00139 char buf[1024];
00140 va_start(va, str);
00141 vsnprintf(buf, lengthof(buf), str, va);
00142 va_end(va);
00143 ShowInfo(buf);
00144 }
00145
00149 static void ShowHelp()
00150 {
00151 char buf[8192];
00152 char *p = buf;
00153
00154 p += seprintf(p, lastof(buf), "OpenTTD %s\n", _openttd_revision);
00155 p = strecpy(p,
00156 "\n"
00157 "\n"
00158 "Command line options:\n"
00159 " -v drv = Set video driver (see below)\n"
00160 " -s drv = Set sound driver (see below) (param bufsize,hz)\n"
00161 " -m drv = Set music driver (see below)\n"
00162 " -b drv = Set the blitter to use (see below)\n"
00163 " -r res = Set resolution (for instance 800x600)\n"
00164 " -h = Display this help text\n"
00165 " -t year = Set starting year\n"
00166 " -d [[fac=]lvl[,...]]= Debug mode\n"
00167 " -e = Start Editor\n"
00168 " -g [savegame] = Start new/save game immediately\n"
00169 " -G seed = Set random seed\n"
00170 #if defined(ENABLE_NETWORK)
00171 " -n [ip:port#company]= Start networkgame\n"
00172 " -p password = Password to join server\n"
00173 " -P password = Password to join company\n"
00174 " -D [ip][:port] = Start dedicated server\n"
00175 " -l ip[:port] = Redirect DEBUG()\n"
00176 #if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32)
00177 " -f = Fork into the background (dedicated only)\n"
00178 #endif
00179 #endif
00180 " -I graphics_set = Force the graphics set (see below)\n"
00181 " -S sounds_set = Force the sounds set (see below)\n"
00182 " -M music_set = Force the music set (see below)\n"
00183 " -c config_file = Use 'config_file' instead of 'openttd.cfg'\n"
00184 " -x = Do not automatically save to config file on exit\n"
00185 " -q savegame = Write some information about the savegame and exit\n"
00186 "\n",
00187 lastof(buf)
00188 );
00189
00190
00191 p = BaseGraphics::GetSetsList(p, lastof(buf));
00192
00193
00194 p = BaseSounds::GetSetsList(p, lastof(buf));
00195
00196
00197 p = BaseMusic::GetSetsList(p, lastof(buf));
00198
00199
00200 p = VideoDriverFactoryBase::GetDriversInfo(p, lastof(buf));
00201
00202
00203 p = BlitterFactoryBase::GetBlittersInfo(p, lastof(buf));
00204
00205
00206 AI::Initialize();
00207 p = AI::GetConsoleList(p, lastof(buf), true);
00208 AI::Uninitialize(true);
00209
00210
00211
00212 #if !defined(WIN32) && !defined(WIN64)
00213 printf("%s\n", buf);
00214 #else
00215 ShowInfo(buf);
00216 #endif
00217 }
00218
00219 static void WriteSavegameInfo(const char *name)
00220 {
00221 extern uint16 _sl_version;
00222 uint32 last_ottd_rev = 0;
00223 byte ever_modified = 0;
00224 bool removed_newgrfs = false;
00225
00226 GamelogInfo(_load_check_data.gamelog_action, _load_check_data.gamelog_actions, &last_ottd_rev, &ever_modified, &removed_newgrfs);
00227
00228 char buf[8192];
00229 char *p = buf;
00230 p += seprintf(p, lastof(buf), "Name: %s\n", name);
00231 p += seprintf(p, lastof(buf), "Savegame ver: %d\n", _sl_version);
00232 p += seprintf(p, lastof(buf), "NewGRF ver: 0x%08X\n", last_ottd_rev);
00233 p += seprintf(p, lastof(buf), "Modified: %d\n", ever_modified);
00234
00235 if (removed_newgrfs) {
00236 p += seprintf(p, lastof(buf), "NewGRFs have been removed\n");
00237 }
00238
00239 p = strecpy(p, "NewGRFs:\n", lastof(buf));
00240 if (_load_check_data.HasNewGrfs()) {
00241 for (GRFConfig *c = _load_check_data.grfconfig; c != NULL; c = c->next) {
00242 char md5sum[33];
00243 md5sumToString(md5sum, lastof(md5sum), HasBit(c->flags, GCF_COMPATIBLE) ? c->original_md5sum : c->ident.md5sum);
00244 p += seprintf(p, lastof(buf), "%08X %s %s\n", c->ident.grfid, md5sum, c->filename);
00245 }
00246 }
00247
00248
00249
00250 #if !defined(WIN32) && !defined(WIN64)
00251 printf("%s\n", buf);
00252 #else
00253 ShowInfo(buf);
00254 #endif
00255 }
00256
00257
00264 static void ParseResolution(Dimension *res, const char *s)
00265 {
00266 const char *t = strchr(s, 'x');
00267 if (t == NULL) {
00268 ShowInfoF("Invalid resolution '%s'", s);
00269 return;
00270 }
00271
00272 res->width = max(strtoul(s, NULL, 0), 64UL);
00273 res->height = max(strtoul(t + 1, NULL, 0), 64UL);
00274 }
00275
00276
00281 static void ShutdownGame()
00282 {
00283 IConsoleFree();
00284
00285 if (_network_available) NetworkShutDown();
00286
00287 DriverFactoryBase::ShutdownDrivers();
00288
00289 UnInitWindowSystem();
00290
00291
00292 AI::Uninitialize(false);
00293
00294
00295 GamelogReset();
00296
00297
00298
00299
00300
00301 InitializeLinkGraphs();
00302
00303 #ifdef ENABLE_NETWORK
00304 free(_config_file);
00305 #endif
00306
00307 PoolBase::Clean(PT_ALL);
00308
00309
00310 if (_game_mode != GM_BOOTSTRAP) ResetNewGRFData();
00311
00312
00313 FioCloseAll();
00314
00315 UninitFreeType();
00316 }
00317
00322 static void LoadIntroGame(bool load_newgrfs = true)
00323 {
00324 _game_mode = GM_MENU;
00325
00326 if (load_newgrfs) ResetGRFConfig(false);
00327
00328
00329 ResetWindowSystem();
00330 SetupColoursAndInitialWindow();
00331
00332
00333 if (SaveOrLoad("opntitle.dat", SL_LOAD, BASESET_DIR) != SL_OK) {
00334 GenerateWorld(GWM_EMPTY, 64, 64);
00335 WaitTillGeneratedWorld();
00336 SetLocalCompany(COMPANY_SPECTATOR);
00337 } else {
00338 SetLocalCompany(COMPANY_FIRST);
00339 }
00340
00341 _pause_mode = PM_UNPAUSED;
00342 _cursor.fix_at = false;
00343
00344 CheckForMissingSprites();
00345 CheckForMissingGlyphs();
00346
00347
00348 if (_music_driver->IsSongPlaying()) ResetMusic();
00349 }
00350
00351 void MakeNewgameSettingsLive()
00352 {
00353 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00354 if (_settings_game.ai_config[c] != NULL) {
00355 delete _settings_game.ai_config[c];
00356 }
00357 }
00358
00359
00360
00361 _settings_game = _settings_newgame;
00362 _old_vds = _settings_client.company.vehicle;
00363
00364 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00365 _settings_game.ai_config[c] = NULL;
00366 if (_settings_newgame.ai_config[c] != NULL) {
00367 _settings_game.ai_config[c] = new AIConfig(_settings_newgame.ai_config[c]);
00368 }
00369 }
00370 }
00371
00373 struct AfterNewGRFScan : NewGRFScanCallback {
00374 Year startyear;
00375 uint generation_seed;
00376 char *dedicated_host;
00377 uint16 dedicated_port;
00378 char *network_conn;
00379 const char *join_server_password;
00380 const char *join_company_password;
00381 bool *save_config_ptr;
00382 bool save_config;
00383
00389 AfterNewGRFScan(bool *save_config_ptr) :
00390 startyear(INVALID_YEAR), generation_seed(GENERATE_NEW_SEED),
00391 dedicated_host(NULL), dedicated_port(0), network_conn(NULL),
00392 join_server_password(NULL), join_company_password(NULL),
00393 save_config_ptr(save_config_ptr), save_config(true)
00394 {
00395 }
00396
00397 virtual void OnNewGRFsScanned()
00398 {
00399 ResetGRFConfig(false);
00400
00401 TarScanner::DoScan(TarScanner::SCENARIO);
00402
00403 AI::Initialize();
00404
00405
00406 uint last_newgrf_count = _settings_client.gui.last_newgrf_count;
00407 LoadFromConfig();
00408 _settings_client.gui.last_newgrf_count = last_newgrf_count;
00409
00410
00411 UpdateNewGRFConfigPalette();
00412
00413 AI::Uninitialize(true);
00414 CheckConfig();
00415 LoadFromHighScore();
00416 LoadHotkeysFromConfig();
00417
00418
00419 *save_config_ptr = save_config;
00420
00421
00422 if (startyear != INVALID_YEAR) _settings_newgame.game_creation.starting_year = startyear;
00423 if (generation_seed != GENERATE_NEW_SEED) _settings_newgame.game_creation.generation_seed = generation_seed;
00424
00425 #if defined(ENABLE_NETWORK)
00426 if (dedicated_host != NULL) {
00427 _network_bind_list.Clear();
00428 *_network_bind_list.Append() = strdup(dedicated_host);
00429 }
00430 if (dedicated_port != 0) _settings_client.network.server_port = dedicated_port;
00431 #endif
00432
00433
00434 IConsoleInit();
00435 InitializeGUI();
00436 IConsoleCmdExec("exec scripts/autoexec.scr 0");
00437
00438
00439 if (_switch_mode != SM_NONE) MakeNewgameSettingsLive();
00440
00441 #ifdef ENABLE_NETWORK
00442 if (_network_available && network_conn != NULL) {
00443 const char *port = NULL;
00444 const char *company = NULL;
00445 uint16 rport = NETWORK_DEFAULT_PORT;
00446 CompanyID join_as = COMPANY_NEW_COMPANY;
00447
00448 ParseConnectionString(&company, &port, network_conn);
00449
00450 if (company != NULL) {
00451 join_as = (CompanyID)atoi(company);
00452
00453 if (join_as != COMPANY_SPECTATOR) {
00454 join_as--;
00455 if (join_as >= MAX_COMPANIES) {
00456 delete this;
00457 return;
00458 }
00459 }
00460 }
00461 if (port != NULL) rport = atoi(port);
00462
00463 LoadIntroGame();
00464 _switch_mode = SM_NONE;
00465 NetworkClientConnectGame(NetworkAddress(network_conn, rport), join_as, join_server_password, join_company_password);
00466 }
00467 #endif
00468
00469
00470 delete this;
00471 }
00472 };
00473
00474 #if defined(UNIX) && !defined(__MORPHOS__)
00475 extern void DedicatedFork();
00476 #endif
00477
00479 static const OptionData _options[] = {
00480 GETOPT_SHORT_VALUE('I'),
00481 GETOPT_SHORT_VALUE('S'),
00482 GETOPT_SHORT_VALUE('M'),
00483 GETOPT_SHORT_VALUE('m'),
00484 GETOPT_SHORT_VALUE('s'),
00485 GETOPT_SHORT_VALUE('v'),
00486 GETOPT_SHORT_VALUE('b'),
00487 #if defined(ENABLE_NETWORK)
00488 GETOPT_SHORT_OPTVAL('D'),
00489 GETOPT_SHORT_OPTVAL('n'),
00490 GETOPT_SHORT_VALUE('l'),
00491 GETOPT_SHORT_VALUE('p'),
00492 GETOPT_SHORT_VALUE('P'),
00493 #if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32)
00494 GETOPT_SHORT_NOVAL('f'),
00495 #endif
00496 #endif
00497 GETOPT_SHORT_VALUE('r'),
00498 GETOPT_SHORT_VALUE('t'),
00499 GETOPT_SHORT_OPTVAL('d'),
00500 GETOPT_SHORT_NOVAL('e'),
00501 GETOPT_SHORT_OPTVAL('g'),
00502 GETOPT_SHORT_VALUE('G'),
00503 GETOPT_SHORT_VALUE('c'),
00504 GETOPT_SHORT_NOVAL('x'),
00505 GETOPT_SHORT_VALUE('q'),
00506 GETOPT_SHORT_NOVAL('h'),
00507 GETOPT_END()
00508 };
00509
00510
00511 int ttd_main(int argc, char *argv[])
00512 {
00513 char *musicdriver = NULL;
00514 char *sounddriver = NULL;
00515 char *videodriver = NULL;
00516 char *blitter = NULL;
00517 char *graphics_set = NULL;
00518 char *sounds_set = NULL;
00519 char *music_set = NULL;
00520 Dimension resolution = {0, 0};
00521
00522 bool save_config = false;
00523 AfterNewGRFScan *scanner = new AfterNewGRFScan(&save_config);
00524 #if defined(ENABLE_NETWORK)
00525 bool dedicated = false;
00526 char *debuglog_conn = NULL;
00527
00528 extern bool _dedicated_forks;
00529 _dedicated_forks = false;
00530 #endif
00531
00532 _game_mode = GM_MENU;
00533 _switch_mode = SM_MENU;
00534 _switch_mode_errorstr = INVALID_STRING_ID;
00535 _config_file = NULL;
00536
00537 GetOptData mgo(argc - 1, argv + 1, _options);
00538
00539 int i;
00540 while ((i = mgo.GetOpt()) != -1) {
00541 switch (i) {
00542 case 'I': free(graphics_set); graphics_set = strdup(mgo.opt); break;
00543 case 'S': free(sounds_set); sounds_set = strdup(mgo.opt); break;
00544 case 'M': free(music_set); music_set = strdup(mgo.opt); break;
00545 case 'm': free(musicdriver); musicdriver = strdup(mgo.opt); break;
00546 case 's': free(sounddriver); sounddriver = strdup(mgo.opt); break;
00547 case 'v': free(videodriver); videodriver = strdup(mgo.opt); break;
00548 case 'b': free(blitter); blitter = strdup(mgo.opt); break;
00549 #if defined(ENABLE_NETWORK)
00550 case 'D':
00551 free(musicdriver);
00552 free(sounddriver);
00553 free(videodriver);
00554 free(blitter);
00555 musicdriver = strdup("null");
00556 sounddriver = strdup("null");
00557 videodriver = strdup("dedicated");
00558 blitter = strdup("null");
00559 dedicated = true;
00560 SetDebugString("net=6");
00561 if (mgo.opt != NULL) {
00562
00563
00564 const char *temp = NULL;
00565 const char *port = NULL;
00566 ParseConnectionString(&temp, &port, mgo.opt);
00567 if (!StrEmpty(mgo.opt)) scanner->dedicated_host = mgo.opt;
00568 if (port != NULL) scanner->dedicated_port = atoi(port);
00569 }
00570 break;
00571 case 'f': _dedicated_forks = true; break;
00572 case 'n':
00573 scanner->network_conn = mgo.opt;
00574 break;
00575 case 'l':
00576 debuglog_conn = mgo.opt;
00577 break;
00578 case 'p':
00579 scanner->join_server_password = mgo.opt;
00580 break;
00581 case 'P':
00582 scanner->join_company_password = mgo.opt;
00583 break;
00584 #endif
00585 case 'r': ParseResolution(&resolution, mgo.opt); break;
00586 case 't': scanner->startyear = atoi(mgo.opt); break;
00587 case 'd': {
00588 #if defined(WIN32)
00589 CreateConsole();
00590 #endif
00591 if (mgo.opt != NULL) SetDebugString(mgo.opt);
00592 break;
00593 }
00594 case 'e': _switch_mode = SM_EDITOR; break;
00595 case 'g':
00596 if (mgo.opt != NULL) {
00597 strecpy(_file_to_saveload.name, mgo.opt, lastof(_file_to_saveload.name));
00598 _switch_mode = SM_LOAD_GAME;
00599 _file_to_saveload.mode = SL_LOAD;
00600
00601
00602 const char *t = strrchr(_file_to_saveload.name, '.');
00603 if (t != NULL) {
00604 FiosType ft = FiosGetSavegameListCallback(SLD_LOAD_GAME, _file_to_saveload.name, t, NULL, NULL);
00605 if (ft != FIOS_TYPE_INVALID) SetFiosType(ft);
00606 }
00607
00608 break;
00609 }
00610
00611 _switch_mode = SM_NEWGAME;
00612
00613 if (scanner->generation_seed == GENERATE_NEW_SEED) {
00614 scanner->generation_seed = InteractiveRandom();
00615 }
00616 break;
00617 case 'q': {
00618 DeterminePaths(argv[0]);
00619 if (StrEmpty(mgo.opt)) return 1;
00620 char title[80];
00621 title[0] = '\0';
00622 FiosGetSavegameListCallback(SLD_LOAD_GAME, mgo.opt, strrchr(mgo.opt, '.'), title, lastof(title));
00623
00624 _load_check_data.Clear();
00625 SaveOrLoadResult res = SaveOrLoad(mgo.opt, SL_LOAD_CHECK, SAVE_DIR, false);
00626 if (res != SL_OK || _load_check_data.HasErrors()) {
00627 fprintf(stderr, "Failed to open savegame\n");
00628 if (_load_check_data.HasErrors()) {
00629 char buf[256];
00630 SetDParamStr(0, _load_check_data.error_data);
00631 GetString(buf, _load_check_data.error, lastof(buf));
00632 fprintf(stderr, "%s\n", buf);
00633 }
00634 return 1;
00635 }
00636
00637 WriteSavegameInfo(title);
00638
00639 return 0;
00640 }
00641 case 'G': scanner->generation_seed = atoi(mgo.opt); break;
00642 case 'c': _config_file = strdup(mgo.opt); break;
00643 case 'x': scanner->save_config = false; break;
00644 case 'h':
00645 i = -2;
00646 break;
00647 }
00648 if (i == -2) break;
00649 }
00650
00651 if (i == -2 || mgo.numleft > 0) {
00652
00653
00654
00655
00656
00657 DeterminePaths(argv[0]);
00658 TarScanner::DoScan(TarScanner::BASESET);
00659 BaseGraphics::FindSets();
00660 BaseSounds::FindSets();
00661 BaseMusic::FindSets();
00662 ShowHelp();
00663 delete scanner;
00664 return 0;
00665 }
00666
00667 #if defined(WINCE) && defined(_DEBUG)
00668
00669 SetDebugString("4");
00670 #endif
00671
00672 DeterminePaths(argv[0]);
00673 TarScanner::DoScan(TarScanner::BASESET);
00674
00675 #if defined(ENABLE_NETWORK)
00676 if (dedicated) DEBUG(net, 0, "Starting dedicated version %s", _openttd_revision);
00677 if (_dedicated_forks && !dedicated) _dedicated_forks = false;
00678
00679 #if defined(UNIX) && !defined(__MORPHOS__)
00680
00681 if (_dedicated_forks) DedicatedFork();
00682 #endif
00683 #endif
00684
00685 LoadFromConfig(true);
00686
00687 if (resolution.width != 0) _cur_resolution = resolution;
00688
00689
00690
00691
00692
00693
00694
00695 _cur_resolution.width = ClampU(_cur_resolution.width, 1, UINT16_MAX / 2);
00696 _cur_resolution.height = ClampU(_cur_resolution.height, 1, UINT16_MAX / 2);
00697
00698
00699
00700
00701
00702 _cursor.in_window = true;
00703
00704
00705 InitializeLanguagePacks();
00706
00707
00708 InitFreeType(false);
00709
00710
00711 InitWindowSystem();
00712
00713 BaseGraphics::FindSets();
00714 if (graphics_set == NULL && BaseGraphics::ini_set != NULL) graphics_set = strdup(BaseGraphics::ini_set);
00715 if (!BaseGraphics::SetSet(graphics_set) && !StrEmpty(graphics_set)) {
00716 usererror("Failed to select requested graphics set '%s'", graphics_set);
00717 }
00718 free(graphics_set);
00719
00720
00721 GfxInitPalettes();
00722
00723 DEBUG(misc, 1, "Loading blitter...");
00724 if (blitter == NULL && _ini_blitter != NULL) blitter = strdup(_ini_blitter);
00725 _blitter_autodetected = StrEmpty(blitter);
00726
00727 if (!_blitter_autodetected || BaseGraphics::GetUsedSet() == NULL || BaseGraphics::GetUsedSet()->blitter == BLT_8BPP || BlitterFactoryBase::SelectBlitter("32bpp-anim") == NULL) {
00728 if (BlitterFactoryBase::SelectBlitter(blitter) == NULL) {
00729 StrEmpty(blitter) ?
00730 usererror("Failed to autoprobe blitter") :
00731 usererror("Failed to select requested blitter '%s'; does it exist?", blitter);
00732 }
00733 }
00734 free(blitter);
00735
00736 if (videodriver == NULL && _ini_videodriver != NULL) videodriver = strdup(_ini_videodriver);
00737 _video_driver = (VideoDriver*)VideoDriverFactoryBase::SelectDriver(videodriver, Driver::DT_VIDEO);
00738 if (_video_driver == NULL) {
00739 StrEmpty(videodriver) ?
00740 usererror("Failed to autoprobe video driver") :
00741 usererror("Failed to select requested video driver '%s'", videodriver);
00742 }
00743 free(videodriver);
00744
00745
00746 _screen.zoom = ZOOM_LVL_NORMAL;
00747
00748 NetworkStartUp();
00749
00750 #if defined(ENABLE_NETWORK)
00751 if (debuglog_conn != NULL && _network_available) {
00752 const char *not_used = NULL;
00753 const char *port = NULL;
00754 uint16 rport;
00755
00756 rport = NETWORK_DEFAULT_DEBUGLOG_PORT;
00757
00758 ParseConnectionString(¬_used, &port, debuglog_conn);
00759 if (port != NULL) rport = atoi(port);
00760
00761 NetworkStartDebugLog(NetworkAddress(debuglog_conn, rport));
00762 }
00763 #endif
00764
00765 if (!HandleBootstrap()) goto exit;
00766
00767 _video_driver->ClaimMousePointer();
00768
00769
00770 InitializeScreenshotFormats();
00771
00772 BaseSounds::FindSets();
00773 if (sounds_set == NULL && BaseSounds::ini_set != NULL) sounds_set = strdup(BaseSounds::ini_set);
00774 if (!BaseSounds::SetSet(sounds_set)) {
00775 StrEmpty(sounds_set) ?
00776 usererror("Failed to find a sounds set. Please acquire a sounds set for OpenTTD. See section 4.1 of readme.txt.") :
00777 usererror("Failed to select requested sounds set '%s'", sounds_set);
00778 }
00779 free(sounds_set);
00780
00781 BaseMusic::FindSets();
00782 if (music_set == NULL && BaseMusic::ini_set != NULL) music_set = strdup(BaseMusic::ini_set);
00783 if (!BaseMusic::SetSet(music_set)) {
00784 StrEmpty(music_set) ?
00785 usererror("Failed to find a music set. Please acquire a music set for OpenTTD. See section 4.1 of readme.txt.") :
00786 usererror("Failed to select requested music set '%s'", music_set);
00787 }
00788 free(music_set);
00789
00790 if (sounddriver == NULL && _ini_sounddriver != NULL) sounddriver = strdup(_ini_sounddriver);
00791 _sound_driver = (SoundDriver*)SoundDriverFactoryBase::SelectDriver(sounddriver, Driver::DT_SOUND);
00792 if (_sound_driver == NULL) {
00793 StrEmpty(sounddriver) ?
00794 usererror("Failed to autoprobe sound driver") :
00795 usererror("Failed to select requested sound driver '%s'", sounddriver);
00796 }
00797 free(sounddriver);
00798
00799 if (musicdriver == NULL && _ini_musicdriver != NULL) musicdriver = strdup(_ini_musicdriver);
00800 _music_driver = (MusicDriver*)MusicDriverFactoryBase::SelectDriver(musicdriver, Driver::DT_MUSIC);
00801 if (_music_driver == NULL) {
00802 StrEmpty(musicdriver) ?
00803 usererror("Failed to autoprobe music driver") :
00804 usererror("Failed to select requested music driver '%s'", musicdriver);
00805 }
00806 free(musicdriver);
00807
00808
00809 _music_driver->SetVolume(_settings_client.music.music_vol);
00810
00811
00812 _modal_progress_paint_mutex->BeginCritical();
00813 _modal_progress_work_mutex->BeginCritical();
00814
00815 GenerateWorld(GWM_EMPTY, 64, 64);
00816 WaitTillGeneratedWorld();
00817
00818 LoadIntroGame(false);
00819
00820 CheckForMissingGlyphs();
00821
00822 ScanNewGRFFiles(scanner);
00823
00824 _video_driver->MainLoop();
00825
00826 WaitTillSaved();
00827
00828
00829 if (save_config) {
00830 SaveToConfig();
00831 SaveHotkeysToConfig();
00832 SaveToHighScore();
00833 }
00834
00835 exit:
00836
00837 ShutdownGame();
00838
00839 free(BaseGraphics::ini_set);
00840 free(BaseSounds::ini_set);
00841 free(BaseMusic::ini_set);
00842 free(_ini_musicdriver);
00843 free(_ini_sounddriver);
00844 free(_ini_videodriver);
00845 free(_ini_blitter);
00846
00847 return 0;
00848 }
00849
00850 void HandleExitGameRequest()
00851 {
00852 if (_game_mode == GM_MENU || _game_mode == GM_BOOTSTRAP) {
00853 _exit_game = true;
00854 } else if (_settings_client.gui.autosave_on_exit) {
00855 DoExitSave();
00856 _exit_game = true;
00857 } else {
00858 AskExitGame();
00859 }
00860 }
00861
00862 static void MakeNewGameDone()
00863 {
00864 SettingsDisableElrail(_settings_game.vehicle.disable_elrails);
00865
00866
00867 if (!_video_driver->HasGUI()) {
00868 SetLocalCompany(COMPANY_SPECTATOR);
00869 IConsoleCmdExec("exec scripts/game_start.scr 0");
00870 return;
00871 }
00872
00873
00874 DoStartupNewCompany(false);
00875
00876 Company *c = Company::Get(COMPANY_FIRST);
00877 c->settings = _settings_client.company;
00878
00879 IConsoleCmdExec("exec scripts/game_start.scr 0");
00880
00881 SetLocalCompany(COMPANY_FIRST);
00882
00883 InitializeRailGUI();
00884
00885 #ifdef ENABLE_NETWORK
00886
00887
00888 if (_network_server && !StrEmpty(_settings_client.network.default_company_pass)) {
00889 NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass);
00890 }
00891 #endif
00892
00893 if (_settings_client.gui.pause_on_newgame) DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE);
00894
00895 MarkWholeScreenDirty();
00896 }
00897
00898 static void MakeNewGame(bool from_heightmap, bool reset_settings)
00899 {
00900 _game_mode = GM_NORMAL;
00901
00902 ResetGRFConfig(true);
00903
00904 GenerateWorldSetCallback(&MakeNewGameDone);
00905 GenerateWorld(from_heightmap ? GWM_HEIGHTMAP : GWM_NEWGAME, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y, reset_settings);
00906 }
00907
00908 static void MakeNewEditorWorldDone()
00909 {
00910 SetLocalCompany(OWNER_NONE);
00911 }
00912
00913 static void MakeNewEditorWorld()
00914 {
00915 _game_mode = GM_EDITOR;
00916
00917 ResetGRFConfig(true);
00918
00919 GenerateWorldSetCallback(&MakeNewEditorWorldDone);
00920 GenerateWorld(GWM_EMPTY, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
00921 }
00922
00933 bool SafeLoad(const char *filename, int mode, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = NULL)
00934 {
00935 assert(mode == SL_LOAD || (lf == NULL && mode == SL_OLD_LOAD));
00936 GameMode ogm = _game_mode;
00937
00938 _game_mode = newgm;
00939
00940 switch (lf == NULL ? SaveOrLoad(filename, mode, subdir) : LoadWithFilter(lf)) {
00941 case SL_OK: return true;
00942
00943 case SL_REINIT:
00944 #ifdef ENABLE_NETWORK
00945 if (_network_dedicated) {
00946
00947
00948
00949
00950
00951
00952 DEBUG(net, 0, "Loading game failed, so a new (random) game will be started!");
00953 MakeNewGame(false, true);
00954 return false;
00955 }
00956 if (_network_server) {
00957
00958 NetworkDisconnect();
00959 }
00960 #endif
00961
00962 switch (ogm) {
00963 default:
00964 case GM_MENU: LoadIntroGame(); break;
00965 case GM_EDITOR: MakeNewEditorWorld(); break;
00966 }
00967 return false;
00968
00969 default:
00970 _game_mode = ogm;
00971 return false;
00972 }
00973 }
00974
00975 void SwitchToMode(SwitchMode new_mode)
00976 {
00977 #ifdef ENABLE_NETWORK
00978
00979 if (new_mode != SM_SAVE_GAME) {
00980
00981 if (_networking) {
00982 if (_network_server && (new_mode == SM_LOAD_GAME || new_mode == SM_NEWGAME || new_mode == SM_RESTARTGAME)) {
00983 NetworkReboot();
00984 } else {
00985 NetworkDisconnect();
00986 }
00987 }
00988
00989
00990 if (_is_network_server) {
00991
00992 if (new_mode != SM_MENU) {
00993
00994 if (_settings_client.network.reload_cfg) {
00995 LoadFromConfig();
00996 MakeNewgameSettingsLive();
00997 ResetGRFConfig(false);
00998 }
00999 NetworkServerStart();
01000 } else {
01001
01002 _is_network_server = false;
01003 }
01004 }
01005 }
01006 #endif
01007
01008 if (new_mode != SM_SAVE_GAME) AI::KillAll();
01009
01010 switch (new_mode) {
01011 case SM_EDITOR:
01012 MakeNewEditorWorld();
01013 break;
01014
01015 case SM_RESTARTGAME:
01016 case SM_NEWGAME:
01017 #ifdef ENABLE_NETWORK
01018 if (_network_server) {
01019 snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "Random Map");
01020 }
01021 #endif
01022 MakeNewGame(false, new_mode == SM_NEWGAME);
01023 break;
01024
01025 case SM_LOAD_GAME: {
01026 ResetGRFConfig(true);
01027 ResetWindowSystem();
01028
01029 if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL, NO_DIRECTORY)) {
01030 SetDParamStr(0, GetSaveLoadErrorString());
01031 ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
01032 } else {
01033 if (_saveload_mode == SLD_LOAD_SCENARIO) {
01034 StartupEngines();
01035 }
01036
01037
01038 SetLocalCompany(_network_dedicated ? COMPANY_SPECTATOR : COMPANY_FIRST);
01039
01040 IConsoleCmdExec("exec scripts/game_start.scr 0");
01041
01042 DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE);
01043 #ifdef ENABLE_NETWORK
01044 if (_network_server) {
01045 snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Loaded game)", _file_to_saveload.title);
01046 }
01047 #endif
01048 }
01049 break;
01050 }
01051
01052 case SM_START_HEIGHTMAP:
01053 #ifdef ENABLE_NETWORK
01054 if (_network_server) {
01055 snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Heightmap)", _file_to_saveload.title);
01056 }
01057 #endif
01058 MakeNewGame(true, true);
01059 break;
01060
01061 case SM_LOAD_HEIGHTMAP:
01062 SetLocalCompany(OWNER_NONE);
01063
01064 GenerateWorld(GWM_HEIGHTMAP, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
01065 MarkWholeScreenDirty();
01066 break;
01067
01068 case SM_LOAD_SCENARIO: {
01069 if (SafeLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR, NO_DIRECTORY)) {
01070 SetLocalCompany(OWNER_NONE);
01071 _settings_newgame.game_creation.starting_year = _cur_year;
01072
01073 DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE);
01074 } else {
01075 SetDParamStr(0, GetSaveLoadErrorString());
01076 ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
01077 }
01078 break;
01079 }
01080
01081 case SM_MENU:
01082 LoadIntroGame();
01083 if (BaseSounds::ini_set == NULL && BaseSounds::GetUsedSet()->fallback) {
01084 ShowErrorMessage(STR_WARNING_FALLBACK_SOUNDSET, INVALID_STRING_ID, WL_CRITICAL);
01085 BaseSounds::ini_set = strdup(BaseSounds::GetUsedSet()->name);
01086 }
01087 break;
01088
01089 case SM_SAVE_GAME:
01090
01091 if (SaveOrLoad(_file_to_saveload.name, SL_SAVE, NO_DIRECTORY) != SL_OK) {
01092 SetDParamStr(0, GetSaveLoadErrorString());
01093 ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
01094 } else {
01095 DeleteWindowById(WC_SAVELOAD, 0);
01096 }
01097 break;
01098
01099 case SM_SAVE_HEIGHTMAP:
01100 MakeHeightmapScreenshot(_file_to_saveload.name);
01101 DeleteWindowById(WC_SAVELOAD, 0);
01102 break;
01103
01104 case SM_GENRANDLAND:
01105 SetLocalCompany(OWNER_NONE);
01106 GenerateWorld(GWM_RANDOM, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
01107
01108 MarkWholeScreenDirty();
01109 break;
01110
01111 default: NOT_REACHED();
01112 }
01113
01114 if (_switch_mode_errorstr != INVALID_STRING_ID) {
01115 ShowErrorMessage(_switch_mode_errorstr, INVALID_STRING_ID, WL_CRITICAL);
01116 _switch_mode_errorstr = INVALID_STRING_ID;
01117 }
01118 }
01119
01120
01127 static void CheckCaches()
01128 {
01129
01130 SmallVector<CompanyInfrastructure, 4> old_infrastructure;
01131 Company *c;
01132 FOR_ALL_COMPANIES(c) MemCpyT(old_infrastructure.Append(), &c->infrastructure);
01133
01134 extern void AfterLoadCompanyStats();
01135 AfterLoadCompanyStats();
01136
01137 uint i = 0;
01138 FOR_ALL_COMPANIES(c) {
01139 if (MemCmpT(old_infrastructure.Get(i), &c->infrastructure) != 0) {
01140 DEBUG(desync, 2, "infrastructure cache mismatch: company %i", (int)c->index);
01141 }
01142 i++;
01143 }
01144
01145
01146
01147 if (_debug_desync_level <= 1) return;
01148
01149
01150 const RoadStop *rs;
01151 FOR_ALL_ROADSTOPS(rs) {
01152 if (IsStandardRoadStopTile(rs->xy)) continue;
01153
01154 assert(rs->GetEntry(DIAGDIR_NE) != rs->GetEntry(DIAGDIR_NW));
01155 rs->GetEntry(DIAGDIR_NE)->CheckIntegrity(rs);
01156 rs->GetEntry(DIAGDIR_NW)->CheckIntegrity(rs);
01157 }
01158
01159 Vehicle *v;
01160 FOR_ALL_VEHICLES(v) {
01161 extern void FillNewGRFVehicleCache(const Vehicle *v);
01162 if (v != v->First() || v->vehstatus & VS_CRASHED || !v->IsPrimaryVehicle()) continue;
01163
01164 uint length = 0;
01165 for (const Vehicle *u = v; u != NULL; u = u->Next()) length++;
01166
01167 NewGRFCache *grf_cache = CallocT<NewGRFCache>(length);
01168 VehicleCache *veh_cache = CallocT<VehicleCache>(length);
01169 GroundVehicleCache *gro_cache = CallocT<GroundVehicleCache>(length);
01170 TrainCache *tra_cache = CallocT<TrainCache>(length);
01171
01172 length = 0;
01173 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
01174 FillNewGRFVehicleCache(u);
01175 grf_cache[length] = u->grf_cache;
01176 veh_cache[length] = u->vcache;
01177 switch (u->type) {
01178 case VEH_TRAIN:
01179 gro_cache[length] = Train::From(u)->gcache;
01180 tra_cache[length] = Train::From(u)->tcache;
01181 break;
01182 case VEH_ROAD:
01183 gro_cache[length] = RoadVehicle::From(u)->gcache;
01184 break;
01185 default:
01186 break;
01187 }
01188 length++;
01189 }
01190
01191 switch (v->type) {
01192 case VEH_TRAIN: Train::From(v)->ConsistChanged(true); break;
01193 case VEH_ROAD: RoadVehUpdateCache(RoadVehicle::From(v)); break;
01194 case VEH_AIRCRAFT: UpdateAircraftCache(Aircraft::From(v)); break;
01195 case VEH_SHIP: Ship::From(v)->UpdateCache(); break;
01196 default: break;
01197 }
01198
01199 length = 0;
01200 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
01201 FillNewGRFVehicleCache(u);
01202 if (memcmp(&grf_cache[length], &u->grf_cache, sizeof(NewGRFCache)) != 0) {
01203 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);
01204 }
01205 if (memcmp(&veh_cache[length], &u->vcache, sizeof(VehicleCache)) != 0) {
01206 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);
01207 }
01208 switch (u->type) {
01209 case VEH_TRAIN:
01210 if (memcmp(&gro_cache[length], &Train::From(u)->gcache, sizeof(GroundVehicleCache)) != 0) {
01211 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);
01212 }
01213 if (memcmp(&tra_cache[length], &Train::From(u)->tcache, sizeof(TrainCache)) != 0) {
01214 DEBUG(desync, 2, "train cache mismatch: vehicle %i, company %i, unit number %i, wagon %i", v->index, (int)v->owner, v->unitnumber, length);
01215 }
01216 break;
01217 case VEH_ROAD:
01218 if (memcmp(&gro_cache[length], &RoadVehicle::From(u)->gcache, sizeof(GroundVehicleCache)) != 0) {
01219 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);
01220 }
01221 break;
01222 default:
01223 break;
01224 }
01225 length++;
01226 }
01227
01228 free(grf_cache);
01229 free(veh_cache);
01230 free(gro_cache);
01231 free(tra_cache);
01232 }
01233
01234
01235 FOR_ALL_VEHICLES(v) {
01236 byte buff[sizeof(VehicleCargoList)];
01237 memcpy(buff, &v->cargo, sizeof(VehicleCargoList));
01238 v->cargo.InvalidateCache();
01239 assert(memcmp(&v->cargo, buff, sizeof(VehicleCargoList)) == 0);
01240 }
01241
01242 Station *st;
01243 FOR_ALL_STATIONS(st) {
01244 for (CargoID c = 0; c < NUM_CARGO; c++) {
01245 byte buff[sizeof(StationCargoList)];
01246 memcpy(buff, &st->goods[c].cargo, sizeof(StationCargoList));
01247 st->goods[c].cargo.InvalidateCache();
01248 assert(memcmp(&st->goods[c].cargo, buff, sizeof(StationCargoList)) == 0);
01249 }
01250 }
01251 }
01252
01258 void StateGameLoop()
01259 {
01260
01261 if (_pause_mode != PM_UNPAUSED) {
01262 UpdateLandscapingLimits();
01263 CallWindowTickEvent();
01264 return;
01265 }
01266 if (HasModalProgress()) return;
01267
01268 ClearStorageChanges(false);
01269
01270 if (_game_mode == GM_EDITOR) {
01271 RunTileLoop();
01272 CallVehicleTicks();
01273 CallLandscapeTick();
01274 ClearStorageChanges(true);
01275 UpdateLandscapingLimits();
01276
01277 CallWindowTickEvent();
01278 NewsLoop();
01279 } else {
01280 if (_debug_desync_level > 2 && _date_fract == 0 && (_date & 0x1F) == 0) {
01281
01282 char name[MAX_PATH];
01283 snprintf(name, lengthof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
01284 SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR, false);
01285 }
01286
01287 CheckCaches();
01288
01289
01290
01291 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
01292
01293 AnimateAnimatedTiles();
01294 IncreaseDate();
01295 RunTileLoop();
01296 CallVehicleTicks();
01297 CallLandscapeTick();
01298 ClearStorageChanges(true);
01299
01300 AI::GameLoop();
01301 UpdateLandscapingLimits();
01302
01303 CallWindowTickEvent();
01304 NewsLoop();
01305 cur_company.Restore();
01306 }
01307
01308 assert(IsLocalCompany());
01309 }
01310
01315 static void DoAutosave()
01316 {
01317 char buf[MAX_PATH];
01318
01319 #if defined(PSP)
01320
01321 if (_networking) return;
01322 #endif
01323
01324 if (_settings_client.gui.keep_all_autosave) {
01325 GenerateDefaultSaveName(buf, lastof(buf));
01326 strecat(buf, ".sav", lastof(buf));
01327 } else {
01328 static int _autosave_ctr = 0;
01329
01330
01331 snprintf(buf, sizeof(buf), "autosave%d.sav", _autosave_ctr);
01332
01333 if (++_autosave_ctr >= _settings_client.gui.max_num_autosaves) _autosave_ctr = 0;
01334 }
01335
01336 DEBUG(sl, 2, "Autosaving to '%s'", buf);
01337 if (SaveOrLoad(buf, SL_SAVE, AUTOSAVE_DIR) != SL_OK) {
01338 ShowErrorMessage(STR_ERROR_AUTOSAVE_FAILED, INVALID_STRING_ID, WL_ERROR);
01339 }
01340 }
01341
01342 void GameLoop()
01343 {
01344 if (_game_mode == GM_BOOTSTRAP) {
01345 #ifdef ENABLE_NETWORK
01346
01347 if (_network_available) NetworkUDPGameLoop();
01348 #endif
01349 InputLoop();
01350 return;
01351 }
01352
01353 ProcessAsyncSaveFinish();
01354
01355
01356 if (_do_autosave) {
01357 _do_autosave = false;
01358 DoAutosave();
01359 SetWindowDirty(WC_STATUS_BAR, 0);
01360 }
01361
01362
01363 if (_switch_mode != SM_NONE && !HasModalProgress()) {
01364 SwitchToMode(_switch_mode);
01365 _switch_mode = SM_NONE;
01366 }
01367
01368 IncreaseSpriteLRU();
01369 InteractiveRandom();
01370
01371 extern int _caret_timer;
01372 _caret_timer += 3;
01373 CursorTick();
01374
01375 #ifdef ENABLE_NETWORK
01376
01377 if (_network_available) NetworkUDPGameLoop();
01378
01379 if (_networking && !HasModalProgress()) {
01380
01381 NetworkGameLoop();
01382 } else {
01383 if (_network_reconnect > 0 && --_network_reconnect == 0) {
01384
01385
01386 NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), COMPANY_SPECTATOR);
01387 }
01388
01389 StateGameLoop();
01390 }
01391
01392
01393 static uint check_message = 0;
01394 if (++check_message > 1000 / MILLISECONDS_PER_TICK) {
01395 check_message = 0;
01396 NetworkChatMessageLoop();
01397 }
01398 #else
01399 StateGameLoop();
01400 #endif
01401
01402 if (!_pause_mode && HasBit(_display_opt, DO_FULL_ANIMATION)) DoPaletteAnimations();
01403
01404 if (!_pause_mode || _game_mode == GM_EDITOR || _settings_game.construction.command_pause_level > CMDPL_NO_CONSTRUCTION) MoveAllTextEffects();
01405
01406 InputLoop();
01407
01408 _sound_driver->MainLoop();
01409 MusicLoop();
01410 }