ttd.c
changeset 1891 862800791170
parent 1890 634da7d89c2b
child 1892 8717d92b32b1
equal deleted inserted replaced
1890:634da7d89c2b 1891:862800791170
     1 #include "stdafx.h"
       
     2 #include "string.h"
       
     3 #include "table/strings.h"
       
     4 #include "debug.h"
       
     5 #include "strings.h"
       
     6 #include "map.h"
       
     7 #include "tile.h"
       
     8 
       
     9 #define VARDEF
       
    10 #include "ttd.h"
       
    11 #include "mixer.h"
       
    12 #include "spritecache.h"
       
    13 #include "gfx.h"
       
    14 #include "gui.h"
       
    15 #include "station.h"
       
    16 #include "vehicle.h"
       
    17 #include "viewport.h"
       
    18 #include "window.h"
       
    19 #include "player.h"
       
    20 #include "command.h"
       
    21 #include "town.h"
       
    22 #include "industry.h"
       
    23 #include "news.h"
       
    24 #include "engine.h"
       
    25 #include "sound.h"
       
    26 #include "economy.h"
       
    27 #include "fileio.h"
       
    28 #include "hal.h"
       
    29 #include "airport.h"
       
    30 #include "ai.h"
       
    31 #include "console.h"
       
    32 #include "screenshot.h"
       
    33 #include "network.h"
       
    34 #include "signs.h"
       
    35 #include "depot.h"
       
    36 #include "waypoint.h"
       
    37 
       
    38 #include <stdarg.h>
       
    39 
       
    40 void GenerateWorld(int mode, uint log_x, uint log_y);
       
    41 void CallLandscapeTick(void);
       
    42 void IncreaseDate(void);
       
    43 void RunOtherPlayersLoop(void);
       
    44 void DoPaletteAnimations(void);
       
    45 void MusicLoop(void);
       
    46 void ResetMusic(void);
       
    47 void InitializeStations(void);
       
    48 void DeleteAllPlayerStations(void);
       
    49 
       
    50 extern void SetDifficultyLevel(int mode, GameOptions *gm_opt);
       
    51 extern void DoStartupNewPlayer(bool is_ai);
       
    52 extern void ShowOSErrorBox(const char *buf);
       
    53 
       
    54 bool LoadSavegame(const char *filename);
       
    55 
       
    56 extern void HalGameLoop(void);
       
    57 
       
    58 uint32 _pixels_redrawn;
       
    59 bool _dbg_screen_rect;
       
    60 bool disable_computer; // We should get ride of this thing.. is only used for a debug-cheat
       
    61 static byte _os_version = 0;
       
    62 
       
    63 /* TODO: usrerror() for errors which are not of an internal nature but
       
    64  * caused by the user, i.e. missing files or fatal configuration errors.
       
    65  * Post-0.4.0 since Celestar doesn't want this in SVN before. --pasky */
       
    66 
       
    67 void CDECL error(const char *s, ...) {
       
    68 	va_list va;
       
    69 	char buf[512];
       
    70 	va_start(va, s);
       
    71 	vsprintf(buf, s, va);
       
    72 	va_end(va);
       
    73 
       
    74 	ShowOSErrorBox(buf);
       
    75 	if (_video_driver)
       
    76 		_video_driver->stop();
       
    77 
       
    78 	assert(0);
       
    79 	exit(1);
       
    80 }
       
    81 
       
    82 void CDECL ShowInfoF(const char *str, ...)
       
    83 {
       
    84 	va_list va;
       
    85 	char buf[1024];
       
    86 	va_start(va, str);
       
    87 	vsprintf(buf, str, va);
       
    88 	va_end(va);
       
    89 	ShowInfo(buf);
       
    90 }
       
    91 
       
    92 char * CDECL str_fmt(const char *str, ...)
       
    93 {
       
    94 	char buf[4096];
       
    95 	va_list va;
       
    96 	int len;
       
    97 	char *p;
       
    98 
       
    99 	va_start(va, str);
       
   100 	len = vsprintf(buf, str, va);
       
   101 	va_end(va);
       
   102 	p = malloc(len + 1);
       
   103 	if (p)
       
   104 		memcpy(p, buf, len + 1);
       
   105 	return p;
       
   106 }
       
   107 
       
   108 
       
   109 // NULL midi driver
       
   110 static const char *NullMidiStart(const char * const *parm) { return NULL; }
       
   111 static void NullMidiStop(void) {}
       
   112 static void NullMidiPlaySong(const char *filename) {}
       
   113 static void NullMidiStopSong(void) {}
       
   114 static bool NullMidiIsSongPlaying(void) { return true; }
       
   115 static void NullMidiSetVolume(byte vol) {}
       
   116 
       
   117 const HalMusicDriver _null_music_driver = {
       
   118 	NullMidiStart,
       
   119 	NullMidiStop,
       
   120 	NullMidiPlaySong,
       
   121 	NullMidiStopSong,
       
   122 	NullMidiIsSongPlaying,
       
   123 	NullMidiSetVolume,
       
   124 };
       
   125 
       
   126 // NULL video driver
       
   127 static void *_null_video_mem;
       
   128 static const char *NullVideoStart(const char * const *parm)
       
   129 {
       
   130 	_screen.width = _screen.pitch = _cur_resolution[0];
       
   131 	_screen.height = _cur_resolution[1];
       
   132 	_null_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]);
       
   133 	return NULL;
       
   134 }
       
   135 static void NullVideoStop(void) { free(_null_video_mem); }
       
   136 static void NullVideoMakeDirty(int left, int top, int width, int height) {}
       
   137 static int NullVideoMainLoop(void)
       
   138 {
       
   139 	int i = 1000;
       
   140 	do {
       
   141 		GameLoop();
       
   142 		_screen.dst_ptr = _null_video_mem;
       
   143 		UpdateWindows();
       
   144 	}	while (--i);
       
   145 	return ML_QUIT;
       
   146 }
       
   147 
       
   148 static bool NullVideoChangeRes(int w, int h) { return false; }
       
   149 static void NullVideoFullScreen(bool fs) {}
       
   150 
       
   151 const HalVideoDriver _null_video_driver = {
       
   152 	NullVideoStart,
       
   153 	NullVideoStop,
       
   154 	NullVideoMakeDirty,
       
   155 	NullVideoMainLoop,
       
   156 	NullVideoChangeRes,
       
   157 	NullVideoFullScreen,
       
   158 };
       
   159 
       
   160 // NULL sound driver
       
   161 static const char *NullSoundStart(const char * const *parm) { return NULL; }
       
   162 static void NullSoundStop(void) {}
       
   163 const HalSoundDriver _null_sound_driver = {
       
   164 	NullSoundStart,
       
   165 	NullSoundStop,
       
   166 };
       
   167 
       
   168 enum {
       
   169 	DF_PRIORITY_MASK = 0xf,
       
   170 };
       
   171 
       
   172 typedef struct {
       
   173 	const DriverDesc *descs;
       
   174 	const char *name;
       
   175 	void *var;
       
   176 } DriverClass;
       
   177 
       
   178 static DriverClass _driver_classes[] = {
       
   179 	{_video_driver_descs, "video", &_video_driver},
       
   180 	{_sound_driver_descs, "sound", &_sound_driver},
       
   181 	{_music_driver_descs, "music", &_music_driver},
       
   182 };
       
   183 
       
   184 static const DriverDesc *GetDriverByName(const DriverDesc *dd, const char *name)
       
   185 {
       
   186 	do {
       
   187 		if (!strcmp(dd->name, name))
       
   188 			return dd;
       
   189 	} while ((++dd)->name);
       
   190 	return NULL;
       
   191 }
       
   192 
       
   193 static const DriverDesc *ChooseDefaultDriver(const DriverDesc *dd)
       
   194 {
       
   195 	const DriverDesc *best = NULL;
       
   196 	int best_pri = -1;
       
   197 	do {
       
   198 		if ((int)(dd->flags&DF_PRIORITY_MASK) > best_pri && _os_version >= (byte)dd->flags) {
       
   199 			best_pri = dd->flags&DF_PRIORITY_MASK;
       
   200 			best = dd;
       
   201 		}
       
   202 	} while ((++dd)->name);
       
   203 	return best;
       
   204 }
       
   205 
       
   206 
       
   207 void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize)
       
   208 {
       
   209 	FILE *in;
       
   210 	byte *mem;
       
   211 	size_t len;
       
   212 
       
   213 	in = fopen(filename, "rb");
       
   214 	if (in == NULL)
       
   215 		return NULL;
       
   216 
       
   217 	fseek(in, 0, SEEK_END);
       
   218 	len = ftell(in);
       
   219 	fseek(in, 0, SEEK_SET);
       
   220 	if (len > maxsize || (mem = malloc(len + 1)) == NULL) {
       
   221 		fclose(in);
       
   222 		return NULL;
       
   223 	}
       
   224 	mem[len] = 0;
       
   225 	if (fread(mem, len, 1, in) != 1) {
       
   226 		fclose(in);
       
   227 		free(mem);
       
   228 		return NULL;
       
   229 	}
       
   230 	fclose(in);
       
   231 
       
   232 	*lenp = len;
       
   233 	return mem;
       
   234 }
       
   235 
       
   236 void LoadDriver(int driver, const char *name)
       
   237 {
       
   238 	const DriverClass *dc = &_driver_classes[driver];
       
   239 	const DriverDesc *dd;
       
   240 	const void **var;
       
   241 	const void *drv;
       
   242 	const char *err;
       
   243 	char *parm;
       
   244 	char buffer[256];
       
   245 	const char *parms[32];
       
   246 
       
   247 	parms[0] = NULL;
       
   248 
       
   249 	if (!*name) {
       
   250 		dd = ChooseDefaultDriver(dc->descs);
       
   251 	} else {
       
   252 		// Extract the driver name and put parameter list in parm
       
   253 		ttd_strlcpy(buffer, name, sizeof(buffer));
       
   254 		parm = strchr(buffer, ':');
       
   255 		if (parm) {
       
   256 			uint np = 0;
       
   257 			// Tokenize the parm.
       
   258 			do {
       
   259 				*parm++ = 0;
       
   260 				if (np < lengthof(parms) - 1)
       
   261 					parms[np++] = parm;
       
   262 				while (*parm != 0 && *parm != ',')
       
   263 					parm++;
       
   264 			} while (*parm == ',');
       
   265 			parms[np] = NULL;
       
   266 		}
       
   267 		dd = GetDriverByName(dc->descs, buffer);
       
   268 		if (dd == NULL)
       
   269 			error("No such %s driver: %s\n", dc->name, buffer);
       
   270 	}
       
   271 	var = dc->var;
       
   272 	if (*var != NULL) ((const HalCommonDriver*)*var)->stop();
       
   273 	*var = NULL;
       
   274 	drv = dd->drv;
       
   275 	if ((err=((const HalCommonDriver*)drv)->start(parms)) != NULL)
       
   276 		error("Unable to load driver %s(%s). The error was: %s\n", dd->name, dd->longname, err);
       
   277 	*var = drv;
       
   278 }
       
   279 
       
   280 static void showhelp(void)
       
   281 {
       
   282 	char buf[4096], *p;
       
   283 	const DriverClass *dc = _driver_classes;
       
   284 	const DriverDesc *dd;
       
   285 	int i;
       
   286 
       
   287 	p = strecpy(buf,
       
   288 		"Command line options:\n"
       
   289 		"  -v drv              = Set video driver (see below)\n"
       
   290 		"  -s drv              = Set sound driver (see below)\n"
       
   291 		"  -m drv              = Set music driver (see below)\n"
       
   292 		"  -r res              = Set resolution (for instance 800x600)\n"
       
   293 		"  -h                  = Display this help text\n"
       
   294 		"  -t date             = Set starting date\n"
       
   295 		"  -d [[fac=]lvl[,...]]= Debug mode\n"
       
   296 		"  -l lng              = Select Language\n"
       
   297 		"  -e                  = Start Editor\n"
       
   298 		"  -g [savegame]       = Start new/save game immediately\n"
       
   299 		"  -G seed             = Set random seed\n"
       
   300 		"  -n [ip#player:port] = Start networkgame\n"
       
   301 		"  -D                  = Start dedicated server\n"
       
   302 		#if !defined(__MORPHOS__) && !defined(__AMIGA__)
       
   303 		"  -f                  = Fork into the background (dedicated only)\n"
       
   304 		#endif
       
   305 		"  -i                  = Force to use the DOS palette (use this if you see a lot of pink)\n"
       
   306 		"  -p #player          = Player as #player (deprecated) (network only)\n"
       
   307 		"  -c config_file      = Use 'config_file' instead of 'openttd.cfg'\n",
       
   308 		lastof(buf)
       
   309 	);
       
   310 
       
   311 	for(i=0; i!=lengthof(_driver_classes); i++,dc++) {
       
   312 		p += sprintf(p, "List of %s drivers:\n", dc->name);
       
   313 		dd = dc->descs;
       
   314 		do {
       
   315 			p += sprintf(p, "%10s: %s\n", dd->name, dd->longname);
       
   316 		} while ((++dd)->name);
       
   317 	}
       
   318 
       
   319 	ShowInfo(buf);
       
   320 }
       
   321 
       
   322 
       
   323 const char *GetDriverParam(const char * const *parm, const char *name)
       
   324 {
       
   325 	const char *p;
       
   326 	int len = strlen(name);
       
   327 	while ((p = *parm++) != NULL) {
       
   328 		if (!strncmp(p,name,len)) {
       
   329 			if (p[len] == '=') return p + len + 1;
       
   330 			if (p[len] == 0)   return p + len;
       
   331 		}
       
   332 	}
       
   333 	return NULL;
       
   334 }
       
   335 
       
   336 bool GetDriverParamBool(const char * const *parm, const char *name)
       
   337 {
       
   338 	const char *p = GetDriverParam(parm, name);
       
   339 	return p != NULL;
       
   340 }
       
   341 
       
   342 int GetDriverParamInt(const char * const *parm, const char *name, int def)
       
   343 {
       
   344 	const char *p = GetDriverParam(parm, name);
       
   345 	return p != NULL ? atoi(p) : def;
       
   346 }
       
   347 
       
   348 typedef struct {
       
   349 	char *opt;
       
   350 	int numleft;
       
   351 	char **argv;
       
   352 	const char *options;
       
   353 	char *cont;
       
   354 } MyGetOptData;
       
   355 
       
   356 static void MyGetOptInit(MyGetOptData *md, int argc, char **argv, const char *options)
       
   357 {
       
   358 	md->cont = NULL;
       
   359 	md->numleft = argc;
       
   360 	md->argv = argv;
       
   361 	md->options = options;
       
   362 }
       
   363 
       
   364 static int MyGetOpt(MyGetOptData *md)
       
   365 {
       
   366 	char *s,*r,*t;
       
   367 
       
   368 	if ((s=md->cont) != NULL)
       
   369 		goto md_continue_here;
       
   370 
       
   371 	while(true) {
       
   372 		if (--md->numleft < 0)
       
   373 			return -1;
       
   374 
       
   375 		s = *md->argv++;
       
   376 		if (*s == '-') {
       
   377 md_continue_here:;
       
   378 			s++;
       
   379 			if (*s != 0) {
       
   380 				// Found argument, try to locate it in options.
       
   381 				if (*s == ':' || (r = strchr(md->options, *s)) == NULL) {
       
   382 					// ERROR!
       
   383 					return -2;
       
   384 				}
       
   385 				if (r[1] == ':') {
       
   386 					// Item wants an argument. Check if the argument follows, or if it comes as a separate arg.
       
   387 					if (!*(t = s + 1)) {
       
   388 						// It comes as a separate arg. Check if out of args?
       
   389 						if (--md->numleft < 0 || *(t = *md->argv) == '-') {
       
   390 							// Check if item is optional?
       
   391 							if (r[2] != ':')
       
   392 								return -2;
       
   393 							md->numleft++;
       
   394 							t = NULL;
       
   395 						} else {
       
   396 							md->argv++;
       
   397 						}
       
   398 					}
       
   399 					md->opt = t;
       
   400 					md->cont = NULL;
       
   401 					return *s;
       
   402 				}
       
   403 				md->opt = NULL;
       
   404 				md->cont = s;
       
   405 				return *s;
       
   406 			}
       
   407 		} else {
       
   408 			// This is currently not supported.
       
   409 			return -2;
       
   410 		}
       
   411 	}
       
   412 }
       
   413 
       
   414 
       
   415 static void ParseResolution(int res[2], char *s)
       
   416 {
       
   417 	char *t = strchr(s, 'x');
       
   418 	if (t == NULL) {
       
   419 		ShowInfoF("Invalid resolution '%s'", s);
       
   420 		return;
       
   421 	}
       
   422 
       
   423 	res[0] = clamp(strtoul(s, NULL, 0), 64, MAX_SCREEN_WIDTH);
       
   424 	res[1] = clamp(strtoul(t + 1, NULL, 0), 64, MAX_SCREEN_HEIGHT);
       
   425 }
       
   426 
       
   427 static void InitializeDynamicVariables(void)
       
   428 {
       
   429 	/* Dynamic stuff needs to be initialized somewhere... */
       
   430 	_station_sort  = NULL;
       
   431 	_vehicle_sort  = NULL;
       
   432 	_town_sort     = NULL;
       
   433 	_industry_sort = NULL;
       
   434 }
       
   435 
       
   436 static void UnInitializeDynamicVariables(void)
       
   437 {
       
   438 	/* Dynamic stuff needs to be free'd somewhere... */
       
   439 	CleanPool(&_town_pool);
       
   440 	CleanPool(&_industry_pool);
       
   441 	CleanPool(&_station_pool);
       
   442 	CleanPool(&_vehicle_pool);
       
   443 	CleanPool(&_sign_pool);
       
   444 	CleanPool(&_order_pool);
       
   445 
       
   446 	free(_station_sort);
       
   447 	free(_vehicle_sort);
       
   448 	free(_town_sort);
       
   449 	free(_industry_sort);
       
   450 }
       
   451 
       
   452 static void UnInitializeGame(void)
       
   453 {
       
   454 	UnInitWindowSystem();
       
   455 	UnInitNewgrEngines();
       
   456 
       
   457 	free(_config_file);
       
   458 }
       
   459 
       
   460 static void LoadIntroGame(void)
       
   461 {
       
   462 	char filename[256];
       
   463 
       
   464 	_game_mode = GM_MENU;
       
   465 	CLRBITS(_display_opt, DO_TRANS_BUILDINGS); // don't make buildings transparent in intro
       
   466 	_opt_ptr = &_opt_newgame;
       
   467 
       
   468 	GfxLoadSprites();
       
   469 	LoadStringWidthTable();
       
   470 
       
   471 	// Setup main window
       
   472 	ResetWindowSystem();
       
   473 	SetupColorsAndInitialWindow();
       
   474 
       
   475 	// Generate a world.
       
   476 	sprintf(filename, "%sopntitle.dat",  _path.data_dir);
       
   477 	if (SaveOrLoad(filename, SL_LOAD) != SL_OK) {
       
   478 #if defined SECOND_DATA_DIR
       
   479 		sprintf(filename, "%sopntitle.dat",  _path.second_data_dir);
       
   480 		if (SaveOrLoad(filename, SL_LOAD) != SL_OK)
       
   481 #endif
       
   482 			GenerateWorld(1, 6, 6); // if failed loading, make empty world.
       
   483 	}
       
   484 
       
   485 	_pause = 0;
       
   486 	_local_player = 0;
       
   487 	MarkWholeScreenDirty();
       
   488 
       
   489 	// Play main theme
       
   490 	if (_music_driver->is_song_playing()) ResetMusic();
       
   491 }
       
   492 
       
   493 extern void DedicatedFork(void);
       
   494 extern void CheckExternalFiles(void);
       
   495 
       
   496 int ttd_main(int argc, char* argv[])
       
   497 {
       
   498 	MyGetOptData mgo;
       
   499 	int i;
       
   500 	bool network = false;
       
   501 	char *network_conn = NULL;
       
   502 	char *language = NULL;
       
   503 	const char *optformat;
       
   504 	char musicdriver[16], sounddriver[16], videodriver[16];
       
   505 	int resolution[2] = {0,0};
       
   506 	uint startdate = -1;
       
   507 	bool dedicated;
       
   508 
       
   509 	musicdriver[0] = sounddriver[0] = videodriver[0] = 0;
       
   510 
       
   511 	_game_mode = GM_MENU;
       
   512 	_switch_mode = SM_MENU;
       
   513 	_switch_mode_errorstr = INVALID_STRING_ID;
       
   514 	_dedicated_forks = false;
       
   515 	dedicated = false;
       
   516 	_config_file = NULL;
       
   517 
       
   518 	// The last param of the following function means this:
       
   519 	//   a letter means: it accepts that param (e.g.: -h)
       
   520 	//   a ':' behind it means: it need a param (e.g.: -m<driver>)
       
   521 	//   a '::' behind it means: it can optional have a param (e.g.: -d<debug>)
       
   522 	#if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32)
       
   523 		optformat = "m:s:v:hDfn::l:eit:d::r:g::G:p:c:";
       
   524 	#else
       
   525 		optformat = "m:s:v:hDn::l:eit:d::r:g::G:p:c:"; // no fork option
       
   526 	#endif
       
   527 
       
   528 	MyGetOptInit(&mgo, argc-1, argv+1, optformat);
       
   529 	while ((i = MyGetOpt(&mgo)) != -1) {
       
   530 		switch(i) {
       
   531 		case 'm': ttd_strlcpy(musicdriver, mgo.opt, sizeof(musicdriver)); break;
       
   532 		case 's': ttd_strlcpy(sounddriver, mgo.opt, sizeof(sounddriver)); break;
       
   533 		case 'v': ttd_strlcpy(videodriver, mgo.opt, sizeof(videodriver)); break;
       
   534 		case 'D': {
       
   535 				sprintf(musicdriver,"null");
       
   536 				sprintf(sounddriver,"null");
       
   537 				sprintf(videodriver,"dedicated");
       
   538 				dedicated = true;
       
   539 			} break;
       
   540 		case 'f': {
       
   541 				_dedicated_forks = true;
       
   542 			}; break;
       
   543 		case 'n': {
       
   544 				network = true;
       
   545 				if (mgo.opt)
       
   546 					// Optional, you can give an IP
       
   547 					network_conn = mgo.opt;
       
   548 				else
       
   549 					network_conn = NULL;
       
   550 			} break;
       
   551 		case 'r': ParseResolution(resolution, mgo.opt); break;
       
   552 		case 'l': {
       
   553 				language = mgo.opt;
       
   554 			} break;
       
   555 		case 't': {
       
   556 				startdate = atoi(mgo.opt);
       
   557 			} break;
       
   558 		case 'd': {
       
   559 #if defined(WIN32)
       
   560 				CreateConsole();
       
   561 #endif
       
   562 				if (mgo.opt)
       
   563 					SetDebugString(mgo.opt);
       
   564 			} break;
       
   565 		case 'e': _switch_mode = SM_EDITOR; break;
       
   566 		case 'i': _use_dos_palette = true; break;
       
   567 		case 'g':
       
   568 			if (mgo.opt) {
       
   569 				strcpy(_file_to_saveload.name, mgo.opt);
       
   570 				_switch_mode = SM_LOAD;
       
   571 			} else
       
   572 				_switch_mode = SM_NEWGAME;
       
   573 			break;
       
   574 		case 'G':
       
   575 			_random_seeds[0][0] = atoi(mgo.opt);
       
   576 			break;
       
   577 		case 'p': {
       
   578 			int i = atoi(mgo.opt);
       
   579 			// Play as an other player in network games
       
   580 			if (IS_INT_INSIDE(i, 1, MAX_PLAYERS)) _network_playas = i;
       
   581 			break;
       
   582 		}
       
   583 		case 'c':
       
   584 			_config_file = strdup(mgo.opt);
       
   585 			break;
       
   586 		case -2:
       
   587  		case 'h':
       
   588 			showhelp();
       
   589 			return 0;
       
   590 		}
       
   591 	}
       
   592 
       
   593 	DeterminePaths();
       
   594 	CheckExternalFiles();
       
   595 
       
   596 #ifdef UNIX
       
   597 	// We must fork here, or we'll end up without some resources we need (like sockets)
       
   598 	if (_dedicated_forks)
       
   599 		DedicatedFork();
       
   600 #endif
       
   601 
       
   602 	LoadFromConfig();
       
   603 	CheckConfig();
       
   604 	LoadFromHighScore();
       
   605 
       
   606 	// override config?
       
   607 	if (musicdriver[0]) ttd_strlcpy(_ini_musicdriver, musicdriver, sizeof(_ini_musicdriver));
       
   608 	if (sounddriver[0]) ttd_strlcpy(_ini_sounddriver, sounddriver, sizeof(_ini_sounddriver));
       
   609 	if (videodriver[0]) ttd_strlcpy(_ini_videodriver, videodriver, sizeof(_ini_videodriver));
       
   610 	if (resolution[0]) { _cur_resolution[0] = resolution[0]; _cur_resolution[1] = resolution[1]; }
       
   611 	if (startdate != (uint)-1) _patches.starting_date = startdate;
       
   612 
       
   613 	if (_dedicated_forks && !dedicated)
       
   614 		_dedicated_forks = false;
       
   615 
       
   616 	// enumerate language files
       
   617 	InitializeLanguagePacks();
       
   618 
       
   619 	// initialize screenshot formats
       
   620 	InitializeScreenshotFormats();
       
   621 
       
   622 	// initialize airport state machines
       
   623 	InitializeAirports();
       
   624 
       
   625 	/* initialize all variables that are allocated dynamically */
       
   626 	InitializeDynamicVariables();
       
   627 
       
   628 	// Sample catalogue
       
   629 	DEBUG(misc, 1) ("Loading sound effects...");
       
   630 	_os_version = GetOSVersion();
       
   631 	MxInitialize(11025);
       
   632 	SoundInitialize("sample.cat");
       
   633 
       
   634 	// This must be done early, since functions use the InvalidateWindow* calls
       
   635 	InitWindowSystem();
       
   636 
       
   637 	GfxLoadSprites();
       
   638 	LoadStringWidthTable();
       
   639 
       
   640 	DEBUG(misc, 1) ("Loading drivers...");
       
   641 	LoadDriver(SOUND_DRIVER, _ini_sounddriver);
       
   642 	LoadDriver(MUSIC_DRIVER, _ini_musicdriver);
       
   643 	LoadDriver(VIDEO_DRIVER, _ini_videodriver); // load video last, to prevent an empty window while sound and music loads
       
   644 	_savegame_sort_order = 1; // default sorting of savegames is by date, newest first
       
   645 
       
   646 #ifdef ENABLE_NETWORK
       
   647 	// initialize network-core
       
   648 	NetworkStartUp();
       
   649 #endif /* ENABLE_NETWORK */
       
   650 
       
   651 	_opt_ptr = &_opt_newgame;
       
   652 
       
   653 	/* XXX - ugly hack, if diff_level is 9, it means we got no setting from the config file */
       
   654 	if (_opt_newgame.diff_level == 9)
       
   655 		SetDifficultyLevel(0, &_opt_newgame);
       
   656 
       
   657 	// initialize the ingame console
       
   658 	IConsoleInit();
       
   659 	InitializeGUI();
       
   660 	IConsoleCmdExec("exec scripts/autoexec.scr 0");
       
   661 
       
   662 	InitPlayerRandoms();
       
   663 
       
   664 	GenerateWorld(1, 6, 6); // Make the viewport initialization happy
       
   665 
       
   666 #ifdef ENABLE_NETWORK
       
   667 	if ((network) && (_network_available)) {
       
   668 		if (network_conn != NULL) {
       
   669 			const char *port = NULL;
       
   670 			const char *player = NULL;
       
   671 			uint16 rport;
       
   672 
       
   673 			rport = NETWORK_DEFAULT_PORT;
       
   674 
       
   675 			ParseConnectionString(&player, &port, network_conn);
       
   676 
       
   677 			if (player != NULL) _network_playas = atoi(player);
       
   678 			if (port != NULL) rport = atoi(port);
       
   679 
       
   680 			LoadIntroGame();
       
   681 			_switch_mode = SM_NONE;
       
   682 			NetworkClientConnectGame(network_conn, rport);
       
   683 		}
       
   684 	}
       
   685 #endif /* ENABLE_NETWORK */
       
   686 
       
   687 	while (_video_driver->main_loop() == ML_SWITCHDRIVER) {}
       
   688 
       
   689 	JoinOTTDThread();
       
   690 	IConsoleFree();
       
   691 
       
   692 #ifdef ENABLE_NETWORK
       
   693 	if (_network_available) {
       
   694 		// Shut down the network and close any open connections
       
   695 		NetworkDisconnect();
       
   696 		NetworkUDPClose();
       
   697 		NetworkShutDown();
       
   698 	}
       
   699 #endif /* ENABLE_NETWORK */
       
   700 
       
   701 	_video_driver->stop();
       
   702 	_music_driver->stop();
       
   703 	_sound_driver->stop();
       
   704 
       
   705 	SaveToConfig();
       
   706 	SaveToHighScore();
       
   707 
       
   708 	// uninitialize airport state machines
       
   709 	UnInitializeAirports();
       
   710 
       
   711 	/* uninitialize variables that are allocated dynamic */
       
   712 	UnInitializeDynamicVariables();
       
   713 
       
   714 	/* Close all and any open filehandles */
       
   715 	FioCloseAll();
       
   716 	UnInitializeGame();
       
   717 
       
   718 	return 0;
       
   719 }
       
   720 
       
   721 static void ShowScreenshotResult(bool b)
       
   722 {
       
   723 	if (b) {
       
   724 		SetDParam(0, STR_SPEC_SCREENSHOT_NAME);
       
   725 		ShowErrorMessage(INVALID_STRING_ID, STR_031B_SCREENSHOT_SUCCESSFULLY, 0, 0);
       
   726 	} else {
       
   727 		ShowErrorMessage(INVALID_STRING_ID, STR_031C_SCREENSHOT_FAILED, 0, 0);
       
   728 	}
       
   729 
       
   730 }
       
   731 
       
   732 static void MakeNewGame(void)
       
   733 {
       
   734 	_game_mode = GM_NORMAL;
       
   735 
       
   736 	// Copy in game options
       
   737 	_opt_ptr = &_opt;
       
   738 	memcpy(_opt_ptr, &_opt_newgame, sizeof(GameOptions));
       
   739 
       
   740 	GfxLoadSprites();
       
   741 
       
   742 	// Reinitialize windows
       
   743 	ResetWindowSystem();
       
   744 	LoadStringWidthTable();
       
   745 
       
   746 	SetupColorsAndInitialWindow();
       
   747 
       
   748 	// Randomize world
       
   749 	GenerateWorld(0, _patches.map_x, _patches.map_y);
       
   750 
       
   751 	// In a dedicated server, the server does not play
       
   752 	if (_network_dedicated) {
       
   753 		_local_player = OWNER_SPECTATOR;
       
   754 	}	else {
       
   755 		// Create a single player
       
   756 		DoStartupNewPlayer(false);
       
   757 
       
   758 		_local_player = 0;
       
   759 	}
       
   760 
       
   761 	MarkWholeScreenDirty();
       
   762 }
       
   763 
       
   764 static void MakeNewEditorWorld(void)
       
   765 {
       
   766 	_game_mode = GM_EDITOR;
       
   767 
       
   768 	// Copy in game options
       
   769 	_opt_ptr = &_opt;
       
   770 	memcpy(_opt_ptr, &_opt_newgame, sizeof(GameOptions));
       
   771 
       
   772 	GfxLoadSprites();
       
   773 
       
   774 	// Re-init the windowing system
       
   775 	ResetWindowSystem();
       
   776 
       
   777 	// Create toolbars
       
   778 	SetupColorsAndInitialWindow();
       
   779 
       
   780 	// Startup the game system
       
   781 	GenerateWorld(1, _patches.map_x, _patches.map_y);
       
   782 
       
   783 	_local_player = OWNER_NONE;
       
   784 	MarkWholeScreenDirty();
       
   785 }
       
   786 
       
   787 void StartupPlayers(void);
       
   788 void StartupDisasters(void);
       
   789 
       
   790 /**
       
   791  * Start Scenario starts a new game based on a scenario.
       
   792  * Eg 'New Game' --> select a preset scenario
       
   793  * This starts a scenario based on your current difficulty settings
       
   794  */
       
   795 static void StartScenario(void)
       
   796 {
       
   797 	_game_mode = GM_NORMAL;
       
   798 
       
   799 	// invalid type
       
   800 	if (_file_to_saveload.mode == SL_INVALID) {
       
   801 		printf("Savegame is obsolete or invalid format: %s\n", _file_to_saveload.name);
       
   802 		ShowErrorMessage(_error_message, STR_4009_GAME_LOAD_FAILED, 0, 0);
       
   803 		_game_mode = GM_MENU;
       
   804 		return;
       
   805 	}
       
   806 
       
   807 	GfxLoadSprites();
       
   808 
       
   809 	// Reinitialize windows
       
   810 	ResetWindowSystem();
       
   811 	LoadStringWidthTable();
       
   812 
       
   813 	SetupColorsAndInitialWindow();
       
   814 
       
   815 	// Load game
       
   816 	if (SaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode) != SL_OK) {
       
   817 		LoadIntroGame();
       
   818 		ShowErrorMessage(_error_message, STR_4009_GAME_LOAD_FAILED, 0, 0);
       
   819 	}
       
   820 
       
   821 	_opt_ptr = &_opt;
       
   822 	memcpy(&_opt_ptr->diff, &_opt_newgame.diff, sizeof(GameDifficulty));
       
   823 	_opt.diff_level = _opt_newgame.diff_level;
       
   824 
       
   825 	// Inititalize data
       
   826 	StartupPlayers();
       
   827 	StartupEngines();
       
   828 	StartupDisasters();
       
   829 
       
   830 	_local_player = 0;
       
   831 
       
   832 	MarkWholeScreenDirty();
       
   833 }
       
   834 
       
   835 bool SafeSaveOrLoad(const char *filename, int mode, int newgm)
       
   836 {
       
   837 	byte ogm = _game_mode;
       
   838 	int r;
       
   839 
       
   840 	_game_mode = newgm;
       
   841 	r = SaveOrLoad(filename, mode);
       
   842 	if (r == SL_REINIT) {
       
   843 		if (ogm == GM_MENU)
       
   844 			LoadIntroGame();
       
   845 		else if (ogm == GM_EDITOR)
       
   846 			MakeNewEditorWorld();
       
   847 		else
       
   848 			MakeNewGame();
       
   849 		return false;
       
   850 	} else if (r != SL_OK) {
       
   851 		_game_mode = ogm;
       
   852 		return false;
       
   853 	} else
       
   854 		return true;
       
   855 }
       
   856 
       
   857 void SwitchMode(int new_mode)
       
   858 {
       
   859 	_in_state_game_loop = true;
       
   860 
       
   861 #ifdef ENABLE_NETWORK
       
   862 	// If we are saving something, the network stays in his current state
       
   863 	if (new_mode != SM_SAVE) {
       
   864 		// If the network is active, make it not-active
       
   865 		if (_networking) {
       
   866 			if (_network_server && (new_mode == SM_LOAD || new_mode == SM_NEWGAME)) {
       
   867 				NetworkReboot();
       
   868 				NetworkUDPClose();
       
   869 			} else {
       
   870 				NetworkDisconnect();
       
   871 				NetworkUDPClose();
       
   872 			}
       
   873 		}
       
   874 
       
   875 		// If we are a server, we restart the server
       
   876 		if (_is_network_server) {
       
   877 			// But not if we are going to the menu
       
   878 			if (new_mode != SM_MENU) {
       
   879 				NetworkServerStart();
       
   880 			} else {
       
   881 				// This client no longer wants to be a network-server
       
   882 				_is_network_server = false;
       
   883 			}
       
   884 		}
       
   885 	}
       
   886 #endif /* ENABLE_NETWORK */
       
   887 
       
   888 	switch (new_mode) {
       
   889 	case SM_EDITOR: /* Switch to scenario editor */
       
   890 		MakeNewEditorWorld();
       
   891 		break;
       
   892 
       
   893 	case SM_NEWGAME: /* New Game --> 'Random game' */
       
   894 #ifdef ENABLE_NETWORK
       
   895 		if (_network_server)
       
   896 			snprintf(_network_game_info.map_name, 40, "Random");
       
   897 #endif /* ENABLE_NETWORK */
       
   898 		MakeNewGame();
       
   899 		break;
       
   900 
       
   901 	case SM_START_SCENARIO: /* New Game --> Choose one of the preset scenarios */
       
   902 		StartScenario();
       
   903 		break;
       
   904 
       
   905 	case SM_LOAD: { /* Load game, Play Scenario */
       
   906 		_opt_ptr = &_opt;
       
   907 
       
   908 		_error_message = INVALID_STRING_ID;
       
   909 		if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL)) {
       
   910 			LoadIntroGame();
       
   911 			ShowErrorMessage(_error_message, STR_4009_GAME_LOAD_FAILED, 0, 0);
       
   912 		} else {
       
   913 			_local_player = 0;
       
   914 			DoCommandP(0, 0, 0, NULL, CMD_PAUSE); // decrease pause counter (was increased from opening load dialog)
       
   915 #ifdef ENABLE_NETWORK
       
   916 			if (_network_server)
       
   917 				snprintf(_network_game_info.map_name, 40, "Loaded game");
       
   918 #endif /* ENABLE_NETWORK */
       
   919 		}
       
   920 		break;
       
   921 	}
       
   922 
       
   923 	case SM_LOAD_SCENARIO: { /* Load scenario from scenario editor */
       
   924 		int i;
       
   925 
       
   926 		if (SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR)) {
       
   927 			_opt_ptr = &_opt;
       
   928 
       
   929 			_local_player = OWNER_NONE;
       
   930 			_generating_world = true;
       
   931 			// delete all players.
       
   932 			for (i = 0; i != MAX_PLAYERS; i++) {
       
   933 				ChangeOwnershipOfPlayerItems(i, 0xff);
       
   934 				_players[i].is_active = false;
       
   935 			}
       
   936 			_generating_world = false;
       
   937 			// delete all stations owned by a player
       
   938 			DeleteAllPlayerStations();
       
   939 
       
   940 #ifdef ENABLE_NETWORK
       
   941 			if (_network_server)
       
   942 				snprintf(_network_game_info.map_name, 40, "Loaded scenario");
       
   943 #endif /* ENABLE_NETWORK */
       
   944 		} else
       
   945 			ShowErrorMessage(INVALID_STRING_ID, STR_4009_GAME_LOAD_FAILED, 0, 0);
       
   946 
       
   947 		break;
       
   948 	}
       
   949 
       
   950 
       
   951 	case SM_MENU: /* Switch to game intro menu */
       
   952 		LoadIntroGame();
       
   953 		break;
       
   954 
       
   955 	case SM_SAVE: /* Save game */
       
   956 		if (SaveOrLoad(_file_to_saveload.name, SL_SAVE) != SL_OK)
       
   957 			ShowErrorMessage(INVALID_STRING_ID, STR_4007_GAME_SAVE_FAILED, 0, 0);
       
   958 		else
       
   959 			DeleteWindowById(WC_SAVELOAD, 0);
       
   960 		break;
       
   961 
       
   962 	case SM_GENRANDLAND: /* Generate random land within scenario editor */
       
   963 		GenerateWorld(2, _patches.map_x, _patches.map_y);
       
   964 		// XXX: set date
       
   965 		_local_player = OWNER_NONE;
       
   966 		MarkWholeScreenDirty();
       
   967 		break;
       
   968 	}
       
   969 
       
   970 	if (_switch_mode_errorstr != INVALID_STRING_ID)
       
   971 		ShowErrorMessage(INVALID_STRING_ID,_switch_mode_errorstr,0,0);
       
   972 
       
   973 	_in_state_game_loop = false;
       
   974 }
       
   975 
       
   976 
       
   977 // State controlling game loop.
       
   978 // The state must not be changed from anywhere
       
   979 // but here.
       
   980 // That check is enforced in DoCommand.
       
   981 void StateGameLoop(void)
       
   982 {
       
   983 	// dont execute the state loop during pause
       
   984 	if (_pause) return;
       
   985 
       
   986 	_in_state_game_loop = true;
       
   987 	// _frame_counter is increased somewhere else when in network-mode
       
   988 	//  Sidenote: _frame_counter is ONLY used for _savedump in non-MP-games
       
   989 	//    Should that not be deleted? If so, the next 2 lines can also be deleted
       
   990 	if (!_networking)
       
   991 		_frame_counter++;
       
   992 
       
   993 	if (_savedump_path[0] && (uint)_frame_counter >= _savedump_first && (uint)(_frame_counter -_savedump_first) % _savedump_freq == 0 ) {
       
   994 		char buf[100];
       
   995 		sprintf(buf, "%s%.5d.sav", _savedump_path, _frame_counter);
       
   996 		SaveOrLoad(buf, SL_SAVE);
       
   997 		if ((uint)_frame_counter >= _savedump_last) exit(1);
       
   998 	}
       
   999 
       
  1000 	if (_game_mode == GM_EDITOR) {
       
  1001 		RunTileLoop();
       
  1002 		CallVehicleTicks();
       
  1003 		CallLandscapeTick();
       
  1004 		CallWindowTickEvent();
       
  1005 		NewsLoop();
       
  1006 	} else {
       
  1007 		// All these actions has to be done from OWNER_NONE
       
  1008 		//  for multiplayer compatibility
       
  1009 		uint p = _current_player;
       
  1010 		_current_player = OWNER_NONE;
       
  1011 
       
  1012 		AnimateAnimatedTiles();
       
  1013 		IncreaseDate();
       
  1014 		RunTileLoop();
       
  1015 		CallVehicleTicks();
       
  1016 		CallLandscapeTick();
       
  1017 
       
  1018 		// To bad the AI does not work in multiplayer, because states are not saved
       
  1019 		//  perfectly
       
  1020 		if (!disable_computer && !_networking)
       
  1021 			RunOtherPlayersLoop();
       
  1022 
       
  1023 		CallWindowTickEvent();
       
  1024 		NewsLoop();
       
  1025 		_current_player = p;
       
  1026 	}
       
  1027 
       
  1028 	_in_state_game_loop = false;
       
  1029 }
       
  1030 
       
  1031 static void DoAutosave(void)
       
  1032 {
       
  1033 	char buf[200];
       
  1034 
       
  1035 	if (_patches.keep_all_autosave && _local_player != OWNER_SPECTATOR) {
       
  1036 		const Player *p = DEREF_PLAYER(_local_player);
       
  1037 		char *s;
       
  1038 		sprintf(buf, "%s%s", _path.autosave_dir, PATHSEP);
       
  1039 
       
  1040 		SetDParam(0, p->name_1);
       
  1041 		SetDParam(1, p->name_2);
       
  1042 		SetDParam(2, _date);
       
  1043 		s = (char*)GetString(buf + strlen(_path.autosave_dir) + strlen(PATHSEP), STR_4004);
       
  1044 		strcpy(s, ".sav");
       
  1045 	} else { /* Save a maximum of 15 autosaves */
       
  1046 		int n = _autosave_ctr;
       
  1047 		_autosave_ctr = (_autosave_ctr + 1) & 15;
       
  1048 		sprintf(buf, "%s%sautosave%d.sav", _path.autosave_dir, PATHSEP, n);
       
  1049 	}
       
  1050 
       
  1051 	DEBUG(misc, 2) ("Autosaving to %s", buf);
       
  1052 	if (SaveOrLoad(buf, SL_SAVE) != SL_OK)
       
  1053 		ShowErrorMessage(INVALID_STRING_ID, STR_AUTOSAVE_FAILED, 0, 0);
       
  1054 }
       
  1055 
       
  1056 static void ScrollMainViewport(int x, int y)
       
  1057 {
       
  1058 	if (_game_mode != GM_MENU) {
       
  1059 		Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
       
  1060 		assert(w);
       
  1061 
       
  1062 		WP(w,vp_d).scrollpos_x += x << w->viewport->zoom;
       
  1063 		WP(w,vp_d).scrollpos_y += y << w->viewport->zoom;
       
  1064 	}
       
  1065 }
       
  1066 
       
  1067 static const int8 scrollamt[16][2] = {
       
  1068 	{ 0, 0},
       
  1069 	{-2, 0}, // 1:left
       
  1070 	{ 0,-2}, // 2:up
       
  1071 	{-2,-1}, // 3:left + up
       
  1072 	{ 2, 0}, // 4:right
       
  1073 	{ 0, 0}, // 5:left + right
       
  1074 	{ 2,-1}, // 6:right + up
       
  1075 	{ 0,-2}, // 7:left + right + up = up
       
  1076 	{ 0 ,2}, // 8:down
       
  1077 	{-2 ,1}, // 9:down+left
       
  1078 	{ 0, 0}, // 10:impossible
       
  1079 	{-2, 0}, // 11:left + up + down = left
       
  1080 	{ 2, 1}, // 12:down+right
       
  1081 	{ 0, 2}, // 13:left + right + down = down
       
  1082 	{ 0,-2}, // 14:left + right + up = up
       
  1083 	{ 0, 0}, // 15:impossible
       
  1084 };
       
  1085 
       
  1086 static void HandleKeyScrolling(void)
       
  1087 {
       
  1088 	if (_dirkeys && !_no_scroll) {
       
  1089 		int factor = _shift_pressed ? 50 : 10;
       
  1090 		ScrollMainViewport(scrollamt[_dirkeys][0] * factor, scrollamt[_dirkeys][1] * factor);
       
  1091 	}
       
  1092 }
       
  1093 
       
  1094 void GameLoop(void)
       
  1095 {
       
  1096 	int m;
       
  1097 
       
  1098 	// autosave game?
       
  1099 	if (_do_autosave) {
       
  1100 		_do_autosave = false;
       
  1101 		DoAutosave();
       
  1102 		RedrawAutosave();
       
  1103 	}
       
  1104 
       
  1105 	// handle scrolling of the main window
       
  1106 	if (_dirkeys) HandleKeyScrolling();
       
  1107 
       
  1108 	// make a screenshot?
       
  1109 	if ((m=_make_screenshot) != 0) {
       
  1110 		_make_screenshot = 0;
       
  1111 		switch(m) {
       
  1112 		case 1: // make small screenshot
       
  1113 			UndrawMouseCursor();
       
  1114 			ShowScreenshotResult(MakeScreenshot());
       
  1115 			break;
       
  1116 		case 2: // make large screenshot
       
  1117 			ShowScreenshotResult(MakeWorldScreenshot(-(int)MapMaxX() * 32, 0, MapMaxX() * 64, MapSizeY() * 32, 0));
       
  1118 			break;
       
  1119 		}
       
  1120 	}
       
  1121 
       
  1122 	// switch game mode?
       
  1123 	if ((m=_switch_mode) != SM_NONE) {
       
  1124 		_switch_mode = SM_NONE;
       
  1125 		SwitchMode(m);
       
  1126 	}
       
  1127 
       
  1128 	IncreaseSpriteLRU();
       
  1129 	InteractiveRandom();
       
  1130 
       
  1131 	if (_scroller_click_timeout > 3)
       
  1132 		_scroller_click_timeout -= 3;
       
  1133 	else
       
  1134 		_scroller_click_timeout = 0;
       
  1135 
       
  1136 	_caret_timer += 3;
       
  1137 	_timer_counter+=8;
       
  1138 	CursorTick();
       
  1139 
       
  1140 #ifdef ENABLE_NETWORK
       
  1141 	// Check for UDP stuff
       
  1142 	NetworkUDPGameLoop();
       
  1143 
       
  1144 	if (_networking) {
       
  1145 		// Multiplayer
       
  1146 		NetworkGameLoop();
       
  1147 	} else {
       
  1148 		if (_network_reconnect > 0 && --_network_reconnect == 0) {
       
  1149 			// This means that we want to reconnect to the last host
       
  1150 			// We do this here, because it means that the network is really closed
       
  1151 			NetworkClientConnectGame(_network_last_host, _network_last_port);
       
  1152 		}
       
  1153 		// Singleplayer
       
  1154 		StateGameLoop();
       
  1155 	}
       
  1156 #else
       
  1157 	StateGameLoop();
       
  1158 #endif /* ENABLE_NETWORK */
       
  1159 
       
  1160 	if (!_pause && _display_opt&DO_FULL_ANIMATION)
       
  1161 		DoPaletteAnimations();
       
  1162 
       
  1163 	if (!_pause || _cheats.build_in_pause.value)
       
  1164 		MoveAllTextEffects();
       
  1165 
       
  1166 	InputLoop();
       
  1167 
       
  1168 	MusicLoop();
       
  1169 }
       
  1170 
       
  1171 void BeforeSaveGame(void)
       
  1172 {
       
  1173 	Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
       
  1174 
       
  1175 	if (w != NULL) {
       
  1176 		_saved_scrollpos_x = WP(w,vp_d).scrollpos_x;
       
  1177 		_saved_scrollpos_y = WP(w,vp_d).scrollpos_y;
       
  1178 		_saved_scrollpos_zoom = w->viewport->zoom;
       
  1179 	}
       
  1180 }
       
  1181 
       
  1182 static void ConvertTownOwner(void)
       
  1183 {
       
  1184 	uint tile;
       
  1185 
       
  1186 	for (tile = 0; tile != MapSize(); tile++) {
       
  1187 		if (IsTileType(tile, MP_STREET)) {
       
  1188 			if ((_map5[tile] & 0xF0) == 0x10 && _map3_lo[tile] & 0x80)
       
  1189 				_map3_lo[tile] = OWNER_TOWN;
       
  1190 
       
  1191 			if (_map_owner[tile] & 0x80)
       
  1192 				_map_owner[tile] = OWNER_TOWN;
       
  1193 		} else if (IsTileType(tile, MP_TUNNELBRIDGE)) {
       
  1194 			if (_map_owner[tile] & 0x80)
       
  1195 				_map_owner[tile] = OWNER_TOWN;
       
  1196 		}
       
  1197 	}
       
  1198 }
       
  1199 
       
  1200 // before savegame version 4, the name of the company determined if it existed
       
  1201 static void CheckIsPlayerActive(void)
       
  1202 {
       
  1203 	Player *p;
       
  1204 	FOR_ALL_PLAYERS(p) {
       
  1205 		if (p->name_1 != 0) {
       
  1206 			p->is_active = true;
       
  1207 		}
       
  1208 	}
       
  1209 }
       
  1210 
       
  1211 // since savegame version 4.1, exclusive transport rights are stored at towns
       
  1212 static void UpdateExclusiveRights(void)
       
  1213 {
       
  1214 	Town *t;
       
  1215 	FOR_ALL_TOWNS(t) if (t->xy != 0) {
       
  1216 		t->exclusivity=(byte)-1;
       
  1217 	}
       
  1218 
       
  1219 	/* FIXME old exclusive rights status is not being imported (stored in s->blocked_months_obsolete)
       
  1220 			could be implemented this way:
       
  1221 			1.) Go through all stations
       
  1222 					Build an array town_blocked[ town_id ][ player_id ]
       
  1223 				 that stores if at least one station in that town is blocked for a player
       
  1224 			2.) Go through that array, if you find a town that is not blocked for
       
  1225 				 	one player, but for all others, then give him exclusivity.
       
  1226 	*/
       
  1227 }
       
  1228 
       
  1229 const byte convert_currency[] = {
       
  1230 	 0,  1, 12,  8,  3,
       
  1231 	10, 14, 19,  4,  5,
       
  1232 	 9, 11, 13,  6, 17,
       
  1233 	16, 22, 21,  7, 15,
       
  1234 	18,  2, 20, };
       
  1235 
       
  1236 // since savegame version 4.2 the currencies are arranged differently
       
  1237 static void UpdateCurrencies(void)
       
  1238 {
       
  1239 	_opt.currency = convert_currency[_opt.currency];
       
  1240 }
       
  1241 
       
  1242 /* Up to revision 1413 the invisible tiles at the southern border have not been
       
  1243  * MP_VOID, even though they should have. This is fixed by this function
       
  1244  */
       
  1245 static void UpdateVoidTiles(void)
       
  1246 {
       
  1247 	uint i;
       
  1248 
       
  1249 	for (i = 0; i < MapMaxY(); ++i)
       
  1250 		SetTileType(i * MapSizeX() + MapMaxX(), MP_VOID);
       
  1251 	for (i = 0; i < MapSizeX(); ++i)
       
  1252 		SetTileType(MapSizeX() * MapMaxY() + i, MP_VOID);
       
  1253 }
       
  1254 
       
  1255 // since savegame version 6.0 each sign has an "owner", signs without owner (from old games are set to 255)
       
  1256 static void UpdateSignOwner(void)
       
  1257 {
       
  1258 	SignStruct *ss;
       
  1259 	FOR_ALL_SIGNS(ss) {
       
  1260 		ss->owner = OWNER_NONE; // no owner
       
  1261 	}
       
  1262 }
       
  1263 
       
  1264 extern void UpdateOldAircraft( void );
       
  1265 extern void UpdateOilRig( void );
       
  1266 
       
  1267 bool AfterLoadGame(uint version)
       
  1268 {
       
  1269 	Window *w;
       
  1270 	ViewPort *vp;
       
  1271 
       
  1272 	// in version 2.1 of the savegame, town owner was unified.
       
  1273 	if (version <= 0x200) {
       
  1274 		ConvertTownOwner();
       
  1275 	}
       
  1276 
       
  1277 	// from version 4.1 of the savegame, exclusive rights are stored at towns
       
  1278 	if (version <= 0x400) {
       
  1279 		UpdateExclusiveRights();
       
  1280 	}
       
  1281 
       
  1282 	// from version 4.2 of the savegame, currencies are in a different order
       
  1283 	if (version <= 0x401) {
       
  1284 		UpdateCurrencies();
       
  1285 	}
       
  1286 
       
  1287 	// from version 6.0 of the savegame, signs have an "owner"
       
  1288 	if (version <= 0x600) {
       
  1289 		UpdateSignOwner();
       
  1290 	}
       
  1291 
       
  1292 	/* In old version there seems to be a problem that water is owned by
       
  1293 	    OWNER_NONE, not OWNER_WATER.. I can't replicate it for the current
       
  1294 	    (0x402) version, so I just check when versions are older, and then
       
  1295 	    walk through the whole map.. */
       
  1296 	if (version <= 0x402) {
       
  1297 		TileIndex tile = TILE_XY(0,0);
       
  1298 		uint w = MapSizeX();
       
  1299 		uint h = MapSizeY();
       
  1300 
       
  1301 		BEGIN_TILE_LOOP(tile_cur, w, h, tile)
       
  1302 			if (IsTileType(tile_cur, MP_WATER) && _map_owner[tile_cur] >= MAX_PLAYERS)
       
  1303 				_map_owner[tile_cur] = OWNER_WATER;
       
  1304 		END_TILE_LOOP(tile_cur, w, h, tile)
       
  1305 	}
       
  1306 
       
  1307 	// convert road side to my format.
       
  1308 	if (_opt.road_side) _opt.road_side = 1;
       
  1309 
       
  1310 	// Load the sprites
       
  1311 	GfxLoadSprites();
       
  1312 
       
  1313 	// Update current year
       
  1314 	SetDate(_date);
       
  1315 
       
  1316 	// reinit the landscape variables (landscape might have changed)
       
  1317 	InitializeLandscapeVariables(true);
       
  1318 
       
  1319 	// Update all vehicles
       
  1320 	AfterLoadVehicles();
       
  1321 
       
  1322 	// Update all waypoints
       
  1323 	if (version < 0x0C00)
       
  1324 		FixOldWaypoints();
       
  1325 
       
  1326 	UpdateAllWaypointSigns();
       
  1327 
       
  1328 	// in version 2.2 of the savegame, we have new airports
       
  1329 	if (version <= 0x201) {
       
  1330 		UpdateOldAircraft();
       
  1331 	}
       
  1332 
       
  1333 	UpdateAllStationVirtCoord();
       
  1334 
       
  1335 	// Setup town coords
       
  1336 	AfterLoadTown();
       
  1337 	UpdateAllSignVirtCoords();
       
  1338 
       
  1339 	// make sure there is a town in the game
       
  1340 	if (_game_mode == GM_NORMAL && !ClosestTownFromTile(0, (uint)-1))
       
  1341 	{
       
  1342 		_error_message = STR_NO_TOWN_IN_SCENARIO;
       
  1343 		return false;
       
  1344 	}
       
  1345 
       
  1346 	// Initialize windows
       
  1347 	ResetWindowSystem();
       
  1348 	SetupColorsAndInitialWindow();
       
  1349 
       
  1350 	w = FindWindowById(WC_MAIN_WINDOW, 0);
       
  1351 
       
  1352 	WP(w,vp_d).scrollpos_x = _saved_scrollpos_x;
       
  1353 	WP(w,vp_d).scrollpos_y = _saved_scrollpos_y;
       
  1354 
       
  1355 	vp = w->viewport;
       
  1356 	vp->zoom = _saved_scrollpos_zoom;
       
  1357 	vp->virtual_width = vp->width << vp->zoom;
       
  1358 	vp->virtual_height = vp->height << vp->zoom;
       
  1359 
       
  1360 
       
  1361 	// in version 4.0 of the savegame, is_active was introduced to determine
       
  1362 	// if a player does exist, rather then checking name_1
       
  1363 	if (version <= 0x400) {
       
  1364 		CheckIsPlayerActive();
       
  1365 	}
       
  1366 
       
  1367 	// the void tiles on the southern border used to belong to a wrong class.
       
  1368 	if (version <= 0x402)
       
  1369 		UpdateVoidTiles();
       
  1370 
       
  1371 	// If Load Scenario / New (Scenario) Game is used,
       
  1372 	//  a player does not exist yet. So create one here.
       
  1373 	// 1 exeption: network-games. Those can have 0 players
       
  1374 	//   But this exeption is not true for network_servers!
       
  1375 	if (!_players[0].is_active && (!_networking || (_networking && _network_server)))
       
  1376 		DoStartupNewPlayer(false);
       
  1377 
       
  1378 	DoZoomInOutWindow(ZOOM_NONE, w); // update button status
       
  1379 	MarkWholeScreenDirty();
       
  1380 
       
  1381 	//In 5.1, Oilrigs have been moved (again)
       
  1382 	if (version <= 0x500) {
       
  1383 		UpdateOilRig();
       
  1384 	}
       
  1385 
       
  1386 	if (version <= 0x600) {
       
  1387 		BEGIN_TILE_LOOP(tile, MapSizeX(), MapSizeY(), 0) {
       
  1388 			if (IsTileType(tile, MP_HOUSE)) {
       
  1389 				_map3_hi[tile] = _map2[tile];
       
  1390 				//XXX magic
       
  1391 				SetTileType(tile, MP_VOID);
       
  1392 				_map2[tile] = ClosestTownFromTile(tile,(uint)-1)->index;
       
  1393 				SetTileType(tile, MP_HOUSE);
       
  1394 			} else if (IsTileType(tile, MP_STREET)) {
       
  1395 				//XXX magic
       
  1396 				SetTileType(tile, MP_VOID);
       
  1397 				_map3_hi[tile] |= (_map2[tile] << 4);
       
  1398 				if ( _map_owner[tile] == OWNER_TOWN)
       
  1399 					_map2[tile] = ClosestTownFromTile(tile,(uint)-1)->index;
       
  1400 				else
       
  1401 					_map2[tile] = 0;
       
  1402 				SetTileType(tile, MP_STREET);
       
  1403 			}
       
  1404 		} END_TILE_LOOP(tile, MapSizeX(), MapSizeY(), 0);
       
  1405 	}
       
  1406 
       
  1407 	if (version < 0x900) {
       
  1408 		Town *t;
       
  1409 		FOR_ALL_TOWNS(t) {
       
  1410 			UpdateTownMaxPass(t);
       
  1411 		}
       
  1412 	}
       
  1413 
       
  1414 	return true;
       
  1415 }