Example #1
0
int main(int argc, const char **argv)
#endif
{
	bContext *C = CTX_create();
	SYS_SystemHandle syshandle;

#ifndef WITH_PYTHON_MODULE
	bArgs *ba;
#endif

#ifdef WIN32
	wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
	int argci = 0;
	char **argv = MEM_mallocN(argc * sizeof(char *), "argv array");
	for (argci = 0; argci < argc; argci++) {
		argv[argci] = alloc_utf_8_from_16(argv_16[argci], 0);
	}
	LocalFree(argv_16);
#endif

#ifdef WITH_PYTHON_MODULE
#ifdef __APPLE__
	environ = *_NSGetEnviron();
#endif

#undef main
	evil_C = C;
#endif



#ifdef WITH_BINRELOC
	br_init(NULL);
#endif

#ifdef WITH_LIBMV
	libmv_initLogging(argv[0]);
#endif

	setCallbacks();
#if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
	/* patch to ignore argument finder gives us (pid?) */
	if (argc == 2 && strncmp(argv[1], "-psn_", 5) == 0) {
		extern int GHOST_HACK_getFirstFile(char buf[]);
		static char firstfilebuf[512];

		argc = 1;

		if (GHOST_HACK_getFirstFile(firstfilebuf)) {
			argc = 2;
			argv[1] = firstfilebuf;
		}
	}

#endif

#ifdef __FreeBSD__
	fpsetmask(0);
#endif

	/* initialize path to executable */
	BLI_init_program_path(argv[0]);

	BLI_threadapi_init();

	initglobals();  /* blender.c */

	IMB_init();
	BKE_images_init();

	BKE_brush_system_init();

	BLI_callback_global_init();

#ifdef WITH_GAMEENGINE
	syshandle = SYS_GetSystem();
#else
	syshandle = 0;
#endif

	/* first test for background */
#ifndef WITH_PYTHON_MODULE
	ba = BLI_argsInit(argc, (const char **)argv); /* skip binary path */
	setupArguments(C, ba, &syshandle);

	BLI_argsParse(ba, 1, NULL, NULL);

	if (use_crash_handler) {
		/* after parsing args */
		signal(SIGSEGV, blender_crash_handler);
	}
#else
	G.factory_startup = true;  /* using preferences or user startup makes no sense for py-as-module */
	(void)syshandle;
#endif

#ifdef WITH_FFMPEG
	IMB_ffmpeg_init();
#endif

	/* after level 1 args, this is so playanim skips RNA init */
	RNA_init();

	RE_engines_init();
	init_nodesystem();
	/* end second init */


#if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
	G.background = true; /* python module mode ALWAYS runs in background mode (for now) */
#else
	/* for all platforms, even windos has it! */
	if (G.background) {
		signal(SIGINT, blender_esc);  /* ctrl c out bg render */
	}
#endif

	/* background render uses this font too */
	BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size);

	/* Initialize ffmpeg if built in, also needed for bg mode if videos are
	 * rendered via ffmpeg */
	sound_init_once();
	
	init_def_material();

	if (G.background == 0) {
#ifndef WITH_PYTHON_MODULE
		BLI_argsParse(ba, 2, NULL, NULL);
		BLI_argsParse(ba, 3, NULL, NULL);
#endif
		WM_init(C, argc, (const char **)argv);

		/* this is properly initialized with user defs, but this is default */
		/* call after loading the startup.blend so we can read U.tempdir */
		BLI_init_temporary_dir(U.tempdir);

#ifdef WITH_SDL
		BLI_setenv("SDL_VIDEODRIVER", "dummy");
#endif
	}
	else {
#ifndef WITH_PYTHON_MODULE
		BLI_argsParse(ba, 3, NULL, NULL);
#endif

		WM_init(C, argc, (const char **)argv);

		/* don't use user preferences temp dir */
		BLI_init_temporary_dir(NULL);
	}
#ifdef WITH_PYTHON
	/**
	 * NOTE: the U.pythondir string is NULL until WM_init() is executed,
	 * so we provide the BPY_ function below to append the user defined
	 * python-dir to Python's sys.path at this point.  Simply putting
	 * WM_init() before #BPY_python_start() crashes Blender at startup.
	 */

	/* TODO - U.pythondir */
#else
	printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
#endif
	
	CTX_py_init_set(C, 1);
	WM_keymap_init(C);

#ifdef WITH_FREESTYLE
	/* initialize Freestyle */
	FRS_initialize();
	FRS_set_context(C);
#endif

	/* OK we are ready for it */
#ifndef WITH_PYTHON_MODULE
	BLI_argsParse(ba, 4, load_file, C);
	
	if (G.background == 0) {
		if (!G.file_loaded)
			if (U.uiflag2 & USER_KEEP_SESSION)
				WM_recover_last_session(C, NULL);
	}

#endif

#ifndef WITH_PYTHON_MODULE
	BLI_argsFree(ba);
#endif

#ifdef WIN32
	while (argci) {
		free(argv[--argci]);
	}
	MEM_freeN(argv);
	argv = NULL;
#endif

#ifdef WITH_PYTHON_MODULE
	return 0; /* keep blender in background mode running */
#endif

	if (G.background) {
		/* actually incorrect, but works for now (ton) */
		WM_exit(C);
	}
	else {
		if (G.fileflags & G_FILE_AUTOPLAY) {
			if (G.f & G_SCRIPT_AUTOEXEC) {
				if (WM_init_game(C)) {
					return 0;
				}
			}
			else {
				if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
					G.f |= G_SCRIPT_AUTOEXEC_FAIL;
					BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Game AutoStart");
				}
			}
		}

		if (!G.file_loaded) {
			WM_init_splash(C);
		}
	}

	WM_main(C);

	return 0;
} /* end of int main(argc, argv)	*/
Example #2
0
int main(int argc, char** argv)
{
	int i;
	int argc_py_clamped= argc; /* use this so python args can be added after ' - ' */
	bool error = false;
	SYS_SystemHandle syshandle = SYS_GetSystem();
	bool fullScreen = false;
	bool fullScreenParFound = false;
	bool windowParFound = false;
#ifdef WIN32
	bool closeConsole = true;
#endif
	RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
	bool stereoWindow = false;
	bool stereoParFound = false;
	int stereoFlag = STEREO_NOSTEREO;
	int domeFov = -1;
	int domeTilt = -200;
	int domeMode = 0;
	char* domeWarp = NULL;
	Text *domeText  = NULL;
	int windowLeft = 100;
	int windowTop = 100;
	int windowWidth = 640;
	int windowHeight = 480;
	GHOST_TUns32 fullScreenWidth = 0;
	GHOST_TUns32 fullScreenHeight= 0;
	int fullScreenBpp = 32;
	int fullScreenFrequency = 60;
	GHOST_TEmbedderWindowID parentWindow = 0;
	bool isBlenderPlayer = false; //true when lauching from blender or command line. false for bundled player
	int validArguments=0;
	bool samplesParFound = false;
	GHOST_TUns16 aasamples = 0;
	
#ifdef __linux__
#ifdef __alpha__
	signal (SIGFPE, SIG_IGN);
#endif /* __alpha__ */
#endif /* __linux__ */

#ifdef WITH_SDL_DYNLOAD
	sdlewInit();
#endif

	BKE_appdir_program_path_init(argv[0]);
	BKE_tempdir_init(NULL);
	
	// We don't use threads directly in the BGE, but we need to call this so things like
	// freeing up GPU_Textures works correctly.
	BLI_threadapi_init();

	RNA_init();

	init_nodesystem();
	
	initglobals();

	// We load our own G.main, so free the one that initglobals() gives us
	BKE_main_free(G.main);
	G.main = NULL;

	MEM_CacheLimiter_set_disabled(true);
	IMB_init();
	BKE_images_init();
	BKE_modifier_init();
	DAG_init();

#ifdef WITH_FFMPEG
	IMB_ffmpeg_init();
#endif

	// Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c)
	BLF_init(11, U.dpi);
	BLT_lang_init();
	BLT_lang_set("");

	BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
	if (blf_mono_font == -1)
		blf_mono_font = BLF_load_mem_unique("monospace", (unsigned char*)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);

	// Parse command line options
#if defined(DEBUG)
	printf("argv[0] = '%s'\n", argv[0]);
#endif

#ifdef WIN32
	if (scr_saver_init(argc, argv))
	{
		switch (scr_saver_mode)
		{
		case SCREEN_SAVER_MODE_CONFIGURATION:
			MessageBox(scr_saver_hwnd, "This screen saver has no options that you can set", "Screen Saver", MB_OK);
			break;
		case SCREEN_SAVER_MODE_PASSWORD:
			/* This is W95 only, which we currently do not support.
			 * Fall-back to normal screen saver behavior in that case... */
		case SCREEN_SAVER_MODE_SAVER:
			fullScreen = true;
			fullScreenParFound = true;
			break;

		case SCREEN_SAVER_MODE_PREVIEW:
			/* This will actually be handled somewhere below... */
			break;
		}
	}
#endif
	// XXX add the ability to change this values to the command line parsing.
	U.mixbufsize = 2048;
	U.audiodevice = 2;
	U.audiorate = 44100;
	U.audioformat = 0x24;
	U.audiochannels = 2;

	// XXX this one too
	U.anisotropic_filter = 2;
	// enable fast mipmap generation
	U.use_gpu_mipmap = 1;

	BKE_sound_init_once();

	// Initialize a default material for meshes without materials.
	init_def_material();

	BKE_library_callback_free_window_manager_set(wm_free);

	/* if running blenderplayer the last argument can't be parsed since it has to be the filename. else it is bundled */
	isBlenderPlayer = !BLO_is_a_runtime(argv[0]);
	if (isBlenderPlayer)
		validArguments = argc - 1;
	else
		validArguments = argc;


	/* Parsing command line arguments (can be set from WM_OT_blenderplayer_start) */
#if defined(DEBUG)
		printf("Parsing command line arguments...\n");
		printf("Num of arguments is: %i\n", validArguments-1); //-1 because i starts at 1
#endif

	for (i = 1; (i < validArguments) && !error 
#ifdef WIN32
		&& scr_saver_mode == SCREEN_SAVER_MODE_NONE
#endif
		;)

	{
#if defined(DEBUG)
		printf("argv[%d] = '%s'\n", i, argv[i]);
#endif
		if (argv[i][0] == '-')
		{
			/* ignore all args after " - ", allow python to have own args */
			if (argv[i][1]=='\0') {
				argc_py_clamped= i;
				break;
			}
			
			switch (argv[i][1])
			{
			case 'g': //game engine options (show_framerate, fixedtime, etc)
			{
				i++;
				if (i <= validArguments)
				{
					char* paramname = argv[i];
					// Check for single value versus assignment
					if (i+1 <= validArguments && (*(argv[i+1]) == '='))
					{
						i++;
						if (i + 1 <= validArguments)
						{
							i++;
							// Assignment
							SYS_WriteCommandLineInt(syshandle, paramname, atoi(argv[i]));
							SYS_WriteCommandLineFloat(syshandle, paramname, atof(argv[i]));
							SYS_WriteCommandLineString(syshandle, paramname, argv[i]);
#if defined(DEBUG)
							printf("%s = '%s'\n", paramname, argv[i]);
#endif
							i++;
						}
						else
						{
							error = true;
							printf("error: argument assignment %s without value.\n", paramname);
						}
					}
					else
					{
//						SYS_WriteCommandLineInt(syshandle, argv[i++], 1);
					}
				}
				break;
			}
			case 'd': //debug on
			{
				i++;
				G.debug |= G_DEBUG;
				MEM_set_memory_debug();
#ifndef NDEBUG
				BLI_mempool_set_memory_debug();
#endif
				break;
			}
			case 'f': //fullscreen mode
			{
				i++;
				fullScreen = true;
				fullScreenParFound = true;
				if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
				{
					fullScreenWidth = atoi(argv[i++]);
					fullScreenHeight = atoi(argv[i++]);
					if ((i + 1) <= validArguments && argv[i][0] != '-')
					{
						fullScreenBpp = atoi(argv[i++]);
						if ((i + 1) <= validArguments && argv[i][0] != '-')
							fullScreenFrequency = atoi(argv[i++]);
					}
				}
				else if ((i + 1) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
				{
					error = true;
					printf("error: to define fullscreen width or height, both options must be used.\n");
				}
				break;
			}
			case 'w': //display in a window
			{
				i++;
				fullScreen = false;
				windowParFound = true;

				// Parse window position and size options
				if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
				{
					windowWidth = atoi(argv[i++]);
					windowHeight = atoi(argv[i++]);

					if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
					{
						windowLeft = atoi(argv[i++]);
						windowTop = atoi(argv[i++]);
					}
					else if ((i + 1) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
					{
						error = true;
						printf("error: to define the window left or right coordinates, both options must be used.\n");
					}
				}
				else if ((i + 1) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
				{
					error = true;
					printf("error: to define the window's width or height, both options must be used.\n");
				}
				break;
			}
			case 'h': //display help
			{
				usage(argv[0], isBlenderPlayer);
				return 0;
				break;
			}
			case 'i': //parent window ID
			{
				i++;
				if ( (i + 1) <= validArguments )
					parentWindow = atoi(argv[i++]);
				else {
					error = true;
					printf("error: too few options for parent window argument.\n");
				}
#if defined(DEBUG)
				printf("XWindows ID = %d\n", parentWindow);
#endif // defined(DEBUG)
				break;
			}
			case 'm': //maximum anti-aliasing (eg. 2,4,8,16)
			{
				i++;
				samplesParFound = true;
				if ((i+1) <= validArguments )
					aasamples = atoi(argv[i++]);
				else
				{
					error = true;
					printf("error: No argument supplied for -m");
				}
				break;
			}
			case 'c': //keep console (windows only)
			{
				i++;
#ifdef WIN32
				closeConsole = false;
#endif
				break;
			}
			case 's': //stereo mode
			{
				i++;
				if ((i + 1) <= validArguments)
				{
					stereoParFound = true;
					stereoFlag = STEREO_ENABLED;

					if (!strcmp(argv[i], "nostereo"))  // may not be redundant if the file has different setting
					{
						stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
						stereoFlag = STEREO_NOSTEREO;
					}

					// only the hardware pageflip method needs a stereo window
					else if (!strcmp(argv[i], "hwpageflip")) {
						stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
						stereoWindow = true;
					}
					else if (!strcmp(argv[i], "syncdoubling"))
						stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;

					else if (!strcmp(argv[i], "3dtvtopbottom"))
						stereomode = RAS_IRasterizer::RAS_STEREO_3DTVTOPBOTTOM;

					else if (!strcmp(argv[i], "anaglyph"))
						stereomode = RAS_IRasterizer::RAS_STEREO_ANAGLYPH;

					else if (!strcmp(argv[i], "sidebyside"))
						stereomode = RAS_IRasterizer::RAS_STEREO_SIDEBYSIDE;

					else if (!strcmp(argv[i], "interlace"))
						stereomode = RAS_IRasterizer::RAS_STEREO_INTERLACED;

					else if (!strcmp(argv[i], "vinterlace"))
						stereomode = RAS_IRasterizer::RAS_STEREO_VINTERLACE;

#if 0
//					// future stuff
//					else if (!strcmp(argv[i], "stencil")
//						stereomode = RAS_STEREO_STENCIL;
#endif
					else
					{
						error = true;
						printf("error: stereomode '%s' unrecognized.\n", argv[i]);
					}

					i++;
				}
				else
				{
					error = true;
					printf("error: too few options for stereo argument.\n");
				}
				break;
			}
			case 'D': //dome mode
			{
				stereoFlag = STEREO_DOME;
				stereomode = RAS_IRasterizer::RAS_STEREO_DOME;
				i++;
				if ((i + 1) <= validArguments)
				{
					if (!strcmp(argv[i], "angle")) {
						i++;
						domeFov = atoi(argv[i++]);
					}
					if (!strcmp(argv[i], "tilt")) {
						i++;
						domeTilt = atoi(argv[i++]);
					}
					if (!strcmp(argv[i], "warpdata")) {
						i++;
						domeWarp = argv[i++];
					}
					if (!strcmp(argv[i], "mode")) {
						i++;
						if (!strcmp(argv[i], "fisheye"))
							domeMode = DOME_FISHEYE;
							
						else if (!strcmp(argv[i], "truncatedfront"))
							domeMode = DOME_TRUNCATED_FRONT;
							
						else if (!strcmp(argv[i], "truncatedrear"))
							domeMode = DOME_TRUNCATED_REAR;
							
						else if (!strcmp(argv[i], "cubemap"))
							domeMode = DOME_ENVMAP;
							
						else if (!strcmp(argv[i], "sphericalpanoramic"))
							domeMode = DOME_PANORAM_SPH;

						else
							printf("error: %s is not a valid dome mode.\n", argv[i]);
					}
					i++;
				}
				break;
			}
			default:  //not recognized
			{
				printf("Unknown argument: %s\n", argv[i++]);
				break;
			}
			}
		}
		else
		{
			i++;
		}
	}

	if ((windowWidth < kMinWindowWidth) || (windowHeight < kMinWindowHeight))
	{
		error = true;
		printf("error: window size too small.\n");
	}
	
	if (error )
	{
		usage(argv[0], isBlenderPlayer);
		return 0;
	}

#ifdef WIN32
	if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION)
#endif
	{
		// Create the system
		if (GHOST_ISystem::createSystem() == GHOST_kSuccess) {
			GHOST_ISystem* system = GHOST_ISystem::getSystem();
			assertd(system);
			
			if (!fullScreenWidth || !fullScreenHeight)
				system->getMainDisplayDimensions(fullScreenWidth, fullScreenHeight);
			// process first batch of events. If the user
			// drops a file on top off the blenderplayer icon, we
			// receive an event with the filename
			
			system->processEvents(0);
			
			// this bracket is needed for app (see below) to get out
			// of scope before GHOST_ISystem::disposeSystem() is called.
			{
				int exitcode = KX_EXIT_REQUEST_NO_REQUEST;
				STR_String exitstring = "";
				GPG_Application app(system);
				bool firstTimeRunning = true;
				char filename[FILE_MAX];
				char pathname[FILE_MAX];
				char *titlename;

				get_filename(argc_py_clamped, argv, filename);
				if (filename[0])
					BLI_path_cwd(filename, sizeof(filename));
				

				// fill the GlobalSettings with the first scene files
				// those may change during the game and persist after using Game Actuator
				GlobalSettings gs;

				do {
					// Read the Blender file
					BlendFileData *bfd;
					
					// if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
					if (exitcode == KX_EXIT_REQUEST_START_OTHER_GAME)
					{
						char basedpath[FILE_MAX];
						
						// base the actuator filename relative to the last file
						BLI_strncpy(basedpath, exitstring.Ptr(), sizeof(basedpath));
						BLI_path_abs(basedpath, pathname);
						
						bfd = load_game_data(basedpath);

						if (!bfd) {
							// just add "//" in front of it
							char temppath[FILE_MAX] = "//";
							BLI_strncpy(temppath + 2, basedpath, FILE_MAX - 2);

							BLI_path_abs(temppath, pathname);
							bfd = load_game_data(temppath);
						}
					}
					else {
						bfd = load_game_data(BKE_appdir_program_path(), filename[0]? filename: NULL);
					}

#if defined(DEBUG)
					printf("Game data loaded from %s\n", filename);
#endif
					
					if (!bfd) {
						usage(argv[0], isBlenderPlayer);
						error = true;
						exitcode = KX_EXIT_REQUEST_QUIT_GAME;
					}
					else {
						/* Setting options according to the blend file if not overriden in the command line */
#ifdef WIN32
#if !defined(DEBUG)
						if (closeConsole) {
							system->toggleConsole(0); // Close a console window
						}
#endif // !defined(DEBUG)
#endif // WIN32
						Main *maggie = bfd->main;
						Scene *scene = bfd->curscene;
						G.main = maggie;

						if (firstTimeRunning) {
							G.fileflags  = bfd->fileflags;

							gs.matmode= scene->gm.matmode;
							gs.glslflag= scene->gm.flag;
						}

						//Seg Fault; icon.c gIcons == 0
						BKE_icons_init(1);
						
						titlename = maggie->name;
						
						// Check whether the game should be displayed full-screen
						if ((!fullScreenParFound) && (!windowParFound)) {
							// Only use file settings when command line did not override
							if ((scene->gm.playerflag & GAME_PLAYER_FULLSCREEN)) {
								//printf("fullscreen option found in Blender file\n");
								fullScreen = true;
								fullScreenWidth= scene->gm.xplay;
								fullScreenHeight= scene->gm.yplay;
								fullScreenFrequency= scene->gm.freqplay;
								fullScreenBpp = scene->gm.depth;
							}
							else
							{
								fullScreen = false;
								windowWidth = scene->gm.xplay;
								windowHeight = scene->gm.yplay;
							}
						}
						
						
						// Check whether the game should be displayed in stereo (dome included)
						if (!stereoParFound) {
							// Only use file settings when command line did not override
							if (scene->gm.stereoflag == STEREO_ENABLED) {
								stereomode = (RAS_IRasterizer::StereoMode) scene->gm.stereomode;
								if (stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
									stereoWindow = true;
							}
						}
						else {
							scene->gm.stereoflag = STEREO_ENABLED;
						}

						if (!samplesParFound)
							aasamples = scene->gm.aasamples;

						// Dome specific settings
						if (stereoFlag == STEREO_DOME) {
							stereomode = RAS_IRasterizer::RAS_STEREO_DOME;
							scene->gm.stereoflag = STEREO_DOME;
							if (domeFov > 89)
								scene->gm.dome.angle = domeFov;
							if (domeTilt > -180)
								scene->gm.dome.tilt = domeTilt;
							if (domeMode > 0)
								scene->gm.dome.mode = domeMode;
							if (domeWarp) {
								//XXX to do: convert relative to absolute path
								domeText= BKE_text_load(G.main, domeWarp, "");
								if (!domeText)
									printf("error: invalid warpdata text file - %s\n", domeWarp);
								else
									scene->gm.dome.warptext = domeText;
							}
						}
						
						//					GPG_Application app (system, maggie, startscenename);
						app.SetGameEngineData(maggie, scene, &gs, argc, argv); /* this argc cant be argc_py_clamped, since python uses it */
						BLI_strncpy(pathname, maggie->name, sizeof(pathname));
						if (G.main != maggie) {
							BLI_strncpy(G.main->name, maggie->name, sizeof(G.main->name));
						}
#ifdef WITH_PYTHON
						setGamePythonPath(G.main->name);
#endif
						if (firstTimeRunning) {
							firstTimeRunning = false;

							if (fullScreen) {
#ifdef WIN32
								if (scr_saver_mode == SCREEN_SAVER_MODE_SAVER)
								{
									app.startScreenSaverFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
									                               stereoWindow, stereomode, aasamples);
								}
								else
#endif
								{
									app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
									                    stereoWindow, stereomode, aasamples, (scene->gm.playerflag & GAME_PLAYER_DESKTOP_RESOLUTION));
								}
							}
							else
							{
#ifdef __APPLE__
								// on Mac's we'll show the executable name instead of the 'game.blend' name
								char tempname[1024], *appstring;
								::strcpy(tempname, titlename);
								
								appstring = strstr(tempname, ".app/");
								if (appstring) {
									appstring[2] = 0;
									titlename = &tempname[0];
								}
#endif
								// Strip the path so that we have the name of the game file
								STR_String path = titlename;
#ifndef WIN32
								vector<STR_String> parts = path.Explode('/');
#else  // WIN32
								vector<STR_String> parts = path.Explode('\\');
#endif // WIN32                        
								STR_String title;
								if (parts.size()) {
									title = parts[parts.size()-1];
									parts = title.Explode('.');
									if (parts.size() > 1)
									{
										title = parts[0];
									}
								}
								else {
									title = "blenderplayer";
								}
#ifdef WIN32
								if (scr_saver_mode == SCREEN_SAVER_MODE_PREVIEW)
								{
									app.startScreenSaverPreview(scr_saver_hwnd, stereoWindow, stereomode, aasamples);
								}
								else
#endif
								{
									if (parentWindow != 0)
										app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode, aasamples);
									else
										app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
										                stereoWindow, stereomode, aasamples);

									if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) {
										GPU_set_mipmap(0);
									}

									GPU_set_anisotropic(U.anisotropic_filter);
									GPU_set_gpu_mipmapping(U.use_gpu_mipmap);
								}
							}
						}
						else {
							app.StartGameEngine(stereomode);
							exitcode = KX_EXIT_REQUEST_NO_REQUEST;
						}
						
						// Add the application as event consumer
						system->addEventConsumer(&app);
						
						// Enter main loop
						bool run = true;
						char *python_main = NULL;
						pynextframestate.state = NULL;
						pynextframestate.func = NULL;
#ifdef WITH_PYTHON
						python_main = KX_GetPythonMain(scene);
#endif // WITH_PYTHON
						if (python_main) {
							char *python_code = KX_GetPythonCode(maggie, python_main);
							if (python_code) {
#ifdef WITH_PYTHON
								// Set python environement variable.
								KX_Scene *startscene = app.GetStartScene();
								KX_SetActiveScene(startscene);
								PHY_SetActiveEnvironment(startscene->GetPhysicsEnvironment());

								gpg_nextframestate.system = system;
								gpg_nextframestate.app = &app;
								gpg_nextframestate.gs = &gs;
								pynextframestate.state = &gpg_nextframestate;
								pynextframestate.func = &GPG_PyNextFrame;

								printf("Yielding control to Python script '%s'...\n", python_main);
								PyRun_SimpleString(python_code);
								printf("Exit Python script '%s'\n", python_main);
#endif // WITH_PYTHON
								MEM_freeN(python_code);
							}
							else {
								fprintf(stderr, "ERROR: cannot yield control to Python: no Python text data block named '%s'\n", python_main);
							}
						}
						else {
							while (run) {
								run = GPG_NextFrame(system, &app, exitcode, exitstring, &gs);
							}
						}
						app.StopGameEngine();

						/* 'app' is freed automatic when out of scope.
						 * removal is needed else the system will free an already freed value */
						system->removeEventConsumer(&app);

						BLO_blendfiledata_free(bfd);
						/* G.main == bfd->main, it gets referenced in free_nodesystem so we can't have a dangling pointer */
						G.main = NULL;
						if (python_main) MEM_freeN(python_main);
					}
				} while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME);
			}

			// Seg Fault; icon.c gIcons == 0
			BKE_icons_free();

			// Dispose the system
			GHOST_ISystem::disposeSystem();
		}
		else {
			error = true;
			printf("error: couldn't create a system.\n");
		}
	}

	/* refer to WM_exit_ext() and free_blender(),
	 * these are not called in the player but we need to match some of there behavior here,
	 * if the order of function calls or blenders state isn't matching that of blender proper,
	 * we may get troubles later on */

	free_nodesystem();

	// Cleanup
	RNA_exit();
	BLF_exit();

#ifdef WITH_INTERNATIONAL
	BLF_free_unifont();
	BLF_free_unifont_mono();
	BLT_lang_free();
#endif

	IMB_exit();
	BKE_images_exit();
	DAG_exit();
	IMB_moviecache_destruct();

	SYS_DeleteSystem(syshandle);

	int totblock= MEM_get_memory_blocks_in_use();
	if (totblock!=0) {
		printf("Error Totblock: %d\n",totblock);
		MEM_set_error_callback(mem_error_cb);
		MEM_printmemlist();
	}

	BKE_tempdir_session_purge();

	return error ? -1 : 0;
}