Skip to content
Snippets Groups Projects
main.c 46.4 KiB
Newer Older
dg's avatar
dg committed
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	/* Set our perspective */
	//gluPerspective( 45.0f, ratio, 0.1f, 100.0f );
	glOrtho(0, width / screen_zoom, height / screen_zoom, 0, -1001, 1001);
dg's avatar
dg committed

	/* Make sure we're chaning the model view and not the projection */
	glMatrixMode( GL_MODELVIEW );

	/* Reset The View */
	glLoadIdentity( );

dg's avatar
dg committed
//TSDL2	SDL_SetGamma(gamma_correction, gamma_correction, gamma_correction);
dg's avatar
dg committed

dg's avatar
dg committed
	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
	printf("OpenGL max texture size: %d\n", max_texture_size);
dg's avatar
dg committed


dg's avatar
dg committed
	return( TRUE );
}

/* @see main.h#resizeNeedsNewWindow */
extern bool resizeNeedsNewWindow(int w, int h, bool fullscreen, bool borderless)
{
	/* Note: w and h currently not a factor */
	bool newWindowNeeded = window && ( (is_borderless && !borderless)
										|| (!is_borderless && borderless) );
	return (newWindowNeeded);
}

/* @see main.h#do_move */
void do_move(int w, int h) {
	/* Save the origin in case a window needs to be remade later. */
	if (!ignore_window_change_pos) {
		start_xpos = w;
		start_ypos = h;
	} else {
DarkGod's avatar
DarkGod committed
		// w = start_xpos;
		h = start_ypos;
	}

	/* Can't move a fullscreen SDL window in one go.*/
	if (is_fullscreen) {
		/* Drop out of fullscreen so we can move the window. */
		SDL_SetWindowFullscreen(window, SDL_FALSE);

	}

	/* Move the window */
	SDL_SetWindowPosition(window, w, h);

	/* Jump back into fullscreen if necessary */
	if (is_fullscreen) {
		if (!SDL_SetWindowFullscreen(window, SDL_TRUE)) {
			/* Fullscreen change successful */
			is_fullscreen = SDL_TRUE;

		} else {
			/* Error switching fullscreen mode */
			printf("[DO MOVE] Unable to return window"
					" to fullscreen mode:  %s\n", SDL_GetError());
			SDL_ClearError();
		}

	}

}

/* @see main.h#do_resize */
void do_resize(int w, int h, bool fullscreen, bool borderless, float zoom)
dg's avatar
dg committed
{
	/* Temporary width, height (since SDL might reject our resize) */
	int aw, ah;
	int mustPushEvent = 0;
	SDL_Event fsEvent;

	screen_zoom = zoom;

	printf("[DO RESIZE] Requested: %dx%d (%d, %d); zoom %d%%\n", w, h, fullscreen, borderless, (int)(zoom * 100));
	/* See if we need to reinitialize the window */
	if (resizeNeedsNewWindow(w, h, fullscreen, borderless)) {
		/* Destroy the current window */
		SDL_GL_DeleteContext(maincontext);
		SDL_DestroyWindow(window);
		maincontext = 0;
		window = 0;
		screen = 0;
		/* Clean up the old window icon */
		SDL_FreeSurface(windowIconSurface);
		windowIconSurface = 0;
		/* Signal a new icon needs to be created. */
		mustCreateIconSurface = 1;
	}

	/* If there is no current window, we have to make one and initialize */
	if (!window) {
		window = SDL_CreateWindow("TE4",
				(start_xpos == -1) ? SDL_WINDOWPOS_CENTERED : start_xpos,
				(start_ypos == -1) ? SDL_WINDOWPOS_CENTERED : start_ypos, w, h,
				SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL
				| (!borderless ? SDL_WINDOW_RESIZABLE : 0)
				| (fullscreen ? SDL_WINDOW_FULLSCREEN : 0)
				| (borderless ? SDL_WINDOW_BORDERLESS : 0)
		);
		if (window==NULL) {
			printf("error opening screen: %s\n", SDL_GetError());
			exit(1);
		}
		is_fullscreen = fullscreen;
		is_borderless = borderless;
		screen = SDL_GetWindowSurface(window);
		maincontext = SDL_GL_CreateContext(window);
dg's avatar
dg committed
		SDL_GL_MakeCurrent(window, maincontext);
dg's avatar
dg committed
		glewInit();
		/* Set the window icon. */
		windowIconSurface = IMG_Load_RW(PHYSFSRWOPS_openRead(WINDOW_ICON_PATH)
				, TRUE);
		SDL_SetWindowIcon(window, windowIconSurface);

DarkGod's avatar
DarkGod committed
		if (!desktop_gamma_set) {
			desktop_gamma = SDL_GetWindowBrightness(window);
			desktop_gamma_set = TRUE;
			printf("[GAMMA] Getting desktop gamma of %f\n", desktop_gamma);
		}
	} else {
		/* SDL won't allow a fullscreen resolution change in one go.  Check. */
		if (is_fullscreen) {
			/* Drop out of fullscreen so we can change resolution. */
			SDL_SetWindowFullscreen(window, SDL_FALSE);
			is_fullscreen = 0;
			mustPushEvent = 1; /* Actually just a maybe for now, confirmed later */

		}

		/* Update window size */

		/* Jump [back] into fullscreen if requested */
		if (fullscreen) {
			if (!SDL_SetWindowFullscreen(window, SDL_TRUE)) {
				/* Fullscreen change successful */
				is_fullscreen = SDL_TRUE;

			} else {
				/* Error switching fullscreen mode */
				printf("[DO RESIZE] Unable to switch window"
						" to fullscreen mode:  %s\n", SDL_GetError());
				SDL_ClearError();
			}

		} else if (mustPushEvent) {
			/* Handle fullscreen -> nonfullscreen transition */
			/*
			 * Our changes will get clobbered by an automatic event from
			 * setWindowFullscreen.  Push an event to the event loop to make
			 * sure these changes are applied after whatever that other
			 * event throws.
			 */
			/* Create an event to push */
			fsEvent.type = SDL_WINDOWEVENT;
			fsEvent.window.timestamp = SDL_GetTicks();
			fsEvent.window.windowID = SDL_GetWindowID(window);
			// windowId
			fsEvent.window.event = SDL_WINDOWEVENT_RESIZED;
			fsEvent.window.data1 = w;
			fsEvent.window.data2 = h;

			/* Push the event, but don't bother waiting */
			SDL_PushEvent(&fsEvent);
			printf("[DO RESIZE]: pushed fullscreen compensation event\n");

		}

		/* Finally, update the screen info */
	/* Check and see if SDL honored our resize request */
	SDL_GetWindowSize(window, &aw, &ah);
	printf("[DO RESIZE] Got: %dx%d (%d, %d)\n", aw, ah, is_fullscreen, borderless);
dg's avatar
dg committed
	SDL_GL_MakeCurrent(window, maincontext);
	resizeWindow(aw, ah);

void boot_lua(int state, bool rebooting, int argc, char *argv[])
{
dg's avatar
dg committed
	core_def->corenum = 0;

	if (state == 1)
	{
		const char *selfexe;

		/* When rebooting we destroy the lua state to free memory and we reset physfs */
		if (rebooting)
		{
			current_mousehandler = LUA_NOREF;
			current_keyhandler = LUA_NOREF;
			current_game = LUA_NOREF;
			lua_close(L);
			PHYSFS_deinit();
		}

		/***************** Physfs Init *****************/
		PHYSFS_init(argv[0]);

DarkGod's avatar
DarkGod committed
		bool bootstrap_mounted = FALSE;
		selfexe = get_self_executable(argc, argv);
dg's avatar
dg committed
		if (selfexe && PHYSFS_mount(selfexe, "/", 1))
		{
		}
		else
		{
			printf("NO SELFEXE: bootstrapping from CWD\n");
			PHYSFS_mount("bootstrap", "/bootstrap", 1);
DarkGod's avatar
DarkGod committed
			bootstrap_mounted = TRUE;
		}

		/***************** Lua Init *****************/
		L = lua_open();  /* create state */
		luaL_openlibs(L);  /* open libraries */
dg's avatar
dg committed
		luaopen_physfs(L);
		luaopen_core(L);
		luaopen_socket_core(L);
		luaopen_mime_core(L);
		luaopen_struct(L);
		luaopen_profiler(L);
dg's avatar
dg committed
		luaopen_bit(L);
		luaopen_lpeg(L);
dg's avatar
dg committed
		luaopen_lxp(L);
		luaopen_map(L);
		luaopen_particles(L);
		luaopen_sound(L);
dg's avatar
dg committed
		luaopen_noise(L);
dg's avatar
dg committed
		luaopen_diamond_square(L);
dg's avatar
dg committed
		luaopen_shaders(L);
		luaopen_serial(L);
dg's avatar
dg committed
		luaopen_zlib(L);
dg's avatar
dg committed
		luaopen_bit(L);
		luaopen_wfc(L);
DarkGod's avatar
DarkGod committed
		if (!no_steam) te4_steam_lua_init(L);
DarkGod's avatar
DarkGod committed
#endif
#ifdef DISCORD_TE4
		extern int luaopen_discord(lua_State *L);
		luaopen_discord(L);
dg's avatar
dg committed
		printf("===top %d\n", lua_gettop(L));
//		exit(0);
dg's avatar
dg committed
		// Override "print" if requested
		if (no_debug)
		{
			lua_pushcfunction(L, noprint);
			lua_setglobal(L, "print");
		}

		// Make the uids repository
		lua_newtable(L);
		lua_setglobal(L, "__uids");

		// Tell the boostrapping code the selfexe path
		if (selfexe)
			lua_pushstring(L, selfexe);
		else
			lua_pushnil(L);
		lua_setglobal(L, "__SELFEXE");

		// Will be useful
#ifdef __APPLE__
		lua_pushboolean(L, TRUE);
		lua_setglobal(L, "__APPLE__");
#endif

		// Run bootstrapping
		if (!luaL_loadfile(L, "/bootstrap/boot.lua"))
		{
			docall(L, 0, 0);
		}
		// Could not load bootstrap! Try to mount the engine from working directory as last resort
		else
		{
			printf("WARNING: No bootstrap code found, defaulting to working directory for engine code!\n");
			PHYSFS_mount("game/thirdparty", "/", 1);
			PHYSFS_mount("game/", "/", 1);
DarkGod's avatar
DarkGod committed
			luaL_loadstring(L,
				"fs.setPathAllowed(fs.getRealPath('/addons/', true)) " \
				"if fs.getRealPath('/dlcs/') then fs.setPathAllowed(fs.getRealPath('/dlcs/', true)) end " \
				"fs.setPathAllowed(fs.getRealPath('/modules/', true)) "
			);
			lua_pcall(L, 0, 0, 0);
		}

		if (bootstrap_mounted) {
			PHYSFS_removeFromSearchPath("bootstrap");
		if (te4_web_init) te4_web_init(L);

		// And run the lua engine pre init scripts
		if (!luaL_loadfile(L, "/loader/pre-init.lua"))
			docall(L, 0, 0);
		else
			lua_pop(L, 1);

		create_particles_thread();
dg's avatar
dg committed
		SDL_SetWindowTitle(window, "T-Engine4");

		// Now we can open lua lanes, the physfs paths are set and it can load it's lanes-keeper.lua file
dg's avatar
dg committed
		//		luaopen_lanes(L);

		printf("Running lua loader code...\n");

		// And run the lua engine scripts
		if (!luaL_loadfile(L, "/loader/init.lua"))
		{
dg's avatar
dg committed
			if (core_def->reboot_engine) lua_pushstring(L, core_def->reboot_engine); else lua_pushnil(L);
			if (core_def->reboot_engine_version) lua_pushstring(L, core_def->reboot_engine_version); else lua_pushnil(L);
			if (core_def->reboot_module) lua_pushstring(L, core_def->reboot_module); else lua_pushnil(L);
			if (core_def->reboot_name) lua_pushstring(L, core_def->reboot_name); else lua_pushnil(L);
			lua_pushboolean(L, core_def->reboot_new);
			if (core_def->reboot_einfo) lua_pushstring(L, core_def->reboot_einfo); else lua_pushnil(L);
			docall(L, 6, 0);
dg's avatar
dg committed
// Update core to run
static void define_core(core_boot_type *core_def, const char *coretype, int id, const char *reboot_engine, const char *reboot_engine_version, const char *reboot_module, const char *reboot_name, int reboot_new, const char *reboot_einfo)
{
	if (core_def->coretype) free(core_def->coretype);
	if (core_def->reboot_engine) free(core_def->reboot_engine);
	if (core_def->reboot_engine_version) free(core_def->reboot_engine_version);
	if (core_def->reboot_module) free(core_def->reboot_module);
	if (core_def->reboot_name) free(core_def->reboot_name);
	if (core_def->reboot_einfo) free(core_def->reboot_einfo);

	core_def->corenum = id;
	core_def->coretype = coretype ? strdup(coretype) : NULL;
	core_def->reboot_engine = reboot_engine ? strdup(reboot_engine) : NULL;
	core_def->reboot_engine_version = reboot_engine_version ? strdup(reboot_engine_version) : NULL;
	core_def->reboot_module = reboot_module ? strdup(reboot_module) : NULL;
	core_def->reboot_name = reboot_name ? strdup(reboot_name) : NULL;
	core_def->reboot_einfo = reboot_einfo ? strdup(reboot_einfo) : NULL;
	core_def->reboot_new = reboot_new;
}

dg's avatar
dg committed
// Let some platforms use a different entry point
#ifdef USE_TENGINE_MAIN
#ifdef main
#undef main
#endif
#define main tengine_main
#endif

/* Cleans up a timer lock.  See function declaration for more info. */
void cleanupTimerLock(SDL_mutex *lock, SDL_TimerID *timer
	, int *timerFlag)
{
	// Grab the lock and start cleaning up
	SDL_mutexP(lock);
		// Cancel the timer (if it is running)
		if (*timer) SDL_RemoveTimer(*timer);
		*timer = 0;
		*timerFlag = -1;

	SDL_mutexV(lock);

	/*
	 * Need to get lock once more just in case a timer call was stuck waiting on
	 * the lock when we altered the variables.
	 */
	SDL_mutexP(lock);
	SDL_mutexV(lock);

	// Can now safely destroy the lock.
	SDL_DestroyMutex(lock);
}

/* Handles game idle transition.  See function declaration for more info. */
void handleIdleTransition(int goIdle)
{
DarkGod's avatar
DarkGod committed
	if (forbid_idle_mode) return;

	/* Only allow if a display timer is already running. */
	if (display_timer_id) {
		if (goIdle) {
			/* Make sure this isn't an idle->idle transition */
			if (requested_fps != requested_fps_idle) {
				requested_fps_idle_saved = requested_fps;
				setupDisplayTimer(requested_fps_idle);
			}

		} else if (requested_fps_idle_saved && (requested_fps != requested_fps_idle_saved)) {
			/* Made sure this wasn't a nonidle->nonidle */
			setupDisplayTimer(requested_fps_idle_saved);
		}

		if (current_game != LUA_NOREF)
		{
			lua_rawgeti(L, LUA_REGISTRYINDEX, current_game);
			lua_pushstring(L, "idling");
			lua_gettable(L, -2);
			lua_remove(L, -2);
			lua_rawgeti(L, LUA_REGISTRYINDEX, current_game);
			lua_pushboolean(L, !goIdle);
			docall(L, 2, 0);
		}
dg's avatar
dg committed

dg's avatar
dg committed
/**
dg's avatar
dg committed
 */
int main(int argc, char *argv[])
dg's avatar
dg committed
{
dg's avatar
dg committed
	core_def = calloc(1, sizeof(core_boot_type));
dg's avatar
dg committed
	core_def->define = &define_core;
	core_def->define(core_def, "te4core", -1, NULL, NULL, NULL, NULL, 0, NULL);

DarkGod's avatar
DarkGod committed
	g_argc = argc;
	g_argv = argv;

	bool logtofile = FALSE;
DarkGod's avatar
DarkGod committed
	bool is_zygote = FALSE;
TomeDev's avatar
TomeDev committed
	bool os_autoflush = FALSE;
DarkGod's avatar
DarkGod committed
	bool no_web = FALSE;
TomeDev's avatar
TomeDev committed
	FILE *logfile = NULL;
dg's avatar
dg committed

	// Parse arguments
	int i;
	for (i = 1; i < argc; i++)
	{
		char *arg = argv[i];
dg's avatar
dg committed
		if (!strncmp(arg, "-M", 2)) core_def->reboot_module = strdup(arg+2);
		if (!strncmp(arg, "-u", 2)) core_def->reboot_name = strdup(arg+2);
		if (!strncmp(arg, "-E", 2)) core_def->reboot_einfo = strdup(arg+2);
		if (!strncmp(arg, "-n", 2)) core_def->reboot_new = 1;
		if (!strncmp(arg, "--flush-stdout", 14))
		{
			setvbuf(stdout, (char *) NULL, _IOLBF, 0);
#ifdef SELFEXE_WINDOWS
TomeDev's avatar
TomeDev committed
			os_autoflush = TRUE;
		if (!strncmp(arg, "--no-debug", 10)) no_debug = TRUE;
dg's avatar
dg committed
		if (!strncmp(arg, "--xpos", 6)) start_xpos = strtol(argv[++i], NULL, 10);
		if (!strncmp(arg, "--ypos", 6)) start_ypos = strtol(argv[++i], NULL, 10);
		if (!strncmp(arg, "--ignore-window-change-pos", 26)) ignore_window_change_pos = TRUE;
		if (!strncmp(arg, "--safe-mode", 11)) safe_mode = TRUE;
		if (!strncmp(arg, "--home", 6)) override_home = strdup(argv[++i]);
DarkGod's avatar
DarkGod committed
		if (!strncmp(arg, "--no-steam", 10)) no_steam = TRUE;
DarkGod's avatar
DarkGod committed
		if (!strncmp(arg, "--type=zygote", 13)) is_zygote = TRUE;
		if (!strncmp(arg, "--type=renderer", 15)) is_zygote = TRUE;
DarkGod's avatar
DarkGod committed
		if (!strncmp(arg, "--no-sandbox", 12)) is_zygote = TRUE;
		if (!strncmp(arg, "--logtofile", 11)) logtofile = TRUE;
DarkGod's avatar
DarkGod committed
		if (!strncmp(arg, "--no-web", 8)) no_web = TRUE;
DarkGod's avatar
DarkGod committed
#ifdef SELFEXE_WINDOWS
	logtofile = TRUE;
#endif
	if (!is_zygote && logtofile) {
DarkGod's avatar
DarkGod committed
		logfile = freopen("te4_log.txt", "w", stdout);
TomeDev's avatar
TomeDev committed
		if (os_autoflush) setvbuf(logfile, NULL, _IONBF, 2);
	}
#ifdef SELFEXE_MACOSX
	if (!is_zygote) {
		const char *logname = "/tmp/te4_log.txt";
TomeDev's avatar
TomeDev committed
		logfile = freopen(logname, "w", stdout);
		if (os_autoflush) setlinebuf(logfile);
DarkGod's avatar
DarkGod committed
	}
#endif

DarkGod's avatar
DarkGod committed
	if (!no_web) te4_web_load();
	// Initialize display lock for thread safety.
	renderingLock = SDL_CreateMutex();
	realtimeLock = SDL_CreateMutex();
	
	// Get cpu cores
	nb_cpus = get_number_cpus();
	printf("[CPU] Detected %d CPUs\n", nb_cpus);

DarkGod's avatar
DarkGod committed
	if (!no_steam) te4_steam_init();
	// RNG init
	init_gen_rand(time(NULL));

dg's avatar
dg committed
	int vid_drv;
	for (vid_drv = 0; vid_drv < SDL_GetNumVideoDrivers(); vid_drv++)
	{
		printf("Available video driver: %s\n", SDL_GetVideoDriver(vid_drv));
	}

dg's avatar
dg committed
	// initialize engine and set up resolution and depth
	Uint32 flags=SDL_INIT_TIMER | SDL_INIT_JOYSTICK;
dg's avatar
dg committed
	if (SDL_Init (flags) < 0) {
		printf("cannot initialize SDL: %s\n", SDL_GetError ());
dg's avatar
dg committed
		return 1;
dg's avatar
dg committed
	}
dg's avatar
dg committed

dg's avatar
dg committed
	if (SDL_VideoInit(NULL) != 0) {
		printf("Error initializing SDL video:  %s\n", SDL_GetError());
		return 2;
	}

	if (SDL_NumJoysticks() >= 1) {
		if (gamepad = SDL_JoystickOpen(0)) {
			printf("Found gamepad, enabling support\n");
		}
	}
dg's avatar
dg committed

dg's avatar
dg committed
	// Filter events, to catch the quit event
dg's avatar
dg committed

	boot_lua(1, FALSE, argc, argv);

	do_resize(WIDTH, HEIGHT, FALSE, FALSE, screen_zoom);
dg's avatar
dg committed
	if (screen==NULL) {
		printf("error opening screen: %s\n", SDL_GetError());
dg's avatar
dg committed
		return 3;
dg's avatar
dg committed
	}
dg's avatar
dg committed
	TTF_Init();
dg's avatar
dg committed

dg's avatar
dg committed
	/* Sets up OpenGL double buffering */
	resizeWindow(WIDTH, HEIGHT);

	// Allow screensaver to work
	SDL_EnableScreenSaver();
	SDL_StartTextInput();
	// Get OpenGL capabilities
dg's avatar
dg committed
	multitexture_active = GLEW_ARB_multitexture;
	shaders_active = GLEW_ARB_shader_objects;
	fbo_active = GLEW_EXT_framebuffer_object || GLEW_ARB_framebuffer_object;
	if (!multitexture_active) shaders_active = FALSE;
	if (!GLEW_VERSION_2_1 || safe_mode)
dg's avatar
dg committed
	{
		multitexture_active = FALSE;
		shaders_active = FALSE;
		fbo_active = FALSE;
	}
	if (safe_mode) printf("Safe mode activated\n");
dg's avatar
dg committed

	boot_lua(2, FALSE, argc, argv);
dg's avatar
dg committed

dg's avatar
dg committed
	pass_command_args(argc, argv);

dg's avatar
dg committed
	SDL_Event event;
dg's avatar
dg committed
	while (!exit_engine)
dg's avatar
dg committed
	{
		if (!isActive || tickPaused) SDL_WaitEvent(NULL);
TomeDev's avatar
TomeDev committed
		if (os_autoflush) _commit(_fileno(stdout));
#endif
#ifdef SELFEXE_MACOSX
		if (os_autoflush) fflush(stdout);
dg's avatar
dg committed
		/* handle the events in the queue */
		while (SDL_PollEvent(&event))
		{
			switch(event.type)
			{
			case SDL_WINDOWEVENT:
				switch (event.window.event)
					/* Note: SDL can't resize a fullscreen window, so don't bother! */
					if (!is_fullscreen) {
						printf("SDL_WINDOWEVENT_RESIZED: %d x %d\n", event.window.data1, event.window.data2);
						do_resize(event.window.data1, event.window.data2, is_fullscreen, is_borderless, screen_zoom);
						if (current_game != LUA_NOREF)
						{
							lua_rawgeti(L, LUA_REGISTRYINDEX, current_game);
							lua_pushstring(L, "onResolutionChange");
							lua_gettable(L, -2);
							lua_remove(L, -2);
							lua_rawgeti(L, LUA_REGISTRYINDEX, current_game);
							docall(L, 1, 0);
						}
					} else {
						printf("SDL_WINDOWEVENT_RESIZED: ignored due to fullscreen\n");
					/* Note: SDL can't resize a fullscreen window, so don't bother! */
					if (!is_fullscreen) {
						SDL_GetWindowPosition(window, &x, &y);
						printf("move %d x %d\n", x, y);
						if (current_game != LUA_NOREF)
						{
							lua_rawgeti(L, LUA_REGISTRYINDEX, current_game);
							lua_pushstring(L, "onWindowMoved");
							lua_gettable(L, -2);
							lua_remove(L, -2);
							lua_rawgeti(L, LUA_REGISTRYINDEX, current_game);
							lua_pushnumber(L, x);
							lua_pushnumber(L, y);
							docall(L, 3, 0);
						}
					} else {
						printf("SDL_WINDOWEVENT_MOVED: ignored due to fullscreen\n");
				case SDL_WINDOWEVENT_CLOSE:
					event.type = SDL_QUIT;
					SDL_PushEvent(&event);
					break;
				case SDL_WINDOWEVENT_SHOWN:
				case SDL_WINDOWEVENT_FOCUS_GAINED:
					SDL_SetModState(KMOD_NONE);
					/* break from idle */
					//printf("[EVENT HANDLER]: Got a SHOW/FOCUS_GAINED event, restoring full FPS.\n");
					handleIdleTransition(0);
					break;

				case SDL_WINDOWEVENT_HIDDEN:
					//printf("[EVENT HANDLER]: Got a HIDDEN/FOCUS_LOST event, going idle.\n");
					handleIdleTransition(1);
dg's avatar
dg committed
				}
				break;
dg's avatar
dg committed
			case SDL_QUIT:
				/* handle quit requests */
dg's avatar
dg committed
				exit_engine = TRUE;
dg's avatar
dg committed
				break;
dg's avatar
dg committed
			case SDL_USEREVENT:
				/* TODO: Enumerate user event codes */
				switch(event.user.code)
				{
				case 0:
					if (isActive) {
						current_redraw_type = redraw_type_normal;
						on_redraw();
						SDL_mutexP(renderingLock);
						redraw_pending = 0;
						SDL_mutexV(renderingLock);
					}
					break;
				case 1:
dg's avatar
dg committed
					on_music_stop();
					break;

				case 2:
					if (isActive) {
						on_tick();
						SDL_mutexP(realtimeLock);
						realtime_pending = 0;
						SDL_mutexV(realtimeLock);
					}
					break;

				default:
					break;
dg's avatar
dg committed
				}
dg's avatar
dg committed
				break;
dg's avatar
dg committed
			default:
				/* handle key presses */
				if (on_event(&event)) {
					tickPaused = FALSE;
				}
dg's avatar
dg committed
				break;
			}
		}

		/* draw the scene */
		// Note: since realtime_timer_id is accessed, have to lock first
		int doATick = 0;
		SDL_mutexP(realtimeLock);
			if (!realtime_timer_id && isActive && !tickPaused) {
				doATick = 1;
				realtime_pending = 1;
			}
		SDL_mutexV(realtimeLock);
		if (doATick) {
			on_tick();
			SDL_mutexP(realtimeLock);
			realtime_pending = 0;	
			SDL_mutexV(realtimeLock);
		}

		/* Reboot the lua engine */
dg's avatar
dg committed
		if (core_def->corenum)
dg's avatar
dg committed
			if (core_def->corenum == TE4CORE_VERSION)
			{
				tickPaused = FALSE;
				setupRealtime(0);
				boot_lua(1, TRUE, argc, argv);
				boot_lua(2, TRUE, argc, argv);
			}
			// Clean up and tell the runner to run a different core
			else
			{
dg's avatar
dg committed
				lua_close(L);
				free_particles_thread();
				free_profile_thread();
				PHYSFS_deinit();
				break;
			}
dg's avatar
dg committed
	}
dg's avatar
dg committed

	printf("Cleaning up!\n");
	cleanupTimerLock(renderingLock, &display_timer_id, &redraw_pending);
	cleanupTimerLock(realtimeLock, &realtime_timer_id, &realtime_pending);
	
DarkGod's avatar
DarkGod committed
	printf("Terminating!\n");
DarkGod's avatar
DarkGod committed
	te4_web_terminate();
DarkGod's avatar
DarkGod committed
	printf("Webcore shutdown complete\n");
	// Restore default gamma on exit.
DarkGod's avatar
DarkGod committed
	if (desktop_gamma_set) SDL_SetWindowBrightness(window, desktop_gamma);
DarkGod's avatar
DarkGod committed
//	SDL_Quit();
DarkGod's avatar
DarkGod committed
	printf("SDL shutdown complete\n");
DarkGod's avatar
DarkGod committed
//	deinit_openal();
DarkGod's avatar
DarkGod committed
	printf("OpenAL shutdown complete\n");
dg's avatar
dg committed
	printf("Thanks for having fun!\n");
dg's avatar
dg committed

#ifdef SELFEXE_WINDOWS
DarkGod's avatar
DarkGod committed
	TerminateProcess( GetCurrentProcess(),0);
dg's avatar
dg committed
	fclose(stdout);
dg's avatar
dg committed
#endif
TomeDev's avatar
TomeDev committed
#ifdef SELFEXE_MACOSX
	fclose(stdout);
#endif
dg's avatar
dg committed
}