truelight@0: #include "stdafx.h" tron@507: #include "table/strings.h" tron@679: #include "map.h" truelight@0: truelight@0: #define VARDEF truelight@0: #include "ttd.h" truelight@0: #include "gfx.h" truelight@0: #include "gui.h" truelight@0: #include "station.h" truelight@0: #include "vehicle.h" truelight@0: #include "viewport.h" truelight@0: #include "window.h" truelight@0: #include "player.h" truelight@0: #include "command.h" truelight@0: #include "town.h" truelight@0: #include "industry.h" truelight@0: #include "news.h" truelight@0: #include "engine.h" truelight@0: #include "sound.h" truelight@0: #include "economy.h" truelight@0: #include "fileio.h" truelight@0: #include "hal.h" truelight@0: #include "airport.h" truelight@0: #include "saveload.h" truelight@139: #include "ai.h" dominik@126: #include "console.h" tron@430: #include "screenshot.h" truelight@543: #include "network.h" truelight@0: truelight@0: #include truelight@0: truelight@0: void GameLoop(); truelight@0: truelight@0: void IncreaseSpriteLRU(); truelight@0: void InitializeGame(); truelight@0: void GenerateWorld(int mode); truelight@0: void CallLandscapeTick(); truelight@0: void IncreaseDate(); truelight@0: void RunOtherPlayersLoop(); truelight@0: void DoPaletteAnimations(); truelight@0: void MusicLoop(); truelight@0: void ResetMusic(); truelight@0: void InitializeStations(); truelight@0: void DeleteAllPlayerStations(); truelight@0: truelight@0: extern void SetDifficultyLevel(int mode, GameOptions *gm_opt); truelight@0: extern void DoStartupNewPlayer(bool is_ai); truelight@0: extern void UpdateAllSignVirtCoords(); truelight@0: extern void ShowOSErrorBox(const char *buf); truelight@0: truelight@0: void redsq_debug(int tile); truelight@0: bool LoadSavegame(const char *filename); truelight@0: truelight@0: extern void HalGameLoop(); truelight@0: truelight@0: uint32 _pixels_redrawn; truelight@0: bool _dbg_screen_rect; truelight@543: bool disable_computer; // We should get ride of this thing.. is only used for a debug-cheat darkvater@223: static byte _os_version = 0; truelight@0: truelight@0: void CDECL error(const char *s, ...) { truelight@0: va_list va; truelight@0: char buf[512]; truelight@0: va_start(va, s); truelight@0: vsprintf(buf, s, va); truelight@0: va_end(va); truelight@193: truelight@0: ShowOSErrorBox(buf); truelight@0: if (_video_driver) truelight@0: _video_driver->stop(); truelight@0: truelight@0: assert(0); truelight@0: exit(1); truelight@0: } truelight@0: truelight@0: void CDECL debug(const char *s, ...) truelight@0: { truelight@0: va_list va; truelight@0: char buf[1024]; truelight@0: va_start(va, s); truelight@0: vsprintf(buf, s, va); truelight@0: va_end(va); truelight@139: fprintf(stderr, "dbg: %s\n", buf); dominik@126: IConsoleDebug((byte *) &buf); truelight@0: } truelight@0: truelight@0: void CDECL ShowInfoF(const char *str, ...) truelight@0: { truelight@0: va_list va; truelight@0: char buf[1024]; truelight@0: va_start(va, str); truelight@0: vsprintf(buf, str, va); truelight@0: va_end(va); truelight@0: ShowInfo(buf); truelight@0: } truelight@0: truelight@0: char * CDECL str_fmt(const char *str, ...) truelight@0: { truelight@0: char buf[4096]; truelight@0: va_list va; truelight@0: int len; truelight@0: char *p; truelight@0: truelight@0: va_start(va, str); truelight@0: len = vsprintf(buf, str, va); truelight@0: va_end(va); truelight@0: p = malloc(len + 1); truelight@0: if (p) truelight@0: memcpy(p, buf, len + 1); truelight@0: return p; truelight@0: } truelight@0: truelight@0: truelight@0: // NULL midi driver truelight@0: static char *NullMidiStart(char **parm) { return NULL; } truelight@0: static void NullMidiStop() {} truelight@0: static void NullMidiPlaySong(const char *filename) {} truelight@0: static void NullMidiStopSong() {} truelight@0: static bool NullMidiIsSongPlaying() { return true; } truelight@0: static void NullMidiSetVolume(byte vol) {} truelight@0: truelight@0: const HalMusicDriver _null_music_driver = { truelight@0: NullMidiStart, truelight@0: NullMidiStop, truelight@0: NullMidiPlaySong, truelight@0: NullMidiStopSong, truelight@0: NullMidiIsSongPlaying, truelight@0: NullMidiSetVolume, truelight@0: }; truelight@0: truelight@0: // NULL video driver truelight@0: static void *_null_video_mem; truelight@0: static const char *NullVideoStart(char **parm) { truelight@0: _screen.width = _screen.pitch = _cur_resolution[0]; truelight@0: _screen.height = _cur_resolution[1]; truelight@0: _null_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]); truelight@0: return NULL; truelight@0: } truelight@0: static void NullVideoStop() { free(_null_video_mem); } truelight@0: static void NullVideoMakeDirty(int left, int top, int width, int height) {} truelight@0: static int NullVideoMainLoop() { truelight@0: int i = 1000; truelight@0: do { truelight@0: GameLoop(); truelight@0: _screen.dst_ptr = _null_video_mem; truelight@0: UpdateWindows(); truelight@0: } while (--i); truelight@0: return ML_QUIT; truelight@0: } truelight@0: truelight@0: static bool NullVideoChangeRes(int w, int h) { return false; } truelight@0: truelight@193: truelight@0: const HalVideoDriver _null_video_driver = { truelight@0: NullVideoStart, truelight@0: NullVideoStop, truelight@0: NullVideoMakeDirty, truelight@0: NullVideoMainLoop, truelight@0: NullVideoChangeRes, truelight@0: }; truelight@0: truelight@0: // NULL sound driver truelight@0: static char *NullSoundStart(char **parm) { return NULL; } truelight@0: static void NullSoundStop() {} truelight@0: const HalSoundDriver _null_sound_driver = { truelight@0: NullSoundStart, truelight@0: NullSoundStop, truelight@0: }; truelight@0: truelight@0: enum { truelight@0: DF_PRIORITY_MASK = 0xf, truelight@0: }; truelight@0: truelight@0: typedef struct { truelight@0: const DriverDesc *descs; truelight@0: const char *name; truelight@0: void *var; truelight@0: } DriverClass; truelight@0: truelight@0: static DriverClass _driver_classes[] = { truelight@0: {_video_driver_descs, "video", &_video_driver}, truelight@0: {_sound_driver_descs, "sound", &_sound_driver}, truelight@0: {_music_driver_descs, "music", &_music_driver}, truelight@0: }; truelight@0: truelight@0: static const DriverDesc *GetDriverByName(const DriverDesc *dd, const char *name) truelight@0: { truelight@0: do { truelight@0: if (!strcmp(dd->name, name)) truelight@0: return dd; truelight@0: } while ((++dd)->name); truelight@0: return NULL; truelight@0: } truelight@0: truelight@0: static const DriverDesc *ChooseDefaultDriver(const DriverDesc *dd) truelight@0: { truelight@0: const DriverDesc *best = NULL; truelight@0: int best_pri = -1; truelight@0: do { darkvater@223: if ((int)(dd->flags&DF_PRIORITY_MASK) > best_pri && _os_version >= (byte)dd->flags) { truelight@0: best_pri = dd->flags&DF_PRIORITY_MASK; truelight@0: best = dd; truelight@0: } truelight@0: } while ((++dd)->name); truelight@0: return best; truelight@0: } truelight@0: truelight@0: void ttd_strlcpy(char *dst, const char *src, size_t len) truelight@0: { truelight@0: assert(len > 0); truelight@0: while (--len && *src) truelight@0: *dst++=*src++; truelight@0: *dst = 0; truelight@0: } truelight@0: truelight@0: char *strecpy(char *dst, const char *src) truelight@0: { truelight@0: while ( (*dst++ = *src++) != 0) {} truelight@0: return dst - 1; truelight@0: } truelight@0: truelight@0: byte *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize) truelight@0: { truelight@0: FILE *in; truelight@0: void *mem; truelight@0: size_t len; truelight@0: truelight@0: in = fopen(filename, "rb"); truelight@0: if (in == NULL) truelight@0: return NULL; truelight@0: truelight@0: fseek(in, 0, SEEK_END); truelight@0: len = ftell(in); truelight@0: fseek(in, 0, SEEK_SET); truelight@0: if (len > maxsize || (mem=(byte*)malloc(len + 1)) == NULL) { truelight@0: fclose(in); truelight@0: return NULL; truelight@0: } truelight@0: ((byte*)mem)[len] = 0; truelight@0: if (fread(mem, len, 1, in) != 1) { truelight@0: fclose(in); truelight@0: free(mem); truelight@0: return NULL; truelight@0: } truelight@0: fclose(in); truelight@0: truelight@0: *lenp = len; truelight@0: return mem; truelight@0: } truelight@0: truelight@0: void LoadDriver(int driver, const char *name) truelight@0: { truelight@0: const DriverClass *dc = &_driver_classes[driver]; truelight@0: const DriverDesc *dd; truelight@0: const void **var; truelight@0: const void *drv; truelight@0: const char *err; truelight@0: char *parm; truelight@0: char buffer[256]; truelight@0: char *parms[32]; truelight@0: truelight@0: parms[0] = NULL; truelight@0: truelight@0: if (!*name) { truelight@0: dd = ChooseDefaultDriver(dc->descs); truelight@0: } else { truelight@0: // Extract the driver name and put parameter list in parm truelight@0: ttd_strlcpy(buffer, name, sizeof(buffer)); truelight@0: parm = strchr(buffer, ':'); truelight@0: if (parm) { truelight@0: int np = 0; truelight@0: // Tokenize the parm. truelight@0: do { truelight@0: *parm++ = 0; truelight@0: if (np < lengthof(parms) - 1) truelight@0: parms[np++] = parm; truelight@0: while (*parm != 0 && *parm != ',') truelight@0: parm++; truelight@0: } while (*parm == ','); truelight@0: parms[np] = NULL; truelight@0: } truelight@0: dd = GetDriverByName(dc->descs, buffer); truelight@0: if (dd == NULL) truelight@0: error("No such %s driver: %s\n", dc->name, buffer); truelight@0: } truelight@0: var = dc->var; darkvater@222: if (*var != NULL) ((const HalCommonDriver*)*var)->stop(); truelight@0: *var = NULL; truelight@0: drv = dd->drv; darkvater@222: if ((err=((const HalCommonDriver*)drv)->start(parms)) != NULL) truelight@0: error("Unable to load driver %s(%s). The error was: %s\n", dd->name, dd->longname, err); truelight@0: *var = drv; truelight@0: } truelight@0: truelight@0: static void showhelp() truelight@0: { truelight@0: char buf[4096], *p; truelight@0: const DriverClass *dc = _driver_classes; truelight@0: const DriverDesc *dd; truelight@0: int i; truelight@0: truelight@193: p = strecpy(buf, truelight@0: "Command line options:\n" truelight@543: " -v drv = Set video driver (see below)\n" truelight@543: " -s drv = Set sound driver (see below)\n" truelight@543: " -m drv = Set music driver (see below)\n" truelight@543: " -r res = Set resolution (for instance 800x600)\n" truelight@543: " -h = Display this help text\n" truelight@543: " -t date = Set starting date\n" truelight@543: " -d [dbg] = Debug mode\n" truelight@543: " -l lng = Select Language\n" truelight@543: " -e = Start Editor\n" truelight@543: " -g [savegame] = Start new/save game immediately\n" truelight@543: " -G seed = Set random seed\n" truelight@543: " -n [ip#player:port] = Start networkgame\n" truelight@543: " -D = Start dedicated server\n" bjarni@770: #if !defined(__MORPHOS__) && !defined(__AMIGA__) truelight@704: " -f = Fork into the background (dedicated only)\n" bjarni@770: #endif dominik@614: " -i = Force to use the DOS palette (use this if you see a lot of pink)\n" truelight@543: " -p #player = Player as #player (deprecated) (network only)\n" truelight@0: ); truelight@0: truelight@193: for(i=0; i!=lengthof(_driver_classes); i++,dc++) { truelight@0: p += sprintf(p, "List of %s drivers:\n", dc->name); truelight@0: dd = dc->descs; truelight@0: do { truelight@0: p += sprintf(p, "%10s: %s\n", dd->name, dd->longname); truelight@0: } while ((++dd)->name); truelight@0: } truelight@0: truelight@0: ShowInfo(buf); truelight@0: } truelight@0: truelight@0: truelight@0: char *GetDriverParam(char **parm, const char *name) truelight@0: { truelight@0: char *p; truelight@0: int len = strlen(name); truelight@0: while ((p = *parm++) != NULL) { truelight@0: if (!strncmp(p,name,len)) { truelight@0: if (p[len] == '=') return p + len + 1; truelight@0: if (p[len] == 0) return p + len; truelight@0: } truelight@0: } truelight@0: return NULL; truelight@0: } truelight@0: truelight@0: bool GetDriverParamBool(char **parm, const char *name) truelight@0: { truelight@0: char *p = GetDriverParam(parm, name); truelight@0: return p != NULL; truelight@0: } truelight@0: truelight@0: int GetDriverParamInt(char **parm, const char *name, int def) truelight@0: { truelight@0: char *p = GetDriverParam(parm, name); truelight@0: return p != NULL ? atoi(p) : def; truelight@0: } truelight@0: truelight@0: typedef struct { truelight@0: char *opt; truelight@0: int numleft; truelight@0: char **argv; truelight@0: const char *options; truelight@0: char *cont; truelight@0: } MyGetOptData; truelight@0: truelight@0: static void MyGetOptInit(MyGetOptData *md, int argc, char **argv, const char *options) truelight@0: { truelight@0: md->cont = NULL; truelight@0: md->numleft = argc; truelight@0: md->argv = argv; truelight@0: md->options = options; truelight@0: } truelight@0: truelight@0: static int MyGetOpt(MyGetOptData *md) truelight@0: { truelight@0: char *s,*r,*t; truelight@0: truelight@0: if ((s=md->cont) != NULL) truelight@0: goto md_continue_here; truelight@0: truelight@0: while(true) { truelight@0: if (--md->numleft < 0) truelight@0: return -1; truelight@0: truelight@0: s = *md->argv++; truelight@0: if (*s == '-') { truelight@0: md_continue_here:; truelight@0: s++; truelight@0: if (*s != 0) { truelight@0: // Found argument, try to locate it in options. truelight@0: if (*s == ':' || (r = strchr(md->options, *s)) == NULL) { truelight@0: // ERROR! truelight@0: return -2; truelight@0: } truelight@0: if (r[1] == ':') { truelight@0: // Item wants an argument. Check if the argument follows, or if it comes as a separate arg. truelight@0: if (!*(t = s + 1)) { truelight@0: // It comes as a separate arg. Check if out of args? truelight@0: if (--md->numleft < 0 || *(t = *md->argv) == '-') { truelight@0: // Check if item is optional? truelight@0: if (r[2] != ':') truelight@0: return -2; truelight@0: md->numleft++; truelight@0: t = NULL; truelight@0: } else { truelight@0: md->argv++; truelight@0: } truelight@0: } truelight@0: md->opt = t; truelight@0: md->cont = NULL; truelight@0: return *s; truelight@0: } truelight@0: md->opt = NULL; truelight@0: md->cont = s; truelight@0: return *s; truelight@0: } truelight@0: } else { truelight@0: // This is currently not supported. truelight@0: return -2; truelight@0: } truelight@0: } truelight@0: } truelight@0: truelight@0: void SetDebugString(const char *s) truelight@0: { truelight@0: int v; truelight@0: char *end; truelight@0: const char *t; truelight@0: int *p; truelight@0: truelight@0: // global debugging level? truelight@0: if (*s >= '0' && *s <= '9') { truelight@0: v = strtoul(s, &end, 0); truelight@0: s = end; truelight@193: truelight@0: _debug_spritecache_level = v; truelight@0: _debug_misc_level = v; darkvater@65: _debug_grf_level = v; truelight@84: _debug_ai_level = v; truelight@185: _debug_net_level = v; truelight@0: } truelight@0: truelight@0: // individual levels truelight@0: for(;;) { truelight@0: // skip delimiters truelight@0: while (*s == ' ' || *s == ',' || *s == '\t') s++; truelight@0: if (*s == 0) break; truelight@0: truelight@0: t = s; truelight@0: while (*s >= 'a' && *s <= 'z') s++; truelight@0: truelight@0: #define IS_LVL(x) (s - t == sizeof(x)-1 && !memcmp(t, x, sizeof(x)-1)) truelight@0: // check debugging levels truelight@0: if IS_LVL("misc") p = &_debug_misc_level; truelight@0: else if IS_LVL("spritecache") p = &_debug_spritecache_level; darkvater@65: else if IS_LVL("grf") p = &_debug_grf_level; truelight@84: else if IS_LVL("ai") p = &_debug_ai_level; truelight@185: else if IS_LVL("net") p = &_debug_net_level; truelight@0: else { truelight@0: ShowInfoF("Unknown debug level '%.*s'", s-t, t); truelight@0: return; truelight@0: } truelight@0: #undef IS_LVL truelight@0: if (*s == '=') s++; truelight@0: v = strtoul(s, &end, 0); truelight@0: s = end; truelight@0: if (p) *p = v; truelight@193: } truelight@0: } truelight@0: truelight@0: void ParseResolution(int res[2], char *s) truelight@0: { truelight@0: char *t = strchr(s, 'x'); truelight@0: if (t == NULL) { truelight@0: ShowInfoF("Invalid resolution '%s'", s); truelight@0: return; truelight@0: } truelight@0: darkvater@310: res[0] = strtoul(s, NULL, 0); darkvater@310: res[1] = strtoul(t + 1, NULL, 0); truelight@193: } truelight@0: truelight@543: void LoadIntroGame() truelight@543: { truelight@543: char filename[256]; truelight@543: _game_mode = GM_MENU; truelight@543: _display_opt &= ~DO_TRANS_BUILDINGS; // don't make buildings transparent in intro truelight@543: truelight@543: _opt_mod_ptr = &_new_opt; truelight@543: GfxLoadSprites(); truelight@543: LoadStringWidthTable(); truelight@543: truelight@543: // Setup main window truelight@543: InitWindowSystem(); truelight@543: SetupColorsAndInitialWindow(); truelight@543: truelight@543: // Generate a world. truelight@543: sprintf(filename, "%sopntitle.dat", _path.data_dir); truelight@543: if (SaveOrLoad(filename, SL_LOAD) != SL_OK) bjarni@561: #if defined SECOND_DATA_DIR bjarni@561: { bjarni@561: sprintf(filename, "%sopntitle.dat", _path.second_data_dir); bjarni@561: if (SaveOrLoad(filename, SL_LOAD) != SL_OK) bjarni@561: #endif bjarni@561: GenerateWorld(1); // if failed loading, make empty world. bjarni@561: #if defined SECOND_DATA_DIR bjarni@561: } bjarni@561: #endif truelight@543: _opt.currency = _new_opt.currency; truelight@543: truelight@543: _pause = 0; truelight@543: _local_player = 0; truelight@543: MarkWholeScreenDirty(); truelight@543: truelight@543: // Play main theme truelight@543: if (_music_driver->is_song_playing()) ResetMusic(); truelight@543: } truelight@543: darkvater@774: extern void DedicatedFork(void); truelight@704: truelight@0: int ttd_main(int argc, char* argv[]) truelight@0: { truelight@0: MyGetOptData mgo; truelight@0: int i; truelight@543: bool network = false; truelight@0: char *network_conn = NULL; truelight@0: char *language = NULL; bjarni@770: char *optformat; truelight@469: char musicdriver[16], sounddriver[16], videodriver[16]; truelight@0: int resolution[2] = {0,0}; truelight@0: uint startdate = -1; truelight@0: musicdriver[0] = sounddriver[0] = videodriver[0] = 0; truelight@0: truelight@0: _game_mode = GM_MENU; truelight@0: _switch_mode = SM_MENU; darkvater@172: _switch_mode_errorstr = INVALID_STRING_ID; truelight@704: _dedicated_forks = false; truelight@704: _dedicated_enabled = false; truelight@0: truelight@543: // The last param of the following function means this: truelight@543: // a letter means: it accepts that param (e.g.: -h) truelight@543: // a ':' behind it means: it need a param (e.g.: -m) truelight@543: // a '::' behind it means: it can optional have a param (e.g.: -d) bjarni@770: #if !defined(__MORPHOS__) && !defined(__AMIGA__) bjarni@770: optformat = "m:s:v:hDfn::l:eit:d::r:g::G:p:"; bjarni@770: #else bjarni@770: optformat = "m:s:v:hDn::l:eit:d::r:g::G:p:"; // no fork option bjarni@770: #endif bjarni@770: bjarni@770: MyGetOptInit(&mgo, argc-1, argv+1, optformat); truelight@0: while ((i = MyGetOpt(&mgo)) != -1) { truelight@0: switch(i) { truelight@0: case 'm': ttd_strlcpy(musicdriver, mgo.opt, sizeof(musicdriver)); break; truelight@0: case 's': ttd_strlcpy(sounddriver, mgo.opt, sizeof(sounddriver)); break; truelight@0: case 'v': ttd_strlcpy(videodriver, mgo.opt, sizeof(videodriver)); break; truelight@543: case 'D': { truelight@543: sprintf(musicdriver,"null"); truelight@543: sprintf(sounddriver,"null"); truelight@543: sprintf(videodriver,"dedicated"); truelight@704: _dedicated_enabled = true; truelight@543: } break; truelight@704: case 'f': { truelight@704: _dedicated_forks = true; truelight@704: }; break; darkvater@1: case 'n': { truelight@543: network = true; truelight@543: if (mgo.opt) truelight@543: // Optional, you can give an IP truelight@193: network_conn = mgo.opt; darkvater@1: else darkvater@1: network_conn = NULL; darkvater@1: } break; truelight@0: case 'r': ParseResolution(resolution, mgo.opt); break; truelight@0: case 'l': { truelight@0: language = mgo.opt; truelight@0: } break; truelight@0: case 't': { truelight@0: startdate = atoi(mgo.opt); truelight@0: } break; truelight@0: case 'd': { truelight@0: #if defined(WIN32) truelight@0: CreateConsole(); truelight@0: #endif truelight@0: if (mgo.opt) truelight@0: SetDebugString(mgo.opt); truelight@0: } break; truelight@0: case 'e': _switch_mode = SM_EDITOR; break; dominik@614: case 'i': _use_dos_palette = true; break; truelight@193: case 'g': truelight@0: if (mgo.opt) { truelight@0: strcpy(_file_to_saveload.name, mgo.opt); truelight@0: _switch_mode = SM_LOAD; truelight@0: } else truelight@0: _switch_mode = SM_NEWGAME; truelight@0: break; truelight@0: case 'G': signde@206: _random_seeds[0][0] = atoi(mgo.opt); truelight@0: break; truelight@0: case 'p': { truelight@0: int i = atoi(mgo.opt); truelight@543: // Play as an other player in network games truelight@543: if (IS_INT_INSIDE(i, 1, MAX_PLAYERS)) _network_playas = i; truelight@0: break; truelight@0: } truelight@0: case -2: truelight@0: case 'h': truelight@0: showhelp(); truelight@0: return 0; truelight@0: } truelight@0: } truelight@0: truelight@0: DeterminePaths(); truelight@704: truelight@704: #ifdef UNIX truelight@704: // We must fork here, or we'll end up without some resources we need (like sockets) truelight@704: if (_dedicated_forks) truelight@704: DedicatedFork(); truelight@704: #endif truelight@704: truelight@0: LoadFromConfig(); truelight@0: truelight@0: // override config? truelight@469: if (musicdriver[0]) ttd_strlcpy(_ini_musicdriver, musicdriver, sizeof(_ini_musicdriver)); truelight@469: if (sounddriver[0]) ttd_strlcpy(_ini_sounddriver, sounddriver, sizeof(_ini_sounddriver)); truelight@469: if (videodriver[0]) ttd_strlcpy(_ini_videodriver, videodriver, sizeof(_ini_videodriver)); truelight@0: if (resolution[0]) { _cur_resolution[0] = resolution[0]; _cur_resolution[1] = resolution[1]; } truelight@0: if (startdate != -1) _patches.starting_date = startdate; truelight@0: truelight@704: if (_dedicated_forks && !_dedicated_enabled) truelight@704: _dedicated_forks = false; truelight@704: truelight@0: // enumerate language files truelight@0: InitializeLanguagePacks(); truelight@0: truelight@0: // initialize screenshot formats truelight@0: InitializeScreenshotFormats(); truelight@0: dominik@105: // initialize airport state machines dominik@105: InitializeAirports(); truelight@193: truelight@0: // Sample catalogue truelight@0: DEBUG(misc, 1) ("Loading sound effects..."); darkvater@223: _os_version = GetOSVersion(); truelight@193: MxInitialize(11025, "sample.cat"); truelight@0: truelight@0: // This must be done early, since functions use the InvalidateWindow* calls truelight@139: InitWindowSystem(); truelight@0: truelight@0: GfxLoadSprites(); truelight@0: LoadStringWidthTable(); truelight@0: truelight@0: DEBUG(misc, 1) ("Loading drivers..."); truelight@0: LoadDriver(SOUND_DRIVER, _ini_sounddriver); truelight@0: LoadDriver(MUSIC_DRIVER, _ini_musicdriver); truelight@0: LoadDriver(VIDEO_DRIVER, _ini_videodriver); // load video last, to prevent an empty window while sound and music loads truelight@0: MusicLoop(); darkvater@168: _savegame_sort_order = 1; // default sorting of savegames is by date, newest first truelight@0: truelight@543: #ifdef ENABLE_NETWORK truelight@543: // initialize network-core truelight@543: NetworkStartUp(); truelight@543: #endif /* ENABLE_NETWORK */ truelight@543: truelight@0: // Default difficulty level truelight@0: _opt_mod_ptr = &_new_opt; truelight@193: truelight@0: // ugly hack, if diff_level is 9, it means we got no setting from the config file, so we load the default settings. truelight@0: if (_opt_mod_ptr->diff_level == 9) truelight@0: SetDifficultyLevel(0, _opt_mod_ptr); truelight@0: truelight@139: // initialize the ingame console truelight@139: IConsoleInit(); dominik@644: IConsoleCmdExec("exec scripts/autoexec.scr 0"); truelight@656: signde@206: InitPlayerRandoms(); truelight@0: truelight@543: #ifdef ENABLE_NETWORK truelight@543: if ((network) && (_network_available)) { truelight@543: if (network_conn != NULL) { truelight@543: const byte *port = NULL; truelight@543: const byte *player = NULL; truelight@543: uint16 rport; truelight@543: truelight@543: rport = NETWORK_DEFAULT_PORT; truelight@543: truelight@543: ParseConnectionString(&player, &port, network_conn); truelight@543: truelight@543: if (player != NULL) _network_playas = atoi(player); truelight@543: if (port != NULL) rport = atoi(port); truelight@543: truelight@543: LoadIntroGame(); truelight@543: _switch_mode = SM_NONE; truelight@543: NetworkClientConnectGame(network_conn, rport); truelight@543: } else { truelight@543: // NetworkCoreConnectGame("auto", _network_server_port); truelight@543: } truelight@543: } truelight@543: #endif /* ENABLE_NETWORK */ truelight@543: truelight@0: while (_video_driver->main_loop() == ML_SWITCHDRIVER) {} truelight@139: truelight@139: IConsoleFree(); truelight@0: truelight@543: #ifdef ENABLE_NETWORK dominik@105: if (_network_available) { truelight@543: // Shut down the network and close any open connections truelight@543: NetworkDisconnect(); truelight@543: NetworkUDPClose(); truelight@543: NetworkShutDown(); truelight@543: } truelight@543: #endif /* ENABLE_NETWORK */ truelight@0: truelight@0: _video_driver->stop(); truelight@0: _music_driver->stop(); truelight@0: _sound_driver->stop(); truelight@0: truelight@0: SaveToConfig(); truelight@0: dominik@105: // uninitialize airport state machines dominik@105: UnInitializeAirports(); truelight@0: truelight@0: return 0; truelight@0: } truelight@0: truelight@0: static void ShowScreenshotResult(bool b) truelight@0: { truelight@0: if (b) { tron@534: SetDParam(0, STR_SPEC_SCREENSHOT_NAME); truelight@0: ShowErrorMessage(INVALID_STRING_ID, STR_031B_SCREENSHOT_SUCCESSFULLY, 0, 0); truelight@0: } else { truelight@0: ShowErrorMessage(INVALID_STRING_ID, STR_031C_SCREENSHOT_FAILED, 0, 0); truelight@0: } truelight@0: truelight@0: } truelight@0: truelight@0: void MakeNewGame() truelight@0: { truelight@0: _game_mode = GM_NORMAL; truelight@0: truelight@0: // Copy in game options truelight@0: _opt_mod_ptr = &_opt; truelight@0: memcpy(&_opt, &_new_opt, sizeof(_opt)); truelight@0: truelight@0: GfxLoadSprites(); truelight@0: dominik@136: // Reinitialize windows truelight@0: InitWindowSystem(); truelight@0: LoadStringWidthTable(); truelight@0: truelight@0: SetupColorsAndInitialWindow(); truelight@0: truelight@0: // Randomize world truelight@0: GenerateWorld(0); truelight@0: truelight@543: // In a dedicated server, the server does not play truelight@543: if (_network_dedicated) { truelight@543: _local_player = OWNER_SPECTATOR; truelight@543: } else { truelight@543: // Create a single player truelight@543: DoStartupNewPlayer(false); truelight@193: truelight@543: _local_player = 0; truelight@543: } truelight@0: truelight@0: MarkWholeScreenDirty(); truelight@0: } truelight@0: tron@410: static void MakeNewEditorWorld() truelight@0: { truelight@0: _game_mode = GM_EDITOR; truelight@0: truelight@0: // Copy in game options truelight@0: _opt_mod_ptr = &_opt; truelight@0: memcpy(&_opt, &_new_opt, sizeof(_opt)); truelight@193: truelight@0: GfxLoadSprites(); truelight@0: dominik@136: // Re-init the windowing system truelight@0: InitWindowSystem(); truelight@0: truelight@0: // Create toolbars truelight@0: SetupColorsAndInitialWindow(); truelight@0: truelight@0: // Startup the game system truelight@0: GenerateWorld(1); truelight@0: truelight@0: _local_player = OWNER_NONE; truelight@0: MarkWholeScreenDirty(); truelight@0: } truelight@0: dominik@116: void StartupPlayers(); dominik@116: void StartupDisasters(); dominik@116: truelight@0: void StartScenario() truelight@0: { truelight@0: _game_mode = GM_NORMAL; truelight@0: truelight@0: // invalid type truelight@0: if (_file_to_saveload.mode == SL_INVALID) { truelight@0: printf("Savegame is obsolete or invalid format: %s\n", _file_to_saveload.name); truelight@0: ShowErrorMessage(_error_message, STR_4009_GAME_LOAD_FAILED, 0, 0); truelight@0: _game_mode = GM_MENU; truelight@0: return; truelight@0: } truelight@0: truelight@0: // Copy in game options dominik@295: // Removed copying of game options when using "new game". --dominik dominik@295: // _opt_mod_ptr = &_opt; dominik@295: // memcpy(&_opt, &_new_opt, sizeof(_opt)); truelight@0: truelight@0: GfxLoadSprites(); truelight@0: dominik@136: // Reinitialize windows truelight@0: InitWindowSystem(); truelight@0: LoadStringWidthTable(); truelight@0: truelight@0: SetupColorsAndInitialWindow(); truelight@0: truelight@0: // Load game truelight@0: if (SaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode) != SL_OK) { truelight@0: LoadIntroGame(); truelight@0: ShowErrorMessage(_error_message, STR_4009_GAME_LOAD_FAILED, 0, 0); truelight@0: } truelight@0: dominik@115: // Inititalize data dominik@115: StartupPlayers(); dominik@115: StartupEngines(); dominik@115: StartupDisasters(); dominik@115: truelight@139: // When starting a scenario, is it really a load.. truelight@139: // and in AfterLoad a player is started when it is truelight@139: // a scenario.. so we do not need it here. truelight@139: // DoStartupNewPlayer(false); truelight@193: truelight@0: _local_player = 0; truelight@0: truelight@0: MarkWholeScreenDirty(); truelight@0: } truelight@0: truelight@543: bool SafeSaveOrLoad(const char *filename, int mode, int newgm) truelight@0: { truelight@0: byte ogm = _game_mode; truelight@0: int r; truelight@0: truelight@0: _game_mode = newgm; truelight@0: r = SaveOrLoad(filename, mode); truelight@0: if (r == SL_REINIT) { truelight@0: if (ogm == GM_MENU) truelight@0: LoadIntroGame(); truelight@0: else if (ogm == GM_EDITOR) truelight@0: MakeNewEditorWorld(); truelight@0: else truelight@0: MakeNewGame(); truelight@0: return false; truelight@0: } else if (r != SL_OK) { truelight@0: _game_mode = ogm; truelight@193: return false; truelight@0: } else truelight@0: return true; truelight@0: } truelight@0: truelight@543: void SwitchMode(int new_mode) truelight@0: { truelight@139: _in_state_game_loop = true; truelight@193: truelight@543: #ifdef ENABLE_NETWORK truelight@543: // If we are saving something, the network stays in his current state truelight@543: if (new_mode != SM_SAVE) { truelight@543: // If the network is active, make it not-active truelight@543: if (_networking) { truelight@543: if (_network_server && (new_mode == SM_LOAD || new_mode == SM_NEWGAME)) { truelight@543: NetworkReboot(); truelight@543: NetworkUDPClose(); truelight@543: } else { truelight@543: NetworkDisconnect(); truelight@543: NetworkUDPClose(); truelight@543: } truelight@543: } truelight@543: truelight@543: // If we are a server, we restart the server truelight@543: if (_is_network_server) { truelight@543: // But not if we are going to the menu truelight@543: if (new_mode != SM_MENU) { truelight@543: NetworkServerStart(); truelight@543: } else { truelight@543: // This client no longer wants to be a network-server truelight@543: _is_network_server = false; truelight@543: } truelight@543: } truelight@543: } truelight@543: #endif /* ENABLE_NETWORK */ truelight@543: truelight@0: switch(new_mode) { truelight@0: case SM_EDITOR: // Switch to scenario editor truelight@0: MakeNewEditorWorld(); truelight@0: break; truelight@0: truelight@0: case SM_NEWGAME: truelight@630: #ifdef ENABLE_NETWORK truelight@543: if (_network_server) truelight@543: snprintf(_network_game_info.map_name, 40, "Random"); truelight@630: #endif /* ENABLE_NETWORK */ truelight@0: MakeNewGame(); truelight@0: break; truelight@0: truelight@543: case SM_START_SCENARIO: truelight@543: StartScenario(); truelight@543: break; truelight@543: truelight@0: normal_load: truelight@0: case SM_LOAD: { // Load game truelight@0: truelight@0: _error_message = INVALID_STRING_ID; truelight@0: if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL)) { truelight@0: ShowErrorMessage(_error_message, STR_4009_GAME_LOAD_FAILED, 0, 0); truelight@0: } else { truelight@0: _opt_mod_ptr = &_opt; truelight@0: _local_player = 0; truelight@0: DoCommandP(0, 0, 0, NULL, CMD_PAUSE); // decrease pause counter (was increased from opening load dialog) truelight@630: #ifdef ENABLE_NETWORK truelight@543: if (_network_server) truelight@543: snprintf(_network_game_info.map_name, 40, "Loaded game"); truelight@630: #endif /* ENABLE_NETWORK */ truelight@0: } truelight@0: break; truelight@0: } truelight@0: truelight@0: case SM_LOAD_SCENARIO: { truelight@0: int i; truelight@0: truelight@0: if (_game_mode == GM_MENU) goto normal_load; truelight@0: truelight@0: if (SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR)) { truelight@0: _opt_mod_ptr = &_opt; truelight@0: truelight@0: _local_player = OWNER_NONE; truelight@0: _generating_world = true; truelight@0: // delete all players. truelight@0: for(i=0; i != MAX_PLAYERS; i++) { truelight@0: ChangeOwnershipOfPlayerItems(i, 0xff); truelight@0: _players[i].is_active = false; truelight@0: } truelight@0: _generating_world = false; truelight@0: // delete all stations owned by a player truelight@0: DeleteAllPlayerStations(); truelight@543: truelight@630: #ifdef ENABLE_NETWORK truelight@543: if (_network_server) truelight@543: snprintf(_network_game_info.map_name, 40, "Loaded scenario"); truelight@630: #endif /* ENABLE_NETWORK */ truelight@0: } else truelight@0: ShowErrorMessage(INVALID_STRING_ID, STR_4009_GAME_LOAD_FAILED, 0, 0); truelight@0: truelight@0: break; truelight@0: } truelight@0: truelight@0: truelight@0: case SM_MENU: // Switch to game menu truelight@0: LoadIntroGame(); truelight@0: break; truelight@0: truelight@0: case SM_SAVE: // Save game truelight@0: if (SaveOrLoad(_file_to_saveload.name, SL_SAVE) != SL_OK) truelight@0: ShowErrorMessage(INVALID_STRING_ID, STR_4007_GAME_SAVE_FAILED, 0, 0); truelight@0: else truelight@0: DeleteWindowById(WC_SAVELOAD, 0); truelight@0: break; truelight@0: truelight@0: case SM_GENRANDLAND: truelight@0: GenerateWorld(2); truelight@0: // XXX: set date truelight@0: _local_player = OWNER_NONE; truelight@0: MarkWholeScreenDirty(); truelight@0: break; truelight@0: } truelight@193: truelight@193: if (_switch_mode_errorstr!=INVALID_STRING_ID) darkvater@172: ShowErrorMessage(INVALID_STRING_ID,_switch_mode_errorstr,0,0); truelight@0: truelight@0: _in_state_game_loop = false; truelight@0: } truelight@0: truelight@0: truelight@0: // State controlling game loop. truelight@0: // The state must not be changed from anywhere truelight@0: // but here. truelight@0: // That check is enforced in DoCommand. truelight@543: void StateGameLoop() truelight@0: { darkvater@213: // dont execute the state loop during pause darkvater@213: if (_pause) return; darkvater@213: truelight@0: _in_state_game_loop = true; truelight@543: // _frame_counter is increased somewhere else when in network-mode truelight@543: // Sidenote: _frame_counter is ONLY used for _savedump in non-MP-games truelight@543: // Should that not be deleted? If so, the next 2 lines can also be deleted truelight@543: if (!_networking) truelight@543: _frame_counter++; truelight@0: truelight@193: if (_savedump_path[0] && (uint)_frame_counter >= _savedump_first && (uint)(_frame_counter -_savedump_first) % _savedump_freq == 0 ) { truelight@193: char buf[100]; truelight@193: sprintf(buf, "%s%.5d.sav", _savedump_path, _frame_counter); truelight@193: SaveOrLoad(buf, SL_SAVE); truelight@0: if ((uint)_frame_counter >= _savedump_last) exit(1); truelight@0: } truelight@0: truelight@0: if (_game_mode == GM_EDITOR) { truelight@0: RunTileLoop(); truelight@0: CallVehicleTicks(); truelight@0: CallLandscapeTick(); truelight@0: CallWindowTickEvent(); truelight@0: NewsLoop(); truelight@0: } else { signde@206: // All these actions has to be done from OWNER_NONE signde@206: // for multiplayer compatibility signde@206: uint p = _current_player; signde@206: _current_player = OWNER_NONE; signde@206: truelight@0: AnimateAnimatedTiles(); truelight@0: IncreaseDate(); truelight@0: RunTileLoop(); truelight@0: CallVehicleTicks(); truelight@0: CallLandscapeTick(); truelight@0: truelight@543: // To bad the AI does not work in multiplayer, because states are not saved truelight@543: // perfectly truelight@543: if (!disable_computer && !_networking) truelight@0: RunOtherPlayersLoop(); truelight@0: truelight@0: CallWindowTickEvent(); truelight@0: NewsLoop(); signde@206: _current_player = p; truelight@0: } truelight@543: truelight@0: _in_state_game_loop = false; truelight@0: } truelight@0: truelight@0: static void DoAutosave() truelight@0: { truelight@0: char buf[200]; truelight@193: darkvater@1: if (_patches.keep_all_autosave && _local_player != OWNER_SPECTATOR) { truelight@0: Player *p; truelight@0: char *s; truelight@0: sprintf(buf, "%s%s", _path.autosave_dir, PATHSEP); truelight@0: p = DEREF_PLAYER(_local_player); tron@534: SetDParam(0, p->name_1); tron@534: SetDParam(1, p->name_2); tron@534: SetDParam(2, _date); dominik@760: s= (char*)GetString(buf + strlen(_path.autosave_dir) + strlen(PATHSEP), STR_4004); truelight@0: strcpy(s, ".sav"); truelight@0: } else { truelight@0: int n = _autosave_ctr; truelight@0: _autosave_ctr = (_autosave_ctr + 1) & 15; truelight@0: sprintf(buf, "%s%sautosave%d.sav", _path.autosave_dir, PATHSEP, n); truelight@0: } truelight@0: darkvater@557: DEBUG(misc, 2) ("Autosaving to %s", buf); truelight@0: if (SaveOrLoad(buf, SL_SAVE) != SL_OK) truelight@0: ShowErrorMessage(INVALID_STRING_ID, STR_AUTOSAVE_FAILED, 0, 0); truelight@0: } truelight@0: truelight@0: void GameLoop() truelight@0: { truelight@0: int m; truelight@0: truelight@0: // autosave game? truelight@0: if (_do_autosave) { truelight@0: _do_autosave = false; truelight@0: DoAutosave(); truelight@0: RedrawAutosave(); truelight@0: } truelight@0: truelight@0: // make a screenshot? truelight@0: if ((m=_make_screenshot) != 0) { truelight@0: _make_screenshot = 0; truelight@0: switch(m) { truelight@0: case 1: // make small screenshot truelight@0: UndrawMouseCursor(); truelight@0: ShowScreenshotResult(MakeScreenshot()); truelight@0: break; truelight@0: case 2: // make large screenshot truelight@0: ShowScreenshotResult(MakeWorldScreenshot(-(TILE_X_MAX)*32, 0, TILE_X_MAX*32 + (TILE_X_MAX)*32, TILES_Y * 32, 0)); truelight@0: break; truelight@0: } truelight@0: } truelight@0: truelight@0: // switch game mode? truelight@0: if ((m=_switch_mode) != SM_NONE) { truelight@0: _switch_mode = SM_NONE; truelight@0: SwitchMode(m); truelight@0: } truelight@0: truelight@0: IncreaseSpriteLRU(); truelight@0: InteractiveRandom(); truelight@0: truelight@0: if (_scroller_click_timeout > 3) truelight@0: _scroller_click_timeout -= 3; truelight@0: else truelight@0: _scroller_click_timeout = 0; truelight@0: truelight@0: _caret_timer += 3; truelight@0: _timer_counter+=8; truelight@0: CursorTick(); truelight@0: truelight@543: #ifdef ENABLE_NETWORK truelight@543: // Check for UDP stuff truelight@543: NetworkUDPGameLoop(); truelight@0: truelight@543: if (_networking) { truelight@543: // Multiplayer truelight@543: NetworkGameLoop(); truelight@543: } else { truelight@543: if (_network_reconnect > 0 && --_network_reconnect == 0) { truelight@543: // This means that we want to reconnect to the last host truelight@543: // We do this here, because it means that the network is really closed truelight@543: NetworkClientConnectGame(_network_last_host, _network_last_port); signde@206: } truelight@543: // Singleplayer darkvater@213: StateGameLoop(); truelight@0: } truelight@543: #else truelight@543: StateGameLoop(); truelight@543: #endif /* ENABLE_NETWORK */ truelight@0: truelight@0: if (!_pause && _display_opt&DO_FULL_ANIMATION) truelight@0: DoPaletteAnimations(); truelight@0: darkvater@67: if (!_pause || _cheats.build_in_pause.value) truelight@0: MoveAllTextEffects(); truelight@0: truelight@0: MouseLoop(); truelight@0: truelight@0: if (_game_mode != GM_MENU) truelight@0: MusicLoop(); truelight@0: } truelight@0: truelight@0: void BeforeSaveGame() truelight@0: { truelight@0: Window *w = FindWindowById(WC_MAIN_WINDOW, 0); truelight@0: truelight@0: _saved_scrollpos_x = WP(w,vp_d).scrollpos_x; truelight@0: _saved_scrollpos_y = WP(w,vp_d).scrollpos_y; truelight@0: _saved_scrollpos_zoom = w->viewport->zoom; truelight@0: } truelight@0: truelight@0: void ConvertTownOwner() truelight@0: { truelight@0: uint tile; truelight@0: truelight@0: for(tile=0; tile!=TILES_X * TILES_Y; tile++) { truelight@0: if (IS_TILETYPE(tile, MP_STREET)) { truelight@0: if ((_map5[tile] & 0xF0) == 0x10 && _map3_lo[tile] & 0x80) truelight@0: _map3_lo[tile] = OWNER_TOWN; truelight@0: truelight@0: if (_map_owner[tile] & 0x80) truelight@0: _map_owner[tile] = OWNER_TOWN; truelight@0: } else if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { truelight@0: if (_map_owner[tile] & 0x80) truelight@0: _map_owner[tile] = OWNER_TOWN; truelight@0: } truelight@0: } truelight@0: } truelight@0: truelight@0: // before savegame version 4, the name of the company determined if it existed truelight@0: void CheckIsPlayerActive() truelight@0: { truelight@0: Player *p; truelight@0: FOR_ALL_PLAYERS(p) { truelight@0: if (p->name_1 != 0) { truelight@0: p->is_active = true; truelight@0: } truelight@0: } truelight@0: } truelight@0: dominik@121: // since savegame version 4.1, exclusive transport rights are stored at towns dominik@121: void UpdateExclusiveRights() dominik@121: { dominik@121: Town *t; dominik@121: FOR_ALL_TOWNS(t) if (t->xy != 0) { dominik@121: t->exclusivity=(byte)-1; dominik@121: } truelight@193: dominik@123: /* FIXME old exclusive rights status is not being imported (stored in s->blocked_months_obsolete) dominik@121: could be implemented this way: dominik@121: 1.) Go through all stations dominik@121: Build an array town_blocked[ town_id ][ player_id ] dominik@121: that stores if at least one station in that town is blocked for a player dominik@121: 2.) Go through that array, if you find a town that is not blocked for dominik@121: one player, but for all others, then give him exclusivity. dominik@121: */ dominik@121: } dominik@121: dominik@768: byte convert_currency[] = { dominik@762: 0, 1, 12, 8, 3, dominik@762: 10, 14, 19, 4, 5, dominik@762: 9, 11, 13, 6, 17, dominik@762: 16, 22, 21, 7, 15, dominik@762: 18, 2, 20, }; dominik@762: dominik@762: // since savegame version 4.2 the currencies are arranged differently dominik@762: void UpdateCurrencies() dominik@762: { dominik@768: _opt.currency = convert_currency[_opt.currency]; dominik@762: } dominik@762: truelight@0: extern void UpdateOldAircraft(); truelight@0: truelight@0: bool AfterLoadGame(uint version) truelight@0: { truelight@0: Window *w; truelight@0: ViewPort *vp; truelight@0: truelight@0: // in version 2.1 of the savegame, town owner was unified. truelight@0: if (version <= 0x200) { truelight@0: ConvertTownOwner(); truelight@0: } truelight@0: dominik@121: // from version 4.1 of the savegame, exclusive rights are stored at towns dominik@121: if (version <= 0x400) { dominik@121: UpdateExclusiveRights(); dominik@121: } truelight@193: dominik@762: // from version 4.2 of the savegame, currencies are in a different order dominik@762: if (version <= 0x401) { dominik@762: UpdateCurrencies(); dominik@762: } dominik@762: truelight@0: // convert road side to my format. truelight@0: if (_opt.road_side) _opt.road_side = 1; truelight@0: truelight@0: // Load the sprites truelight@0: GfxLoadSprites(); truelight@0: truelight@0: // Update current year truelight@0: SetDate(_date); truelight@0: truelight@0: // reinit the landscape variables (landscape might have changed) truelight@0: InitializeLandscapeVariables(true); truelight@193: truelight@0: // Update all vehicles truelight@0: AfterLoadVehicles(); truelight@0: // in version 2.2 of the savegame, we have new airports truelight@0: if (version <= 0x201) { truelight@0: UpdateOldAircraft(); truelight@0: } truelight@0: truelight@0: UpdateAllStationVirtCoord(); truelight@0: truelight@0: // Setup town coords truelight@0: AfterLoadTown(); truelight@0: UpdateAllSignVirtCoords(); truelight@0: truelight@0: // make sure there is a town in the game truelight@0: if (_game_mode == GM_NORMAL && !ClosestTownFromTile(0, (uint)-1)) truelight@0: { truelight@0: _error_message = STR_NO_TOWN_IN_SCENARIO; truelight@0: return false; truelight@0: } truelight@0: truelight@0: // Initialize windows truelight@0: InitWindowSystem(); truelight@0: SetupColorsAndInitialWindow(); truelight@0: truelight@0: w = FindWindowById(WC_MAIN_WINDOW, 0); truelight@0: truelight@0: WP(w,vp_d).scrollpos_x = _saved_scrollpos_x; truelight@0: WP(w,vp_d).scrollpos_y = _saved_scrollpos_y; truelight@193: truelight@0: vp = w->viewport; truelight@0: vp->zoom = _saved_scrollpos_zoom; truelight@0: vp->virtual_width = vp->width << vp->zoom; truelight@0: vp->virtual_height = vp->height << vp->zoom; truelight@0: truelight@0: truelight@0: // in version 4.0 of the savegame, is_active was introduced to determine truelight@0: // if a player does exist, rather then checking name_1 truelight@0: if (version <= 0x400) { truelight@0: CheckIsPlayerActive(); truelight@0: } truelight@193: truelight@193: // If Load Scenario / New (Scenario) Game is used, truelight@139: // a player does not exist yet. So create one here. truelight@543: // 1 exeption: network-games. Those can have 0 players truelight@543: // But this exeption is not true for network_servers! truelight@543: if (!_players[0].is_active && (!_networking || (_networking && _network_server))) truelight@139: DoStartupNewPlayer(false); truelight@0: darkvater@152: DoZoomInOutWindow(ZOOM_NONE, w); // update button status truelight@0: MarkWholeScreenDirty(); truelight@0: truelight@0: return true; truelight@0: } truelight@0: truelight@0: truelight@0: void DebugProc(int i) truelight@0: { truelight@0: switch(i) { truelight@0: case 0: truelight@0: *(byte*)0 = 0; truelight@0: break; truelight@0: case 1: truelight@0: DoCommandP(0, -10000000, 0, NULL, CMD_MONEY_CHEAT); truelight@0: break; truelight@0: case 2: truelight@0: UpdateAllStationVirtCoord(); truelight@0: break; truelight@0: } truelight@0: }