2005-08-15 01:34:37 +02:00
|
|
|
/*
|
|
|
|
|
|
|
|
This module drives the game when running without Atlas (our integrated
|
|
|
|
map editor). It receives input and OS messages via SDL and feeds them
|
|
|
|
into the input dispatcher, where they are passed on to the game GUI and
|
|
|
|
simulation.
|
|
|
|
It also contains main(), which either runs the above controller or
|
|
|
|
that of Atlas depending on commandline parameters.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2006-06-02 05:56:24 +02:00
|
|
|
// not for any PCH effort, but instead for the (common) definitions
|
|
|
|
// included there.
|
|
|
|
#include "lib/precompiled.h"
|
2004-06-03 20:38:14 +02:00
|
|
|
|
2005-08-15 01:34:37 +02:00
|
|
|
#include "lib/input.h"
|
2007-05-04 19:30:32 +02:00
|
|
|
#include "lib/external_libraries/sdl.h"
|
2005-06-16 23:50:20 +02:00
|
|
|
#include "lib/timer.h"
|
2005-08-15 01:34:37 +02:00
|
|
|
#include "lib/res/file/vfs.h"
|
2006-04-10 23:49:12 +02:00
|
|
|
#include "lib/res/sound/snd_mgr.h"
|
2006-03-01 23:31:11 +01:00
|
|
|
#include "lib/res/file/vfs_optimizer.h"
|
2004-06-02 22:39:21 +02:00
|
|
|
|
2005-08-15 01:34:37 +02:00
|
|
|
#include "ps/GameSetup/GameSetup.h"
|
|
|
|
#include "ps/GameSetup/Atlas.h"
|
|
|
|
#include "ps/GameSetup/Config.h"
|
2006-12-09 15:39:52 +01:00
|
|
|
#include "ps/GameSetup/CmdLineArgs.h"
|
2005-03-22 03:17:55 +01:00
|
|
|
#include "ps/Loader.h"
|
2004-06-02 22:39:21 +02:00
|
|
|
#include "ps/CConsole.h"
|
2005-08-15 01:34:37 +02:00
|
|
|
#include "ps/Profile.h"
|
2005-08-15 01:50:37 +02:00
|
|
|
#include "ps/Util.h"
|
2004-07-27 23:00:53 +02:00
|
|
|
#include "ps/Game.h"
|
2005-06-16 23:50:20 +02:00
|
|
|
#include "ps/Hotkey.h"
|
2005-10-31 19:36:36 +01:00
|
|
|
#include "ps/Globals.h"
|
2005-08-15 01:34:37 +02:00
|
|
|
#include "ps/Interact.h"
|
2006-08-26 22:25:37 +02:00
|
|
|
#include "network/SessionManager.h"
|
2007-01-08 02:56:46 +01:00
|
|
|
#include "graphics/Camera.h"
|
2006-03-21 21:55:45 +01:00
|
|
|
#include "graphics/GameView.h"
|
2005-06-16 23:50:20 +02:00
|
|
|
#include "simulation/Scheduler.h"
|
2004-07-28 13:36:16 +02:00
|
|
|
#include "sound/CMusicPlayer.h"
|
2005-10-31 19:36:36 +01:00
|
|
|
#include "gui/GUI.h"
|
2004-09-19 17:58:13 +02:00
|
|
|
|
2006-06-08 23:27:03 +02:00
|
|
|
#if OS_WIN
|
2007-05-04 19:30:32 +02:00
|
|
|
# include "lib/sysdep/win/wstartup.h"
|
2006-06-08 23:27:03 +02:00
|
|
|
#endif
|
|
|
|
|
2005-08-15 01:34:37 +02:00
|
|
|
#define LOG_CATEGORY "main"
|
2005-06-16 23:50:20 +02:00
|
|
|
|
2005-10-19 05:02:51 +02:00
|
|
|
extern bool g_TerrainModified;
|
2006-10-08 05:28:22 +02:00
|
|
|
extern bool g_GameRestarted;
|
2005-06-16 23:50:20 +02:00
|
|
|
|
2005-08-15 01:34:37 +02:00
|
|
|
void kill_mainloop();
|
2005-06-16 23:50:20 +02:00
|
|
|
|
2004-06-02 22:39:21 +02:00
|
|
|
|
2005-08-15 01:34:37 +02:00
|
|
|
// main app message handler
|
2006-08-26 23:52:18 +02:00
|
|
|
static InReaction MainInputHandler(const SDL_Event_* ev)
|
2004-05-24 22:25:48 +02:00
|
|
|
{
|
2006-08-26 23:52:18 +02:00
|
|
|
switch(ev->ev.type)
|
2004-05-24 22:25:48 +02:00
|
|
|
{
|
2005-10-12 06:27:55 +02:00
|
|
|
case SDL_QUIT:
|
|
|
|
kill_mainloop();
|
|
|
|
break;
|
|
|
|
|
2004-07-21 18:34:07 +02:00
|
|
|
case SDL_HOTKEYDOWN:
|
2006-08-26 23:52:18 +02:00
|
|
|
switch(ev->ev.user.code)
|
2004-05-24 22:25:48 +02:00
|
|
|
{
|
2004-07-21 18:34:07 +02:00
|
|
|
case HOTKEY_EXIT:
|
2005-08-15 01:34:37 +02:00
|
|
|
kill_mainloop();
|
2005-10-20 19:44:56 +02:00
|
|
|
return IN_HANDLED;
|
2004-06-26 00:13:48 +02:00
|
|
|
|
2004-07-21 18:34:07 +02:00
|
|
|
case HOTKEY_SCREENSHOT:
|
2005-08-15 01:34:37 +02:00
|
|
|
WriteScreenshot("png");
|
2005-10-20 19:44:56 +02:00
|
|
|
return IN_HANDLED;
|
2004-07-28 13:36:16 +02:00
|
|
|
|
2005-10-24 03:53:03 +02:00
|
|
|
case HOTKEY_BIGSCREENSHOT:
|
|
|
|
WriteBigScreenshot("bmp", 10);
|
|
|
|
return IN_HANDLED;
|
|
|
|
|
2004-07-21 18:34:07 +02:00
|
|
|
default:
|
2005-10-13 20:05:55 +02:00
|
|
|
break;
|
2004-05-24 22:25:48 +02:00
|
|
|
}
|
2005-10-13 20:05:55 +02:00
|
|
|
break;
|
2004-05-24 22:25:48 +02:00
|
|
|
}
|
|
|
|
|
2005-10-20 19:44:56 +02:00
|
|
|
return IN_PASS;
|
2004-05-24 22:25:48 +02:00
|
|
|
}
|
|
|
|
|
2005-06-16 23:50:20 +02:00
|
|
|
|
2005-08-15 01:34:37 +02:00
|
|
|
// dispatch all pending events to the various receivers.
|
|
|
|
static void PumpEvents()
|
2004-06-21 16:14:12 +02:00
|
|
|
{
|
2005-08-15 01:34:37 +02:00
|
|
|
in_dispatch_recorded_events();
|
2004-07-24 21:38:12 +02:00
|
|
|
|
2006-08-26 23:52:18 +02:00
|
|
|
SDL_Event_ ev;
|
|
|
|
while(SDL_PollEvent(&ev.ev))
|
|
|
|
in_dispatch_event(&ev);
|
2004-12-08 16:34:15 +01:00
|
|
|
}
|
|
|
|
|
2005-06-16 23:50:20 +02:00
|
|
|
|
2006-03-01 23:31:11 +01:00
|
|
|
// return indication of whether archive is currently being built; this is
|
|
|
|
// used to prevent reloading during that time (see call site).
|
|
|
|
static bool ProgressiveBuildArchive()
|
|
|
|
{
|
2006-03-07 06:44:34 +01:00
|
|
|
int ret = vfs_opt_auto_build("../logs/trace.txt", "mods/official/official%02d.zip", "mods/official/mini%02d.zip");
|
2006-09-22 15:19:40 +02:00
|
|
|
if(ret == INFO::ALL_COMPLETE)
|
2006-03-01 23:31:11 +01:00
|
|
|
{
|
|
|
|
// nothing to do; will return false below
|
|
|
|
}
|
|
|
|
else if(ret < 0)
|
|
|
|
DISPLAY_ERROR(L"Archive build failed");
|
2006-09-22 15:19:40 +02:00
|
|
|
else if(ret == INFO::OK)
|
2006-03-01 23:31:11 +01:00
|
|
|
g_GUI.SendEventToAll("archivebuildercomplete");
|
|
|
|
// in progress
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int percent = (int)ret;
|
|
|
|
g_ScriptingHost.SetGlobal("g_ArchiveBuilderProgress", INT_TO_JSVAL(percent));
|
|
|
|
g_GUI.SendEventToAll("archivebuilderprogress");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-03-22 03:17:55 +01:00
|
|
|
|
|
|
|
static int ProgressiveLoad()
|
|
|
|
{
|
|
|
|
wchar_t description[100];
|
|
|
|
int progress_percent;
|
2005-12-12 20:19:30 +01:00
|
|
|
LibError ret = LDR_ProgressiveLoad(10e-3, description, ARRAY_SIZE(description), &progress_percent);
|
2005-03-22 03:17:55 +01:00
|
|
|
switch(ret)
|
|
|
|
{
|
2005-08-15 01:34:37 +02:00
|
|
|
// no load active => no-op (skip code below)
|
2006-09-22 15:19:40 +02:00
|
|
|
case INFO::OK:
|
2005-05-11 06:39:21 +02:00
|
|
|
return 0;
|
2005-08-15 01:34:37 +02:00
|
|
|
// current task didn't complete. we only care about this insofar as the
|
|
|
|
// load process is therefore not yet finished.
|
2006-09-22 15:19:40 +02:00
|
|
|
case ERR::TIMED_OUT:
|
2005-03-22 03:17:55 +01:00
|
|
|
break;
|
2005-08-15 01:34:37 +02:00
|
|
|
// just finished loading
|
2006-09-22 15:19:40 +02:00
|
|
|
case INFO::ALL_COMPLETE:
|
2005-03-22 03:17:55 +01:00
|
|
|
g_Game->ReallyStartGame();
|
|
|
|
wcscpy_s(description, ARRAY_SIZE(description), L"Game is starting..");
|
2005-08-15 01:34:37 +02:00
|
|
|
// LDR_ProgressiveLoad returns L""; set to valid text to
|
|
|
|
// avoid problems in converting to JSString
|
2005-03-22 03:17:55 +01:00
|
|
|
break;
|
2005-08-15 01:34:37 +02:00
|
|
|
// error!
|
2005-03-22 03:17:55 +01:00
|
|
|
default:
|
|
|
|
CHECK_ERR(ret);
|
2006-09-22 15:19:40 +02:00
|
|
|
// can't do this above due to legit ERR::TIMED_OUT
|
2005-03-22 03:17:55 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-08-14 17:23:59 +02:00
|
|
|
GUI_DisplayLoadProgress(progress_percent, description);
|
2005-03-22 03:17:55 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-03-01 23:31:11 +01:00
|
|
|
|
2005-08-15 01:34:37 +02:00
|
|
|
CMusicPlayer music_player;
|
2005-06-16 23:50:20 +02:00
|
|
|
|
2004-07-12 18:50:46 +02:00
|
|
|
static void Frame()
|
|
|
|
{
|
2005-08-09 18:03:36 +02:00
|
|
|
MICROLOG(L"Frame");
|
2007-05-02 14:07:08 +02:00
|
|
|
ogl_WarnIfError();
|
2005-06-25 04:21:26 +02:00
|
|
|
|
2005-10-31 19:36:36 +01:00
|
|
|
// get elapsed time
|
2005-10-18 01:35:16 +02:00
|
|
|
calc_fps();
|
2005-10-31 19:36:36 +01:00
|
|
|
// .. old method - "exact" but contains jumps
|
2005-10-18 01:35:16 +02:00
|
|
|
#if 0
|
2004-07-12 18:50:46 +02:00
|
|
|
static double last_time;
|
|
|
|
const double time = get_time();
|
|
|
|
const float TimeSinceLastFrame = (float)(time-last_time);
|
|
|
|
last_time = time;
|
2005-10-18 01:35:16 +02:00
|
|
|
ONCE(return); // first call: set last_time and return
|
2005-10-31 19:36:36 +01:00
|
|
|
|
|
|
|
// .. new method - filtered and more smooth, but errors may accumulate
|
2005-10-18 01:35:16 +02:00
|
|
|
#else
|
|
|
|
const float TimeSinceLastFrame = spf;
|
|
|
|
#endif
|
2005-06-28 06:06:25 +02:00
|
|
|
debug_assert(TimeSinceLastFrame >= 0.0f);
|
2004-05-24 22:25:48 +02:00
|
|
|
|
2005-10-31 19:36:36 +01:00
|
|
|
// decide if update/render is necessary
|
|
|
|
bool need_render, need_update;
|
2006-01-02 04:07:29 +01:00
|
|
|
if( g_app_minimized )
|
2005-10-31 19:36:36 +01:00
|
|
|
{
|
|
|
|
// TODO: eventually update ought to be re-enabled so the server host
|
|
|
|
// can Alt+Tab out without the match hanging. however, game updates
|
|
|
|
// are currently really slow and disabling them makes debugging nicer.
|
|
|
|
need_update = false;
|
|
|
|
need_render = false;
|
|
|
|
|
|
|
|
// inactive; relinquish CPU for a little while
|
|
|
|
// don't use SDL_WaitEvent: don't want the main loop to freeze until app focus is restored
|
|
|
|
SDL_Delay(10);
|
|
|
|
}
|
2006-01-02 04:07:29 +01:00
|
|
|
else if( !g_app_has_focus )
|
2005-10-31 19:36:36 +01:00
|
|
|
{
|
|
|
|
need_update = false; // see above
|
|
|
|
need_render = true;
|
|
|
|
|
|
|
|
SDL_Delay(5); // see above
|
|
|
|
}
|
2006-01-02 04:07:29 +01:00
|
|
|
else // active
|
2005-10-31 19:36:36 +01:00
|
|
|
{
|
|
|
|
need_update = true;
|
|
|
|
need_render = true;
|
|
|
|
}
|
|
|
|
// TODO: throttling: limit update and render frequency to the minimum.
|
|
|
|
// this is mostly relevant for "inactive" state, so that other windows
|
|
|
|
// get enough CPU time, but it's always nice for power+thermal management.
|
|
|
|
|
|
|
|
|
|
|
|
PROFILE_START( "update music" );
|
2007-05-02 14:07:08 +02:00
|
|
|
music_player.Update();
|
2005-10-31 19:36:36 +01:00
|
|
|
PROFILE_END( "update music" );
|
|
|
|
|
2006-03-01 23:31:11 +01:00
|
|
|
bool is_building_archive; // must come before PROFILE_START's {
|
|
|
|
PROFILE_START("build archive");
|
|
|
|
MICROLOG(L"build archive");
|
|
|
|
is_building_archive = ProgressiveBuildArchive();
|
|
|
|
PROFILE_END( "build archive");
|
|
|
|
|
|
|
|
// this scans for changed files/directories and reloads them, thus
|
|
|
|
// allowing hotloading (changes are immediately assimilated in-game).
|
|
|
|
// must not be done during archive building because it changes the
|
|
|
|
// archive file each iteration, but keeps it locked; reloading
|
|
|
|
// would trigger a warning because the file can't be opened.
|
|
|
|
if(!is_building_archive)
|
|
|
|
{
|
|
|
|
PROFILE_START("reload changed files");
|
|
|
|
MICROLOG(L"reload changed files");
|
|
|
|
vfs_reload_changed_files();
|
|
|
|
PROFILE_END( "reload changed files");
|
|
|
|
}
|
2004-05-24 22:25:48 +02:00
|
|
|
|
2005-10-31 19:36:36 +01:00
|
|
|
PROFILE_START("progressive load");
|
|
|
|
MICROLOG(L"progressive load");
|
2005-03-22 03:17:55 +01:00
|
|
|
ProgressiveLoad();
|
2005-10-31 19:36:36 +01:00
|
|
|
PROFILE_END( "progressive load");
|
2004-07-15 21:12:54 +02:00
|
|
|
|
2005-10-31 19:36:36 +01:00
|
|
|
PROFILE_START("input");
|
2005-03-22 03:17:55 +01:00
|
|
|
MICROLOG(L"input");
|
2005-08-15 01:34:37 +02:00
|
|
|
PumpEvents();
|
2004-08-16 17:19:17 +02:00
|
|
|
g_SessionManager.Poll();
|
2005-10-31 19:36:36 +01:00
|
|
|
PROFILE_END("input");
|
2005-03-30 18:14:19 +02:00
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
ogl_WarnIfError();
|
2005-10-12 06:27:55 +02:00
|
|
|
|
2005-10-31 19:36:36 +01:00
|
|
|
PROFILE_START("gui tick");
|
|
|
|
MICROLOG(L"gui tick");
|
2005-01-11 17:58:16 +01:00
|
|
|
#ifndef NO_GUI
|
2004-12-19 00:25:58 +01:00
|
|
|
g_GUI.TickObjects();
|
2005-01-11 17:58:16 +01:00
|
|
|
#endif
|
2005-10-31 19:36:36 +01:00
|
|
|
PROFILE_END("gui tick");
|
2005-08-09 18:03:36 +02:00
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
ogl_WarnIfError();
|
2005-10-12 06:27:55 +02:00
|
|
|
|
2005-03-30 18:14:19 +02:00
|
|
|
PROFILE_START( "game logic" );
|
2005-10-31 19:36:36 +01:00
|
|
|
if (g_Game && g_Game->IsGameStarted() && need_update)
|
2004-08-05 15:07:51 +02:00
|
|
|
{
|
2005-03-30 18:14:19 +02:00
|
|
|
PROFILE_START( "simulation update" );
|
2004-08-05 15:07:51 +02:00
|
|
|
g_Game->Update(TimeSinceLastFrame);
|
2005-03-30 18:14:19 +02:00
|
|
|
PROFILE_END( "simulation update" );
|
2005-03-22 03:17:55 +01:00
|
|
|
|
2004-08-05 15:07:51 +02:00
|
|
|
if (!g_FixedFrameTiming)
|
2005-03-30 18:14:19 +02:00
|
|
|
{
|
|
|
|
PROFILE( "camera update" );
|
2004-08-05 15:07:51 +02:00
|
|
|
g_Game->GetView()->Update(float(TimeSinceLastFrame));
|
2005-03-30 18:14:19 +02:00
|
|
|
}
|
2004-07-21 18:34:07 +02:00
|
|
|
|
2005-03-30 18:14:19 +02:00
|
|
|
PROFILE_START( "selection and interaction ui" );
|
2004-08-05 15:07:51 +02:00
|
|
|
// TODO Where does GameView end and other things begin?
|
2007-05-02 14:07:08 +02:00
|
|
|
g_Mouseover.Update( TimeSinceLastFrame );
|
|
|
|
g_Selection.Update();
|
|
|
|
g_BuildingPlacer.Update( TimeSinceLastFrame );
|
2005-03-30 18:14:19 +02:00
|
|
|
PROFILE_END( "selection and interaction ui" );
|
2004-10-15 15:29:04 +02:00
|
|
|
|
2005-03-30 18:14:19 +02:00
|
|
|
PROFILE_START( "sound update" );
|
2004-10-15 15:29:04 +02:00
|
|
|
CCamera* camera = g_Game->GetView()->GetCamera();
|
|
|
|
CMatrix3D& orientation = camera->m_Orientation;
|
2004-10-16 22:55:56 +02:00
|
|
|
|
|
|
|
float* pos = &orientation._data[12];
|
|
|
|
float* dir = &orientation._data[8];
|
|
|
|
float* up = &orientation._data[4];
|
2004-10-21 01:16:38 +02:00
|
|
|
if(snd_update(pos, dir, up) < 0)
|
2005-05-11 20:56:30 +02:00
|
|
|
debug_printf("snd_update failed\n");
|
2005-03-30 18:14:19 +02:00
|
|
|
PROFILE_END( "sound update" );
|
2004-08-05 15:07:51 +02:00
|
|
|
}
|
2004-10-21 01:16:38 +02:00
|
|
|
else
|
|
|
|
{
|
2004-12-19 00:25:58 +01:00
|
|
|
// CSimulation would do this with the proper turn length if we were in
|
|
|
|
// a game. This is basically just to keep script timers running.
|
2005-07-20 02:57:17 +02:00
|
|
|
uint ms_elapsed = (uint)(TimeSinceLastFrame*1000);
|
2007-05-02 14:07:08 +02:00
|
|
|
g_Scheduler.Update(ms_elapsed);
|
2004-10-21 01:16:38 +02:00
|
|
|
if(snd_update(0, 0, 0) < 0)
|
2005-05-11 20:56:30 +02:00
|
|
|
debug_printf("snd_update (pos=0 version) failed\n");
|
2004-10-21 01:16:38 +02:00
|
|
|
}
|
2005-03-30 18:14:19 +02:00
|
|
|
PROFILE_END( "game logic" );
|
|
|
|
|
|
|
|
PROFILE_START( "update console" );
|
2004-07-20 21:30:35 +02:00
|
|
|
g_Console->Update(TimeSinceLastFrame);
|
2005-03-30 18:14:19 +02:00
|
|
|
PROFILE_END( "update console" );
|
2004-07-20 21:30:35 +02:00
|
|
|
|
2005-10-31 19:36:36 +01:00
|
|
|
PROFILE_START("render");
|
2007-05-02 14:07:08 +02:00
|
|
|
ogl_WarnIfError();
|
2005-10-31 19:36:36 +01:00
|
|
|
if(need_render)
|
2004-07-12 18:50:46 +02:00
|
|
|
{
|
2004-07-15 21:12:54 +02:00
|
|
|
MICROLOG(L"render");
|
2004-07-12 18:50:46 +02:00
|
|
|
Render();
|
2004-07-15 21:12:54 +02:00
|
|
|
MICROLOG(L"finished render");
|
2005-03-31 00:33:10 +02:00
|
|
|
PROFILE_START( "swap buffers" );
|
2004-12-28 12:16:05 +01:00
|
|
|
SDL_GL_SwapBuffers();
|
2005-03-31 00:33:10 +02:00
|
|
|
PROFILE_END( "swap buffers" );
|
2004-07-12 18:50:46 +02:00
|
|
|
}
|
2007-05-02 14:07:08 +02:00
|
|
|
ogl_WarnIfError();
|
2005-10-31 19:36:36 +01:00
|
|
|
PROFILE_END("render");
|
2005-03-30 18:14:19 +02:00
|
|
|
|
|
|
|
g_Profiler.Frame();
|
|
|
|
|
2005-08-15 01:34:37 +02:00
|
|
|
if(g_FixedFrameTiming && frameCount==100)
|
|
|
|
kill_mainloop();
|
2005-10-19 05:02:51 +02:00
|
|
|
|
|
|
|
g_TerrainModified = false;
|
2006-10-08 05:28:22 +02:00
|
|
|
g_GameRestarted = false;
|
2005-08-15 01:34:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void MainControllerInit()
|
|
|
|
{
|
2005-10-19 08:11:21 +02:00
|
|
|
// add additional input handlers only needed by this controller:
|
2005-08-15 01:34:37 +02:00
|
|
|
|
2005-10-19 08:11:21 +02:00
|
|
|
// gui_handler needs to be registered after (i.e. called before!) the
|
|
|
|
// hotkey handler so that input boxes can be typed in without
|
|
|
|
// setting off hotkeys.
|
2005-08-15 01:34:37 +02:00
|
|
|
#ifndef NO_GUI
|
|
|
|
in_add_handler(gui_handler);
|
|
|
|
#endif
|
|
|
|
|
2005-10-19 08:11:21 +02:00
|
|
|
// must be registered after gui_handler. Should mayhap even be last.
|
2005-08-15 01:34:37 +02:00
|
|
|
in_add_handler(MainInputHandler);
|
2004-07-12 18:50:46 +02:00
|
|
|
}
|
2004-05-24 22:25:48 +02:00
|
|
|
|
2004-07-15 21:12:54 +02:00
|
|
|
|
|
|
|
|
2005-08-15 01:34:37 +02:00
|
|
|
static void MainControllerShutdown()
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
music_player.Release();
|
2005-08-15 01:34:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool quit = false; // break out of main loop
|
|
|
|
|
2005-10-13 20:05:55 +02:00
|
|
|
// stop the main loop and trigger orderly shutdown. called from several
|
|
|
|
// places: the event handler (SDL_QUIT and hotkey) and JS exitProgram.
|
2005-08-15 01:34:37 +02:00
|
|
|
void kill_mainloop()
|
|
|
|
{
|
|
|
|
quit = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-05 19:41:20 +02:00
|
|
|
// moved into a helper function to ensure args is destroyed before
|
|
|
|
// exit(), which may result in a memory leak.
|
|
|
|
static void RunGameOrAtlas(int argc, char* argv[])
|
2004-07-12 18:50:46 +02:00
|
|
|
{
|
2007-05-04 19:30:32 +02:00
|
|
|
CmdLineArgs args(argc, argv);
|
2005-01-25 19:56:43 +01:00
|
|
|
|
2007-05-04 19:30:32 +02:00
|
|
|
// run Atlas (if requested via args)
|
|
|
|
bool ran_atlas = ATLAS_RunIfOnCmdLine(args);
|
2007-05-05 19:41:20 +02:00
|
|
|
// Atlas handles the whole init/shutdown/etc sequence by itself;
|
|
|
|
// when we get here, it has exited and we're done.
|
2007-05-04 19:30:32 +02:00
|
|
|
if(ran_atlas)
|
2007-05-05 19:41:20 +02:00
|
|
|
return;
|
2006-04-10 23:49:12 +02:00
|
|
|
|
2007-05-04 19:30:32 +02:00
|
|
|
// run the game
|
|
|
|
Init(args, 0);
|
|
|
|
MainControllerInit();
|
|
|
|
while(!quit)
|
|
|
|
Frame();
|
|
|
|
Shutdown(0);
|
|
|
|
MainControllerShutdown();
|
2007-05-05 19:41:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
// If you ever want to catch a particular allocation:
|
|
|
|
//_CrtSetBreakAlloc(321);
|
|
|
|
|
|
|
|
// see discussion at declaration of wstartup_PreMainInit.
|
|
|
|
#if OS_WIN
|
|
|
|
wstartup_PreMainInit();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RunGameOrAtlas(argc, argv);
|
2004-07-10 16:14:36 +02:00
|
|
|
|
2007-05-04 19:30:32 +02:00
|
|
|
exit(EXIT_SUCCESS);
|
2004-05-24 22:25:48 +02:00
|
|
|
}
|