1 //       _________ __                 __
2 //      /   _____//  |_____________ _/  |______     ____  __ __  ______
3 //      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
4 //      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ |
5 //     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
6 //             \/                  \/          \//_____/            \/
7 //  ______________________                           ______________________
8 //                        T H E   W A R   B E G I N S
9 //         Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name stratagus.cpp - The main file. */
12 //
13 //      (c) Copyright 1998-2015 by Lutz Sammer, Francois Beerten,
14 //                                 Jimmy Salmon, Pali Rohár and cybermind
15 //
16 //      This program is free software; you can redistribute it and/or modify
17 //      it under the terms of the GNU General Public License as published by
18 //      the Free Software Foundation; only version 2 of the License.
19 //
20 //      This program is distributed in the hope that it will be useful,
21 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
22 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 //      GNU General Public License for more details.
24 //
25 //      You should have received a copy of the GNU General Public License
26 //      along with this program; if not, write to the Free Software
27 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 //      02111-1307, USA.
29 //
30 
31 //@{
32 
33 /**
34 ** @mainpage
35 **
36 ** @section Introduction Introduction
37 **
38 ** Welcome to the source code documentation of the Stratagus engine.
39 ** Extract the source documentation with doxygen (http://www.doxygen.org) tool.
40 **
41 ** Any help to improve this documention is welcome. If you didn't
42 ** understand something or you found an error or a wrong spelling
43 ** or wrong grammar please write an email (including a patch :).
44 **
45 ** @section Information Information
46 **
47 ** Visit the https://github.com/Wargus/stratagus web page for the latest news and
48 ** <A HREF="../index.html">Stratagus Info</A> for other documentation.
49 **
50 ** @section Modules Modules
51 **
52 ** This are the main modules of the Stratagus engine.
53 **
54 ** @subsection Map Map
55 **
56 ** Handles the map. A map is made from tiles.
57 **
58 ** @see map.h @see map.cpp @see tileset.h @see tileset.cpp
59 **
60 ** @subsection Unit Unit
61 **
62 ** Handles units. Units are ships, flyers, buildings, creatures,
63 ** machines.
64 **
65 ** @see unit.h @see unit.cpp @see unittype.h @see unittype.cpp
66 **
67 ** @subsection Missile Missile
68 **
69 ** Handles missiles. Missiles are all other sprites on map
70 ** which are no unit.
71 **
72 ** @see missile.h @see missile.cpp
73 **
74 ** @subsection Player Player
75 **
76 ** Handles players, all units are owned by a player. A player
77 ** could be controlled by a human or a computer.
78 **
79 ** @see player.h @see player.cpp @see ::CPlayer
80 **
81 ** @subsection Sound Sound
82 **
83 ** Handles the high and low level of the sound. There are the
84 ** background music support, voices and sound effects.
85 ** Following low level backends are supported: OSS and SDL.
86 **
87 ** @todo adpcm file format support for sound effects
88 ** @todo better separation of low and high level, assembler mixing
89 ** support.
90 ** @todo Streaming support of ogg/mp3 files.
91 **
92 ** @see sound.h @see sound.cpp
93 ** @see script_sound.cpp @see sound_id.cpp @see sound_server.cpp
94 ** @see unitsound.cpp
95 ** @see sdl_audio.cpp
96 ** @see ogg.cpp @see wav.cpp
97 **
98 ** @subsection Video Video
99 **
100 ** Handles the high and low level of the graphics.
101 ** This also contains the sprite and linedrawing routines.
102 **
103 ** See page @ref VideoModule for more information upon supported
104 ** features and video platforms.
105 **
106 ** @see video.h @see video.cpp
107 **
108 ** @subsection Network Network
109 **
110 ** Handles the high and low level of the network protocol.
111 ** The network protocol is needed for multiplayer games.
112 **
113 ** See page @ref NetworkModule for more information upon supported
114 ** features and API.
115 **
116 ** @see network.h @see network.cpp
117 **
118 ** @subsection Pathfinder Pathfinder
119 **
120 ** @see pathfinder.h @see pathfinder.cpp
121 **
122 ** @subsection AI AI
123 **
124 ** There are currently two AI's. The old one is very hardcoded,
125 ** but does things like placing buildings better than the new.
126 ** The old AI shouldn't be used.  The new is very flexible, but
127 ** very basic. It includes none optimations.
128 **
129 ** See page @ref AiModule for more information upon supported
130 ** features and API.
131 **
132 ** @see ai_local.h
133 ** @see ai.h @see ai.cpp
134 **
135 ** @subsection CCL CCL
136 **
137 ** CCL is Craft Configuration Language, which is used to
138 ** configure and customize Stratagus.
139 **
140 ** @see script.h @see script.cpp
141 **
142 ** @subsection Icon Icon
143 **
144 ** @see icons.h @see icons.cpp
145 **
146 ** @subsection Editor Editor
147 **
148 ** This is the integrated editor, it shouldn't be a perfect
149 ** editor. It is used to test new features of the engine.
150 **
151 ** See page @ref EditorModule for more information upon supported
152 ** features and API.
153 **
154 ** @see editor.h @see editor.cpp
155 */
156 
157 /*----------------------------------------------------------------------------
158 --  Includes
159 ----------------------------------------------------------------------------*/
160 
161 #include <ctype.h>
162 
163 #ifdef USE_BEOS
164 #include <fcntl.h>
165 #include <sys/types.h>
166 #include <sys/stat.h>
167 
168 extern void beos_init(int argc, char **argv);
169 
170 #endif
171 
172 #ifdef MAC_BUNDLE
173 #define Button ButtonOSX
174 #include <Carbon/Carbon.h>
175 #undef Button
176 #endif
177 
178 #include "SDL.h"
179 
180 #include "stratagus.h"
181 
182 #include "ai.h"
183 #include "editor.h"
184 #include "game.h"
185 #include "guichan.h"
186 #include "interface.h"
187 #include "iocompat.h"
188 #include "iolib.h"
189 #include "map.h"
190 #include "netconnect.h"
191 #include "network.h"
192 #include "parameters.h"
193 #include "player.h"
194 #include "replay.h"
195 #include "results.h"
196 #include "settings.h"
197 #include "sound_server.h"
198 #include "title.h"
199 #include "translate.h"
200 #include "ui.h"
201 #include "unit_manager.h"
202 #include "version.h"
203 #include "video.h"
204 #include "widgets.h"
205 #include "util.h"
206 
207 #include "missile.h" //for FreeBurningBuildingFrames
208 
209 #ifdef USE_STACKTRACE
210 #include <stdexcept>
211 #include <stacktrace/call_stack.hpp>
212 #include <stacktrace/stack_exception.hpp>
213 #else
214 #include "st_backtrace.h"
215 #endif
216 
217 #include <stdlib.h>
218 #include <stdio.h>
219 
220 #ifdef USE_WIN32
221 #include <windows.h>
222 #include <dbghelp.h>
223 #endif
224 
225 #if defined(USE_WIN32) && ! defined(NO_STDIO_REDIRECT)
226 #include "windows.h"
227 #define REDIRECT_OUTPUT
228 #endif
229 
230 #if defined(USE_WIN32) && ! defined(REDIRECT_OUTPUT)
231 #include "SetupConsole_win32.h"
232 #endif
233 
234 /*----------------------------------------------------------------------------
235 --  Variables
236 ----------------------------------------------------------------------------*/
237 
238 std::string StratagusLibPath;        /// Path for data directory
239 
240 /// Name, Version, Copyright
241 const char NameLine[] = NAME " v" VERSION ", " COPYRIGHT;
242 
243 std::string CliMapName;          /// Filename of the map given on the command line
244 std::string MenuRace;
245 
246 bool EnableDebugPrint;           /// if enabled, print the debug messages
247 bool EnableAssert;               /// if enabled, halt on assertion failures
248 bool EnableUnitDebug;            /// if enabled, a unit info dump will be created
249 
250 #ifdef DEBUG
251 bool IsDebugEnabled {true};      /// Is debug enabled? Flag to pass into lua code.
252 #else
253 bool IsDebugEnabled {false};     /// Is debug enabled? Flag to pass into lua code.
254 #endif
255 bool EnableWallsInSinglePlayer {false}; /// Enables ability to build walls in the single player games
256 										/// used for debug purposes
257 
258 /*============================================================================
259 ==  MAIN
260 ============================================================================*/
261 
262 /**
263 **  Pre menu setup.
264 */
PreMenuSetup()265 void PreMenuSetup()
266 {
267 	//
268 	//  Initial menus require some gfx.
269 	//
270 	SetDefaultTextColors(FontYellow, FontWhite);
271 
272 	LoadFonts();
273 
274 	InitVideoCursors();
275 
276 	if (MenuRace.empty()) {
277 		LoadCursors(PlayerRaces.Name[0]);
278 	} else {
279 		LoadCursors(MenuRace);
280 	}
281 
282 	InitSettings();
283 
284 	InitUserInterface();
285 	UI.Load();
286 }
287 
288 /**
289 **  Run the guichan main menus loop.
290 **
291 **  @return          0 for success, else exit.
292 */
MenuLoop()293 static int MenuLoop()
294 {
295 	int status;
296 
297 	initGuichan();
298 	InterfaceState = IfaceStateMenu;
299 	//  Clear screen
300 	Video.ClearScreen();
301 	Invalidate();
302 
303 	ButtonUnderCursor = -1;
304 	OldButtonUnderCursor = -1;
305 	CursorState = CursorStatePoint;
306 	GameCursor = UI.Point.Cursor;
307 
308 	// FIXME delete this when switching to full guichan GUI
309 	const std::string filename = LibraryFileName("scripts/guichan.lua");
310 	status = LuaLoadFile(filename);
311 
312 	// We clean up later in Exit
313 	return status;
314 }
315 
316 //----------------------------------------------------------------------------
317 
318 /**
319 **  Print headerline, copyright, ...
320 */
PrintHeader()321 static void PrintHeader()
322 {
323 	std::string CompileOptions =
324 #ifdef DEBUG
325 		"DEBUG "
326 #endif
327 #ifdef USE_ZLIB
328 		"ZLIB "
329 #endif
330 #ifdef USE_BZ2LIB
331 		"BZ2LIB "
332 #endif
333 #ifdef USE_VORBIS
334 		"VORBIS "
335 #endif
336 #ifdef USE_THEORA
337 		"THEORA "
338 #endif
339 #ifdef USE_WIN32
340 		"WIN32 "
341 #endif
342 #ifdef USE_LINUX
343 		"LINUX "
344 #endif
345 #ifdef USE_BSD
346 		"BSD "
347 #endif
348 #ifdef USE_BEOS
349 		"BEOS "
350 #endif
351 #ifdef USE_MAC
352 		"MAC "
353 #endif
354 		"";
355 
356 	fprintf(stdout,
357 			"%s\n  written by Lutz Sammer, Fabrice Rossi, Vladi Shabanski, Patrice Fortier,\n"
358 			"  Jon Gabrielson, Andreas Arens, Nehal Mistry, Jimmy Salmon, Pali Rohar,\n"
359 			"  cybermind and others.\n"
360 			"\t" HOMEPAGE "\n"
361 			"Compile options %s",
362 			NameLine, CompileOptions.c_str());
363 }
364 
PrintLicense()365 void PrintLicense()
366 {
367 	printf("\n"
368 		   "\n"
369 		   "Stratagus may be copied only under the terms of the GNU General Public License\n"
370 		   "which may be found in the Stratagus source kit.\n"
371 		   "\n"
372 		   "DISCLAIMER:\n"
373 		   "This software is provided as-is.  The author(s) can not be held liable for any\n"
374 		   "damage that might arise from the use of this software.\n"
375 		   "Use it at your own risk.\n"
376 		   "\n");
377 }
378 
379 
380 /**
381 **  Exit the game.
382 **
383 **  @param err  Error code to pass to shell.
384 */
Exit(int err)385 void Exit(int err)
386 {
387 	if (GameRunning) {
388 		StopGame(GameExit);
389 		return;
390 	}
391 
392 	StopMusic();
393 	QuitSound();
394 	NetworkQuitGame();
395 
396 	ExitNetwork1();
397 	CleanModules();
398 	FreeBurningBuildingFrames();
399 	FreeSounds();
400 	FreeGraphics();
401 	FreePlayerColors();
402 	FreeButtonStyles();
403 	FreeAllContainers();
404 	freeGuichan();
405 	DebugPrint("Frames %lu, Slow frames %d = %ld%%\n" _C_
406 			   FrameCounter _C_ SlowFrameCounter _C_
407 			   (SlowFrameCounter * 100) / (FrameCounter ? FrameCounter : 1));
408 	lua_settop(Lua, 0);
409 	lua_close(Lua);
410 	DeInitVideo();
411 	DeInitImageLoaders();
412 
413 	fprintf(stdout, "%s", _("Thanks for playing Stratagus.\n"));
414 	exit(err);
415 }
416 
417 /**
418 **  Do a fatal exit.
419 **  Called on out of memory or crash.
420 **
421 **  @param err  Error code to pass to shell.
422 */
ExitFatal(int err)423 void ExitFatal(int err)
424 {
425 #ifdef USE_STACKTRACE
426 	throw stacktrace::stack_runtime_error((const char*)err);
427 #else
428 	print_backtrace();
429 #endif
430 	exit(err);
431 }
432 
433 /**
434 **  Display the usage.
435 */
Usage()436 static void Usage()
437 {
438 	PrintHeader();
439 	printf(
440 		"\n\nUsage: %s [OPTIONS] [map.smp|map.smp.gz]\n"
441 		"\t-a\t\tEnables asserts check in engine code (for debugging)\n"
442 		"\t-c file.lua\tConfiguration start file (default stratagus.lua)\n"
443 		"\t-d datapath\tPath to stratagus data (default current directory)\n"
444 		"\t-D depth\tVideo mode depth = pixel per point\n"
445 		"\t-e\t\tStart editor (instead of game)\n"
446 		"\t-E file.lua\tEditor configuration start file (default editor.lua)\n"
447 		"\t-F\t\tFull screen video mode\n"
448 		"\t-g\t\tForce software rendering (implies no shaders)\n"
449 		"\t-G \"options\"\tGame options (passed to game scripts)\n"
450 		"\t-h\t\tHelp shows this page\n"
451 		"\t-i\t\tEnables unit info dumping into log (for debugging)\n"
452 		"\t-I addr\t\tNetwork address to use\n"
453 		"\t-l\t\tDisable command log\n"
454 		"\t-N name\t\tName of the player\n"
455 		"\t-p\t\tEnables debug messages printing in console\n"
456 		"\t-P port\t\tNetwork port to use\n"
457 		"\t-s sleep\tNumber of frames for the AI to sleep before it starts\n"
458 		"\t-S speed\tSync speed (100 = 30 frames/s)\n"
459 		"\t-u userpath\tPath where stratagus saves preferences, log and savegame. Use 'userhome' to force platform-default userhome directory.\n"
460 		"\t-v mode\t\tVideo mode resolution in format <xres>x<yres>\n"
461 		"\t-W\t\tWindowed video mode. Optionally takes a window size in <xres>x<yres>\n"
462 		"map is relative to StratagusLibPath=datapath, use ./map for relative to cwd\n",
463 		Parameters::Instance.applicationName.c_str());
464 }
465 
466 #ifdef REDIRECT_OUTPUT
467 
468 static std::string stdoutFile;
469 static std::string stderrFile;
470 
CleanupOutput()471 static void CleanupOutput()
472 {
473 	fclose(stdout);
474 	fclose(stderr);
475 
476 	struct stat st;
477 	if (stat(stdoutFile.c_str(), &st) == 0 && st.st_size == 0) {
478 		unlink(stdoutFile.c_str());
479 	}
480 	if (stat(stderrFile.c_str(), &st) == 0 && st.st_size == 0) {
481 		unlink(stderrFile.c_str());
482 	}
483 }
484 
RedirectOutput()485 static void RedirectOutput()
486 {
487 	std::string path = Parameters::Instance.GetUserDirectory();
488 
489 	makedir(path.c_str(), 0777);
490 
491 	stdoutFile = path + "\\stdout.txt";
492 	stderrFile = path + "\\stderr.txt";
493 
494 	if (!freopen(stdoutFile.c_str(), "w", stdout)) {
495 		printf("freopen stdout failed");
496 	}
497 	if (!freopen(stderrFile.c_str(), "w", stderr)) {
498 		printf("freopen stderr failed");
499 	}
500 	atexit(CleanupOutput);
501 }
502 #endif
503 
ParseCommandLine(int argc,char ** argv,Parameters & parameters)504 void ParseCommandLine(int argc, char **argv, Parameters &parameters)
505 {
506 	char *sep;
507 	for (;;) {
508 		switch (getopt(argc, argv, "ac:d:D:eE:FgG:hiI:lN:oOP:ps:S:u:v:W?-")) {
509 			case 'a':
510 				EnableAssert = true;
511 				continue;
512 			case 'c':
513 				parameters.luaStartFilename = optarg;
514 				if (strlen(optarg) > 4 &&
515 				    !(strstr(optarg, ".lua") == optarg + strlen(optarg) - 4)) {
516 					parameters.luaStartFilename += ".lua";
517 				}
518 				continue;
519 			case 'd': {
520 				StratagusLibPath = optarg;
521 				size_t index;
522 				while ((index = StratagusLibPath.find('\\')) != std::string::npos) {
523 					StratagusLibPath[index] = '/';
524 				}
525 				continue;
526 			}
527 			case 'D':
528 				Video.Depth = atoi(optarg);
529 				continue;
530 			case 'e':
531 				Editor.Running = EditorCommandLine;
532 				continue;
533 			case 'E':
534 				parameters.luaEditorStartFilename = optarg;
535 				continue;
536 			case 'F':
537 				VideoForceFullScreen = 1;
538 				Video.FullScreen = 1;
539 				continue;
540 			case 'g':
541 				SDL_SetHintWithPriority(SDL_HINT_RENDER_DRIVER, "software", SDL_HINT_OVERRIDE);
542 				continue;
543 			case 'G':
544 				parameters.luaScriptArguments = optarg;
545 				continue;
546 			case 'i':
547 				EnableUnitDebug = true;
548 				continue;
549 			case 'I':
550 				CNetworkParameter::Instance.localHost = optarg;
551 				continue;
552 			case 'l':
553 				CommandLogDisabled = true;
554 				continue;
555 			case 'N':
556 				parameters.LocalPlayerName = optarg;
557 				continue;
558 			case 'P':
559 				CNetworkParameter::Instance.localPort = atoi(optarg);
560 				continue;
561 			case 'p':
562 				EnableDebugPrint = true;
563 				continue;
564 			case 's':
565 				AiSleepCycles = atoi(optarg);
566 				continue;
567 			case 'S':
568 				VideoSyncSpeed = atoi(optarg);
569 				continue;
570 			case 'u':
571 				if (!strcmp(optarg, "userhome")) {
572 					Parameters::Instance.SetUserDirectory("");
573 				} else {
574 					Parameters::Instance.SetUserDirectory(optarg);
575 				}
576 				continue;
577 			case 'v': {
578 				sep = strchr(optarg, 'x');
579 				if (!sep || !*(sep + 1)) {
580 					fprintf(stderr, "%s: incorrect format of video mode resolution -- '%s'\n", argv[0], optarg);
581 					Usage();
582 					exit(-1);
583 				}
584 				Video.Height = atoi(sep + 1);
585 				*sep = 0;
586 				Video.Width = atoi(optarg);
587 				if (!Video.Height || !Video.Width) {
588 					fprintf(stderr, "%s: incorrect format of video mode resolution -- '%sx%s'\n", argv[0], optarg, sep + 1);
589 					Usage();
590 					exit(-1);
591 				}
592 				continue;
593 			}
594 			case 'W':
595 				if (optind < argc && argv[optind] && argv[optind][0] != '-') {
596 					// allow -W to take an optional argument in a POSIX compliant way
597 					optarg = argv[optind];
598 					sep = strchr(optarg, 'x');
599 					if (!sep || !*(sep + 1)) {
600 						fprintf(stderr, "%s: incorrect window size -- '%s'\n", argv[0], optarg);
601 						Usage();
602 						exit(-1);
603 					}
604 					Video.WindowHeight = atoi(sep + 1);
605 					*sep = 0;
606 					Video.WindowWidth = atoi(optarg);
607 					if (!Video.WindowHeight || !Video.WindowWidth) {
608 						fprintf(stderr, "%s: incorrect window size -- '%sx%s'\n", argv[0], optarg, sep + 1);
609 						Usage();
610 						exit(-1);
611 					}
612 					optind += 1; // skip the optional window size argument
613 				}
614 				VideoForceFullScreen = 1;
615 				Video.FullScreen = 0;
616 				continue;
617 			case -1:
618 				break;
619 			case '?':
620 			case 'h':
621 			default:
622 				Usage();
623 				exit(-1);
624 		}
625 		break;
626 	}
627 
628 	if (argc - optind > 1) {
629 		fprintf(stderr, "too many map files. if you meant to pass game arguments, these go after '--'\n");
630 		Usage();
631 		ExitFatal(-1);
632 	}
633 
634 	if (argc - optind) {
635 		size_t index;
636 		CliMapName = argv[optind];
637 		while ((index = CliMapName.find('\\')) != std::string::npos) {
638 			CliMapName[index] = '/';
639 		}
640 	}
641 }
642 
643 #ifdef USE_WIN32
CreateDumpFile(EXCEPTION_POINTERS * ExceptionInfo)644 static LONG WINAPI CreateDumpFile(EXCEPTION_POINTERS *ExceptionInfo)
645 {
646 	HANDLE hFile = CreateFile("crash.dmp", GENERIC_READ | GENERIC_WRITE,	FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
647 		NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,	NULL);
648 	MINIDUMP_EXCEPTION_INFORMATION mei;
649 	mei.ThreadId = GetCurrentThreadId();
650 	mei.ClientPointers = TRUE;
651 	mei.ExceptionPointers = ExceptionInfo;
652 	MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mei, NULL, NULL);
653 	fprintf(stderr, "Stratagus crashed!\n");
654 	fprintf(stderr, "A mini dump file \"crash.dmp\" has been created in the Stratagus folder.\n");
655 	fprintf(stderr, "Please send it to our bug tracker: https://github.com/Wargus/stratagus/issues\n");
656 	fprintf(stderr, "and tell us what caused this bug to occur.\n");
657 	return EXCEPTION_EXECUTE_HANDLER;
658 }
659 #endif
660 
661 /**
662 **  The main program: initialise, parse options and arguments.
663 **
664 **  @param argc  Number of arguments.
665 **  @param argv  Vector of arguments.
666 */
stratagusMain(int argc,char ** argv)667 int stratagusMain(int argc, char **argv)
668 {
669 #ifdef USE_BEOS
670 	//  Parse arguments for BeOS
671 	beos_init(argc, argv);
672 #endif
673 #ifdef USE_WIN32
674 	SetUnhandledExceptionFilter(CreateDumpFile);
675 #endif
676 #if defined(USE_WIN32) && ! defined(REDIRECT_OUTPUT)
677 	SetupConsole();
678 #endif
679 	//  Setup some defaults.
680 #ifndef MAC_BUNDLE
681 	StratagusLibPath = ".";
682 #else
683 	freopen("/tmp/stdout.txt", "w", stdout);
684 	freopen("/tmp/stderr.txt", "w", stderr);
685 	// Look for the specified data set inside the application bundle
686 	// This should be a subdir of the Resources directory
687 	CFURLRef pluginRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
688 												 CFSTR(MAC_BUNDLE_DATADIR), NULL, NULL);
689 	CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef,  kCFURLPOSIXPathStyle);
690 	const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding());
691 	Assert(pathPtr);
692 	StratagusLibPath = pathPtr;
693 #endif
694 	try {
695 		Parameters &parameters = Parameters::Instance;
696 		parameters.SetDefaultValues();
697 		parameters.SetLocalPlayerNameFromEnv();
698 
699 #ifdef REDIRECT_OUTPUT
700 		RedirectOutput();
701 #endif
702 
703 		if (argc > 0) {
704 			parameters.applicationName = argv[0];
705 		}
706 
707 		// FIXME: Parse options before or after scripts?
708 		ParseCommandLine(argc, argv, parameters);
709 		// Init the random number generator.
710 		InitSyncRand();
711 
712 		makedir(parameters.GetUserDirectory().c_str(), 0777);
713 
714 		// Init Lua and register lua functions!
715 		InitLua();
716 		LuaRegisterModules();
717 
718 		// Initialise AI module
719 		InitAiModule();
720 
721 		// Setup sound card, must be done before loading sounds, so that
722 		// SDL_mixer can auto-convert to the target format
723 		if (!InitSound()) {
724 			InitMusic();
725 		}
726 
727 		LoadCcl(parameters.luaStartFilename, parameters.luaScriptArguments);
728 
729 		// Setup video display
730 		InitVideo();
731 
732 		PrintHeader();
733 		PrintLicense();
734 
735 #ifndef DEBUG           // For debug it's better not to have:
736 		srand(time(NULL));  // Random counter = random each start
737 #endif
738 
739 		//  Show title screens.
740 		SetDefaultTextColors(FontYellow, FontWhite);
741 		LoadFonts();
742 		SetClipping(0, 0, Video.Width - 1, Video.Height - 1);
743 		Video.ClearScreen();
744 		ShowTitleScreens();
745 
746 		// Init player data
747 		ThisPlayer = NULL;
748 		//Don't clear the Players structure as it would erase the allowed units.
749 		// memset(Players, 0, sizeof(Players));
750 		NumPlayers = 0;
751 
752 		UnitManager.Init(); // Units memory management
753 		PreMenuSetup();     // Load everything needed for menus
754 
755 		MenuLoop();
756 
757 		Exit(0);
758 	} catch (const std::exception &e) {
759 		fprintf(stderr, "Stratagus crashed!\n");
760 		fprintf(stderr, "Please send this call stack to our bug tracker: https://github.com/Wargus/stratagus/issues\n");
761 		fprintf(stderr, "and tell us what caused this bug to occur.\n");
762 		fprintf(stderr, " === exception state traceback === \n");
763 		fprintf(stderr, "%s", e.what());
764 		exit(1);
765 	}
766 	return 0;
767 }
768 
769 //@}
770