2004-06-03 20:38:14 +02:00
# include "precompiled.h"
2005-01-11 17:58:16 +01:00
# ifdef SCED
# include "ui / StdAfx.h"
# undef ERROR
# endif // SCED
2004-05-24 22:25:48 +02:00
# include <cstdio>
# include <cstring>
# include <cstdlib>
2004-06-03 03:43:33 +02:00
# include <cmath>
2004-07-12 18:50:46 +02:00
# include <stdarg.h>
2004-06-03 03:43:33 +02:00
2004-05-28 15:07:54 +02:00
2004-05-24 22:25:48 +02:00
# include "sdl.h"
# include "ogl.h"
# include "detect.h"
# include "timer.h"
# include "input.h"
# include "lib.h"
2004-10-06 16:25:36 +02:00
# include "lib/res/res.h"
# include "lib/res/tex.h"
# include "lib/res/hotload.h"
2004-05-24 22:25:48 +02:00
# ifdef _M_IX86
2005-01-11 17:58:16 +01:00
# include "sysdep / ia32.h" // _control87
2004-05-24 22:25:48 +02:00
# endif
2004-07-24 21:38:12 +02:00
# include "lib/res/cursor.h"
2004-06-02 22:39:21 +02:00
2005-03-30 18:14:19 +02:00
# include "ps/Profile.h"
# include "ps/ProfileViewer.h"
2005-03-22 03:17:55 +01:00
# include "ps/Loader.h"
2004-08-28 00:08:30 +02:00
# include "ps/Font.h"
2004-06-02 22:39:21 +02:00
# include "ps/CConsole.h"
2004-07-27 23:00:53 +02:00
# include "ps/Game.h"
2004-05-24 22:25:48 +02:00
# include "MapReader.h"
# include "Terrain.h"
2004-05-29 23:04:18 +02:00
# include "TextureManager.h"
# include "ObjectManager.h"
# include "SkeletonAnimManager.h"
2004-05-24 22:25:48 +02:00
# include "Renderer.h"
2004-08-05 15:07:51 +02:00
# include "LightEnv.h"
2004-05-24 22:25:48 +02:00
# include "Model.h"
# include "UnitManager.h"
2004-09-23 07:21:18 +02:00
# include "MaterialManager.h"
2004-11-08 23:21:50 +01:00
# include "MeshManager.h"
2005-01-11 17:58:16 +01:00
# include "Overlay.h"
2004-05-24 22:25:48 +02:00
2004-07-20 21:30:35 +02:00
# include "Interact.h"
2004-07-21 18:34:07 +02:00
# include "Hotkey.h"
2004-05-24 22:25:48 +02:00
# include "BaseEntityCollection.h"
# include "Entity.h"
# include "EntityHandles.h"
# include "EntityManager.h"
2004-05-29 05:32:33 +02:00
# include "PathfindEngine.h"
2004-07-20 21:30:35 +02:00
# include "Scheduler.h"
2005-05-10 09:13:25 +02:00
# include "Projectile.h"
2005-03-22 03:17:55 +01:00
# include "StringConvert.h"
2004-05-24 22:25:48 +02:00
2004-07-12 18:50:46 +02:00
# include "scripting/ScriptingHost.h"
2005-04-22 09:12:55 +02:00
# include "scripting/GameEvents.h"
2004-06-11 00:24:03 +02:00
# include "scripting/JSInterface_Entity.h"
# include "scripting/JSInterface_BaseEntity.h"
# include "scripting/JSInterface_Vector3D.h"
2004-08-03 01:14:54 +02:00
# include "scripting/JSInterface_Camera.h"
# include "scripting/JSInterface_Selection.h"
# include "scripting/JSInterface_Console.h"
2004-10-07 21:23:35 +02:00
# include "scripting/JSCollection.h"
2004-10-23 16:39:28 +02:00
# include "scripting/DOMEvent.h"
2005-01-11 17:58:16 +01:00
# ifndef NO_GUI
# include "gui / scripting / JSInterface_IGUIObject.h"
# include "gui / scripting / JSInterface_GUITypes.h"
# endif
2004-06-09 16:10:31 +02:00
2004-06-11 00:24:03 +02:00
# include "ConfigDB.h"
2004-06-09 16:10:31 +02:00
# include "CLogger.h"
2004-05-28 15:07:54 +02:00
2004-08-21 13:45:01 +02:00
# include "ps/i18n.h"
2004-08-15 22:57:31 +02:00
# define LOG_CATEGORY "main"
2004-05-24 22:25:48 +02:00
# ifndef NO_GUI
2005-01-11 17:58:16 +01:00
# include "gui / GUI.h"
2004-05-24 22:25:48 +02:00
# endif
2004-07-28 13:36:16 +02:00
# include "sound/CMusicPlayer.h"
2004-11-15 19:23:39 +01:00
# include "sound/JSI_Sound.h"
2004-09-19 17:58:13 +02:00
# include "lib/res/snd.h"
2004-08-16 17:19:17 +02:00
# include "Network/SessionManager.h"
# include "Network/Server.h"
2005-01-17 05:52:02 +01:00
# include "Network/Client.h"
2004-09-19 17:58:13 +02:00
2004-06-02 22:39:21 +02:00
CConsole * g_Console = 0 ;
2004-06-26 00:13:48 +02:00
extern int conInputHandler ( const SDL_Event * ev ) ;
2004-06-02 22:39:21 +02:00
2004-07-20 21:30:35 +02:00
// Globals
2004-05-24 22:25:48 +02:00
bool keys [ SDLK_LAST ] ;
2004-05-26 00:02:57 +02:00
bool mouseButtons [ 5 ] ;
2005-01-23 18:35:36 +01:00
int g_mouse_x = 50 , g_mouse_y = 50 ;
2004-05-24 22:25:48 +02:00
2004-06-03 03:43:33 +02:00
int g_xres , g_yres ;
int g_bpp ;
int g_freq ;
2004-07-12 18:50:46 +02:00
bool g_active = true ;
2004-05-24 22:25:48 +02:00
// flag to disable extended GL extensions until fix found - specifically, crashes
// using VBOs on laptop Radeon cards
static bool g_NoGLVBO = false ;
2004-05-29 23:04:18 +02:00
// flag to switch on shadows
static bool g_Shadows = false ;
// flag to switch off pbuffers
2004-06-07 21:51:52 +02:00
static bool g_NoPBuffer = true ;
// flag to switch on fixed frame timing (RC: I'm using this for profiling purposes)
static bool g_FixedFrameTiming = false ;
2004-05-24 22:25:48 +02:00
static bool g_VSync = false ;
2004-10-17 23:01:00 +02:00
static float g_LodBias = 0.0f ;
2004-05-24 22:25:48 +02:00
2004-11-19 23:58:01 +01:00
static bool g_Quickstart = false ;
2004-10-23 16:39:28 +02:00
extern CLightEnv g_LightEnv ;
2004-08-05 15:07:51 +02:00
2004-05-29 05:32:33 +02:00
static bool g_EntGraph = false ;
2004-05-24 22:25:48 +02:00
static float g_Gamma = 1.0f ;
2004-07-31 17:57:18 +02:00
extern int game_view_handler ( const SDL_Event * ev ) ;
2004-05-24 22:25:48 +02:00
2004-07-28 13:36:16 +02:00
static CMusicPlayer MusicPlayer ;
2004-07-31 14:45:30 +02:00
CStr g_CursorName = " test " ;
2004-10-23 16:39:28 +02:00
CStr g_ActiveProfile = " default " ;
2004-09-22 16:01:50 +02:00
2004-05-24 22:25:48 +02:00
extern int allow_reload ( ) ;
2004-12-10 00:12:02 +01:00
extern int dir_add_watch ( const char * dir , bool watch_subdirs ) ;
2004-05-24 22:25:48 +02:00
2004-07-12 18:50:46 +02:00
extern void sle ( int ) ;
2004-07-27 23:00:53 +02:00
extern size_t frameCount ;
2004-07-12 18:50:46 +02:00
static bool quit = false ; // break out of main loop
const wchar_t * HardcodedErrorString ( int err )
{
2004-07-14 14:26:49 +02:00
# define E(sym) case sym: return L ## #sym;
2004-07-12 18:50:46 +02:00
switch ( err )
{
E ( ERR_NO_MEM )
E ( ERR_FILE_NOT_FOUND )
E ( ERR_INVALID_HANDLE )
E ( ERR_INVALID_PARAM )
E ( ERR_EOF )
E ( ERR_PATH_NOT_FOUND )
2004-12-01 22:37:01 +01:00
E ( ERR_PATH_LENGTH )
2004-07-12 18:50:46 +02:00
default :
return 0 ;
}
}
const wchar_t * ErrorString ( int err )
{
// language file not available (yet)
if ( 1 )
return HardcodedErrorString ( err ) ;
// TODO: load from language file
}
2004-07-19 21:03:33 +02:00
ERROR_GROUP ( System ) ;
ERROR_TYPE ( System , SDLInitFailed ) ;
ERROR_TYPE ( System , VmodeFailed ) ;
ERROR_TYPE ( System , RequiredExtensionsMissing ) ;
2004-07-12 18:50:46 +02:00
2004-06-02 22:39:21 +02:00
void Testing ( void )
{
2004-06-16 17:44:24 +02:00
g_Console - > InsertMessage ( L " Testing Function Registration " ) ;
}
2004-10-23 20:13:54 +02:00
static std : : string SplitExts ( const char * exts )
{
2004-11-26 22:34:35 +01:00
std : : string str = exts ;
std : : string ret = " " ;
size_t idx = str . find_first_of ( " " ) ;
while ( idx ! = std : : string : : npos )
{
if ( idx > = str . length ( ) - 1 )
{
ret + = str ;
break ;
}
ret + = str . substr ( 0 , idx ) ;
ret + = " \n " ;
str = str . substr ( idx + 1 ) ;
idx = str . find_first_of ( " " ) ;
}
return ret ;
2004-10-23 20:13:54 +02:00
}
2004-06-02 22:39:21 +02:00
2004-12-01 22:37:01 +01:00
static void WriteSysInfo ( )
2004-05-24 22:25:48 +02:00
{
2004-11-19 23:58:01 +01:00
double t1 = get_time ( ) ;
2004-05-24 22:25:48 +02:00
get_gfx_info ( ) ;
2005-04-29 15:17:17 +02:00
// get_cpu_info already called during init - see call site
2004-11-19 23:58:01 +01:00
get_snd_info ( ) ;
get_mem_status ( ) ;
double t2 = get_time ( ) ;
2005-05-11 20:56:30 +02:00
debug_printf ( " SYS DETECT TIME %g \n \n " , t2 - t1 ) ;
2004-11-19 23:58:01 +01:00
2004-05-24 22:25:48 +02:00
struct utsname un ;
uname ( & un ) ;
2004-12-10 00:12:02 +01:00
FILE * f = fopen ( " ../logs/system_info.txt " , " w " ) ;
2004-05-24 22:25:48 +02:00
if ( ! f )
2004-12-01 22:37:01 +01:00
return ;
2004-05-24 22:25:48 +02:00
// .. OS
2005-04-19 19:04:12 +02:00
fprintf ( f , " OS : %s %s (%s) \n " , un . sysname , un . release , un . version ) ;
2004-11-19 23:58:01 +01:00
2004-05-24 22:25:48 +02:00
// .. CPU
2005-04-19 19:04:12 +02:00
fprintf ( f , " CPU : %s, %s " , un . machine , cpu_type ) ;
2004-05-24 22:25:48 +02:00
if ( cpus > 1 )
fprintf ( f , " (x%d) " , cpus ) ;
if ( cpu_freq ! = 0.0f )
{
if ( cpu_freq < 1e9 )
fprintf ( f , " , %.2f MHz \n " , cpu_freq * 1e-6 ) ;
else
fprintf ( f , " , %.2f GHz \n " , cpu_freq * 1e-9 ) ;
}
else
fprintf ( f , " \n " ) ;
2004-11-19 23:58:01 +01:00
2004-05-24 22:25:48 +02:00
// .. memory
2005-04-19 19:04:12 +02:00
fprintf ( f , " Memory : %lu MiB; %lu MiB free \n " , tot_mem / MiB , avl_mem / MiB ) ;
2004-11-19 23:58:01 +01:00
2005-04-19 19:04:12 +02:00
// .. graphics
fprintf ( f , " Graphics Card : %s (%s) \n " , gfx_card , gfx_drv_ver ) ;
fprintf ( f , " OpenGL Version: %s \n " , glGetString ( GL_VERSION ) ) ;
fprintf ( f , " Video Mode : %dx%d:%d@%d \n " , g_xres , g_yres , g_bpp , g_freq ) ;
2004-10-23 20:13:54 +02:00
2005-04-19 19:04:12 +02:00
// .. sound
fprintf ( f , " Sound Card : %s \n " , snd_card ) ;
fprintf ( f , " Sound Drivers : %s \n " , snd_drv_ver ) ;
2004-11-19 23:58:01 +01:00
2005-04-19 19:04:12 +02:00
//
2004-05-24 22:25:48 +02:00
// .. network name / ips
2005-04-19 19:04:12 +02:00
//
// note: can't use un.nodename because it is for an
// "implementation-defined communications network".
char hostname [ 128 ] = " (unknown) " ;
( void ) gethostname ( hostname , sizeof ( hostname ) - 1 ) ;
// -1 makes sure it's 0-terminated. if the function fails,
// we display "(unknown)" and will skip IP output below.
fprintf ( f , " Network Name : %s " , hostname ) ;
2004-05-24 22:25:48 +02:00
{
2005-04-19 19:04:12 +02:00
hostent * host = gethostbyname ( hostname ) ;
if ( ! host )
goto no_ip ;
struct in_addr * * ips = ( struct in_addr * * ) host - > h_addr_list ;
if ( ! ips )
goto no_ip ;
// output all IPs (> 1 if using VMware or dual ethernet)
fprintf ( f , " ( " ) ;
for ( uint i = 0 ; i < 256 & & ips [ i ] ; i + + ) // safety
{
// separate entries but avoid trailing comma
if ( i ! = 0 )
fprintf ( f , " , " ) ;
fprintf ( f , " %s " , inet_ntoa ( * ips [ i ] ) ) ;
}
fprintf ( f , " ) " ) ;
2004-05-24 22:25:48 +02:00
}
2004-06-07 21:51:52 +02:00
2005-04-19 19:04:12 +02:00
no_ip :
fprintf ( f , " \n " ) ;
// .. OpenGL extensions (write them last, since it's a lot of text)
2004-07-19 21:03:33 +02:00
const char * exts = oglExtList ( ) ;
if ( ! exts ) exts = " {unknown} " ;
2005-04-19 19:04:12 +02:00
fprintf ( f , " \n OpenGL Extensions: \n %s \n " , SplitExts ( exts ) . c_str ( ) ) ;
2004-07-19 21:03:33 +02:00
2004-05-24 22:25:48 +02:00
fclose ( f ) ;
2004-12-10 00:12:02 +01:00
f = 0 ;
2004-05-24 22:25:48 +02:00
}
2004-07-10 23:33:31 +02:00
static int set_vmode ( int w , int h , int bpp , bool fullscreen )
2004-05-24 22:25:48 +02:00
{
2004-09-23 14:42:37 +02:00
SDL_GL_SetAttribute ( SDL_GL_DEPTH_SIZE , 24 ) ;
SDL_GL_SetAttribute ( SDL_GL_DOUBLEBUFFER , 1 ) ;
2004-05-24 22:25:48 +02:00
2004-07-10 23:33:31 +02:00
if ( ! SDL_SetVideoMode ( w , h , bpp , SDL_OPENGL | ( fullscreen ? SDL_FULLSCREEN : 0 ) ) )
2004-05-24 22:25:48 +02:00
return - 1 ;
glViewport ( 0 , 0 , w , h ) ;
# ifndef NO_GUI
g_GUI . UpdateResolution ( ) ;
# endif
oglInit ( ) ; // required after each mode change
2004-07-12 18:50:46 +02:00
if ( SDL_SetGamma ( g_Gamma , g_Gamma , g_Gamma ) < 0 )
debug_warn ( " SDL_SetGamma failed " ) ;
2004-05-24 22:25:48 +02:00
return 0 ;
}
2005-03-10 17:57:42 +01:00
// <extension> identifies the file format that is to be written
// (case-insensitive). examples: "bmp", "png", "jpg".
// BMP is good for quick output at the expense of large files.
static void WriteScreenshot ( const char * extension = " png " )
2004-06-26 00:13:48 +02:00
{
2004-07-09 04:04:30 +02:00
// determine next screenshot number.
//
// current approach: increment number until that file doesn't yet exist.
// this is fairly slow, but it's typically only done once, since the last
// number is cached. binary search shouldn't be necessary.
//
// known bug: after program restart, holes in the number series are
// filled first. example: add 1st and 2nd; [exit] delete 1st; [restart]
// add 3rd -> it gets number 1, not 3.
// could fix via enumerating all files, but it's not worth it ATM.
char fn [ VFS_MAX_PATH ] ;
2004-07-17 13:13:21 +02:00
2005-01-09 15:23:59 +01:00
const char * file_format_string = " screenshots/screenshot%04d.%s " ;
// %04d -> always 4 digits, so sorting by filename works correctly.
2004-07-17 13:13:21 +02:00
2004-07-09 04:04:30 +02:00
static int next_num = 1 ;
do
2005-01-09 15:23:59 +01:00
sprintf ( fn , file_format_string , next_num + + , extension ) ;
2004-07-09 04:04:30 +02:00
while ( vfs_exists ( fn ) ) ;
const int w = g_xres , h = g_yres ;
const int bpp = 24 ;
2005-03-10 17:57:42 +01:00
GLenum fmt = GL_RGB ;
int flags = TEX_BOTTOM_UP ;
// we want writing BMP to be as fast as possible,
// so read data from OpenGL in BMP format to obviate conversion.
if ( ! stricmp ( extension , " bmp " ) )
{
fmt = GL_BGR ;
flags | = TEX_BGR ;
}
2004-07-09 04:04:30 +02:00
const size_t size = w * h * bpp ;
void * img = mem_alloc ( size ) ;
2005-01-09 15:23:59 +01:00
glReadPixels ( 0 , 0 , w , h , fmt , GL_UNSIGNED_BYTE , img ) ;
2004-07-09 04:04:30 +02:00
2005-01-09 15:23:59 +01:00
if ( tex_write ( fn , w , h , bpp , flags , img ) < 0 )
2004-07-09 04:04:30 +02:00
debug_warn ( " WriteScreenshot: tex_write failed " ) ;
mem_free ( img ) ;
2004-06-26 00:13:48 +02:00
}
2004-05-24 22:25:48 +02:00
2004-07-09 14:44:12 +02:00
// HACK: Let code from other files (i.e. the scripting system) quit
void kill_mainloop ( )
{
quit = true ;
}
2004-06-26 00:13:48 +02:00
static int handler ( const SDL_Event * ev )
2004-05-24 22:25:48 +02:00
{
int c ;
2004-06-26 00:13:48 +02:00
switch ( ev - > type )
2004-05-24 22:25:48 +02:00
{
2004-07-10 23:33:31 +02:00
case SDL_ACTIVEEVENT :
2004-07-12 18:50:46 +02:00
g_active = ev - > active . gain ! = 0 ;
2004-06-21 16:14:12 +02:00
break ;
2004-07-20 21:30:35 +02:00
case SDL_MOUSEMOTION :
2005-01-23 18:35:36 +01:00
g_mouse_x = ev - > motion . x ;
g_mouse_y = ev - > motion . y ;
2004-07-20 21:30:35 +02:00
break ;
2004-05-24 22:25:48 +02:00
case SDL_KEYDOWN :
2004-06-26 00:13:48 +02:00
c = ev - > key . keysym . sym ;
2004-05-24 22:25:48 +02:00
keys [ c ] = true ;
2004-07-21 18:34:07 +02:00
break ;
case SDL_HOTKEYDOWN :
2004-06-02 22:39:21 +02:00
2004-07-21 18:34:07 +02:00
switch ( ev - > user . code )
2004-05-24 22:25:48 +02:00
{
2004-07-21 18:34:07 +02:00
case HOTKEY_EXIT :
2004-05-24 22:25:48 +02:00
quit = true ;
break ;
2004-06-26 00:13:48 +02:00
2004-07-21 18:34:07 +02:00
case HOTKEY_SCREENSHOT :
2004-07-09 04:04:30 +02:00
WriteScreenshot ( ) ;
2004-06-26 00:13:48 +02:00
break ;
2004-07-21 18:34:07 +02:00
2004-07-28 13:36:16 +02:00
case HOTKEY_PLAYMUSIC :
2004-09-19 17:58:13 +02:00
{
// MusicPlayer.open("audio/music/germanic peace 3.ogg");
// MusicPlayer.play();
2004-10-05 15:14:03 +02:00
Handle hs = snd_open (
2004-09-22 16:01:50 +02:00
//"audio/music/germanic peace 3.ogg"
2004-10-19 15:45:50 +02:00
" audio/voice/hellenes/soldier/Attack-ZeusSaviourandVictory.ogg "
2004-09-22 16:01:50 +02:00
) ;
2004-10-15 15:29:04 +02:00
snd_set_pos ( hs , 0 , 0 , 0 , true ) ;
2004-10-05 15:14:03 +02:00
snd_play ( hs ) ;
2004-09-19 17:58:13 +02:00
}
2004-07-28 13:36:16 +02:00
break ;
2004-07-21 18:34:07 +02:00
default :
return ( EV_PASS ) ;
2004-05-24 22:25:48 +02:00
}
2004-07-21 18:34:07 +02:00
return ( EV_HANDLED ) ;
2004-05-24 22:25:48 +02:00
case SDL_KEYUP :
2004-06-26 00:13:48 +02:00
c = ev - > key . keysym . sym ;
2004-05-24 22:25:48 +02:00
keys [ c ] = false ;
break ;
2004-05-26 00:02:57 +02:00
case SDL_MOUSEBUTTONDOWN :
2004-06-26 00:13:48 +02:00
c = ev - > button . button ;
2004-05-26 00:02:57 +02:00
if ( c < 5 )
mouseButtons [ c ] = true ;
2004-06-21 16:14:12 +02:00
else
debug_warn ( " SDL mouse button defs changed; fix mouseButton array def " ) ;
2004-05-26 00:02:57 +02:00
break ;
case SDL_MOUSEBUTTONUP :
2004-06-26 00:13:48 +02:00
c = ev - > button . button ;
2004-05-26 00:02:57 +02:00
if ( c < 5 )
mouseButtons [ c ] = false ;
2004-06-21 16:14:12 +02:00
else
debug_warn ( " SDL mouse button defs changed; fix mouseButton array def " ) ;
2004-05-26 00:02:57 +02:00
break ;
2004-05-24 22:25:48 +02:00
}
2004-06-26 00:13:48 +02:00
return EV_PASS ;
2004-05-24 22:25:48 +02:00
}
2004-08-05 15:07:51 +02:00
void EndGame ( )
{
2005-01-23 02:36:47 +01:00
if ( g_NetServer )
{
delete g_NetServer ;
g_NetServer = NULL ;
}
else if ( g_NetClient )
{
delete g_NetClient ;
2005-01-28 23:19:09 +01:00
g_NetClient = NULL ;
2005-01-23 02:36:47 +01:00
}
2004-08-05 15:07:51 +02:00
delete g_Game ;
g_Game = NULL ;
}
2004-05-24 22:25:48 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////
// RenderNoCull: render absolutely everything to a blank frame to force renderer
2004-06-07 21:51:52 +02:00
// to load required assets
2004-05-24 22:25:48 +02:00
void RenderNoCull ( )
{
g_Renderer . BeginFrame ( ) ;
2004-07-31 17:57:18 +02:00
2004-08-05 15:07:51 +02:00
if ( g_Game )
g_Game - > GetView ( ) - > RenderNoCull ( ) ;
2004-05-24 22:25:48 +02:00
g_Renderer . FlushFrame ( ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
g_Renderer . EndFrame ( ) ;
}
static void Render ( )
{
2004-07-15 21:12:54 +02:00
MICROLOG ( L " begin frame " ) ;
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2005-01-11 17:58:16 +01:00
# ifndef NO_GUI // HACK: because colour-parsing requires the GUI
2004-12-28 12:16:05 +01:00
CStr skystring = " 61 193 255 " ;
CConfigValue * val ;
if ( ( val = g_ConfigDB . GetValue ( CFG_USER , " skycolor " ) ) )
val - > GetString ( skystring ) ;
CColor skycol ;
GUI < CColor > : : ParseString ( skystring , skycol ) ;
g_Renderer . SetClearColor ( skycol . Int ( ) ) ;
2005-01-11 17:58:16 +01:00
# endif
2004-12-28 12:16:05 +01:00
2004-05-24 22:25:48 +02:00
// start new frame
g_Renderer . BeginFrame ( ) ;
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2005-03-22 03:17:55 +01:00
if ( g_Game & & g_Game - > IsGameStarted ( ) )
2004-05-29 05:32:33 +02:00
{
2004-08-05 15:07:51 +02:00
g_Game - > GetView ( ) - > Render ( ) ;
2004-05-26 22:57:25 +02:00
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2004-08-05 15:07:51 +02:00
MICROLOG ( L " flush frame " ) ;
2005-03-30 18:14:19 +02:00
PROFILE_START ( " flush frame " ) ;
2004-08-05 15:07:51 +02:00
g_Renderer . FlushFrame ( ) ;
2005-03-30 18:14:19 +02:00
PROFILE_END ( " flush frame " ) ;
2004-05-24 22:25:48 +02:00
2004-08-05 15:07:51 +02:00
glPushAttrib ( GL_ENABLE_BIT ) ;
glDisable ( GL_LIGHTING ) ;
glDisable ( GL_TEXTURE_2D ) ;
glDisable ( GL_DEPTH_TEST ) ;
if ( g_EntGraph )
{
2005-03-30 18:14:19 +02:00
PROFILE ( " render entity overlays " ) ;
2004-08-05 15:07:51 +02:00
glColor3f ( 1.0f , 0.0f , 1.0f ) ;
2004-07-20 21:30:35 +02:00
2004-08-05 15:07:51 +02:00
MICROLOG ( L " render entities " ) ;
g_EntityManager . renderAll ( ) ; // <-- collision outlines, pathing routes
}
2005-03-30 18:14:19 +02:00
PROFILE_START ( " render selection " ) ;
2004-08-05 15:07:51 +02:00
g_Mouseover . renderSelectionOutlines ( ) ;
g_Selection . renderSelectionOutlines ( ) ;
2005-03-30 18:14:19 +02:00
PROFILE_END ( " render selection " ) ;
2004-08-05 15:07:51 +02:00
glPopAttrib ( ) ;
}
else
2005-03-30 18:14:19 +02:00
{
PROFILE_START ( " flush frame " ) ;
2004-08-05 15:07:51 +02:00
g_Renderer . FlushFrame ( ) ;
2005-03-30 18:14:19 +02:00
PROFILE_END ( " flush frame " ) ;
}
2004-07-20 21:30:35 +02:00
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2005-03-30 18:14:19 +02:00
PROFILE_START ( " render fonts " ) ;
2004-07-15 21:12:54 +02:00
MICROLOG ( L " render fonts " ) ;
2004-05-24 22:25:48 +02:00
// overlay mode
glPushAttrib ( GL_ENABLE_BIT ) ;
2004-06-16 17:44:24 +02:00
glEnable ( GL_TEXTURE_2D ) ;
2004-05-24 22:25:48 +02:00
glDisable ( GL_CULL_FACE ) ;
2004-06-07 21:51:52 +02:00
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2004-05-24 22:25:48 +02:00
glEnable ( GL_BLEND ) ;
glMatrixMode ( GL_PROJECTION ) ;
glPushMatrix ( ) ;
glLoadIdentity ( ) ;
glOrtho ( 0.f , ( float ) g_xres , 0.f , ( float ) g_yres , - 1.f , 1000.f ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glPushMatrix ( ) ;
2005-03-30 18:14:19 +02:00
PROFILE_END ( " render fonts " ) ;
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2004-07-17 19:51:04 +02:00
# ifndef NO_GUI
// Temp GUI message GeeTODO
glLoadIdentity ( ) ;
MICROLOG ( L " render GUI " ) ;
2005-03-30 18:14:19 +02:00
PROFILE_START ( " render gui " ) ;
2004-07-17 19:51:04 +02:00
g_GUI . Draw ( ) ;
2005-03-30 18:14:19 +02:00
PROFILE_END ( " render gui " ) ;
2004-07-17 19:51:04 +02:00
# endif
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2004-07-17 19:51:04 +02:00
// Text:
2004-05-24 22:25:48 +02:00
2004-06-16 17:44:24 +02:00
// Use the GL_ALPHA texture as the alpha channel with a flat colouring
glDisable ( GL_ALPHA_TEST ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
2004-09-03 07:49:20 +02:00
// Added --
glEnable ( GL_TEXTURE_2D ) ;
// -- GL
2004-06-16 17:44:24 +02:00
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2004-08-28 00:08:30 +02:00
{
2005-03-30 18:14:19 +02:00
PROFILE ( " render console " ) ;
2004-08-28 00:08:30 +02:00
glLoadIdentity ( ) ;
MICROLOG ( L " render console " ) ;
CFont font ( " console " ) ;
font . Bind ( ) ;
g_Console - > Render ( ) ;
}
2004-05-26 22:57:25 +02:00
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2005-03-30 18:14:19 +02:00
// Profile information
PROFILE_START ( " render profiling " ) ;
RenderProfile ( ) ;
PROFILE_END ( " render profiling " ) ;
oglCheck ( ) ;
2005-03-26 00:04:36 +01:00
if ( g_Game & & g_Game - > IsGameStarted ( ) )
2004-08-05 15:07:51 +02:00
{
2005-03-30 18:14:19 +02:00
PROFILE ( " render selection overlays " ) ;
2004-08-05 15:07:51 +02:00
g_Mouseover . renderOverlays ( ) ;
g_Selection . renderOverlays ( ) ;
}
2004-07-20 21:30:35 +02:00
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2004-07-24 21:38:12 +02:00
// Draw the cursor (or set the Windows cursor, on Windows)
2004-07-31 14:45:30 +02:00
cursor_draw ( g_CursorName ) ;
2004-07-24 21:38:12 +02:00
2004-05-24 22:25:48 +02:00
// restore
glMatrixMode ( GL_PROJECTION ) ;
glPopMatrix ( ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glPopMatrix ( ) ;
glPopAttrib ( ) ;
2004-07-15 21:12:54 +02:00
MICROLOG ( L " end frame " ) ;
2004-05-24 22:25:48 +02:00
g_Renderer . EndFrame ( ) ;
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2004-05-24 22:25:48 +02:00
}
2004-10-23 16:39:28 +02:00
static void LoadProfile ( CStr profile )
{
2005-05-10 09:13:25 +02:00
CStr base = CStr ( " profiles/ " ) + profile ;
g_ConfigDB . SetConfigFile ( CFG_USER , true , base + " /settings/user.cfg " ) ;
2004-10-23 16:39:28 +02:00
g_ConfigDB . Reload ( CFG_USER ) ;
2005-05-10 09:13:25 +02:00
int history_size = 50 ;
CConfigValue * config_value = g_ConfigDB . GetValue ( CFG_USER , " console.history.size " ) ;
if ( config_value )
config_value - > GetInt ( history_size ) ;
g_Console - > UseHistoryFile ( base + " /settings/history " , ( history_size > = 0 ) ? history_size : 50 ) ;
2004-10-23 16:39:28 +02:00
}
// Fill in the globals from the config files.
static void LoadGlobals ( )
{
CConfigValue * val ;
if ( ( val = g_ConfigDB . GetValue ( CFG_SYSTEM , " profile " ) ) )
val - > GetString ( g_ActiveProfile ) ;
// Now load the profile before trying to retrieve the values of the rest of these.
LoadProfile ( g_ActiveProfile ) ;
if ( ( val = g_ConfigDB . GetValue ( CFG_USER , " xres " ) ) )
val - > GetInt ( g_xres ) ;
if ( ( val = g_ConfigDB . GetValue ( CFG_USER , " yres " ) ) )
val - > GetInt ( g_yres ) ;
if ( ( val = g_ConfigDB . GetValue ( CFG_USER , " vsync " ) ) )
val - > GetBool ( g_VSync ) ;
if ( ( val = g_ConfigDB . GetValue ( CFG_USER , " novbo " ) ) )
val - > GetBool ( g_NoGLVBO ) ;
if ( ( val = g_ConfigDB . GetValue ( CFG_USER , " shadows " ) ) )
val - > GetBool ( g_Shadows ) ;
2004-11-30 16:52:10 +01:00
2005-03-09 01:55:22 +01:00
if ( ( val = g_ConfigDB . GetValue ( CFG_USER , " lodbias " ) ) )
val - > GetFloat ( g_LodBias ) ;
2005-02-26 22:44:21 +01:00
if ( ( val = g_ConfigDB . GetValue ( CFG_USER , " sound.mastergain " ) ) )
{
float gain ;
val - > GetFloat ( gain ) ;
int ret = snd_set_master_gain ( gain ) ;
assert2 ( ret = = 0 ) ;
}
2004-10-23 16:39:28 +02:00
LOG ( NORMAL , LOG_CATEGORY , " g_x/yres is %dx%d " , g_xres , g_yres ) ;
2004-11-07 22:30:47 +01:00
LOG ( NORMAL , LOG_CATEGORY , " Active profile is %s " , g_ActiveProfile . c_str ( ) ) ;
2004-10-23 16:39:28 +02:00
}
2004-08-02 14:53:49 +02:00
static void ParseArgs ( int argc , char * argv [ ] )
2004-05-24 22:25:48 +02:00
{
2004-08-02 14:53:49 +02:00
for ( int i = 1 ; i < argc ; i + + )
{
// this arg isn't an option; skip
if ( argv [ i ] [ 0 ] ! = ' - ' )
continue ;
2004-05-29 23:04:18 +02:00
2004-08-02 14:53:49 +02:00
char * name = argv [ i ] + 1 ; // no leading '-'
2004-06-07 21:51:52 +02:00
2004-08-02 14:53:49 +02:00
// switch first letter of option name
switch ( argv [ i ] [ 1 ] )
{
case ' c ' :
if ( strcmp ( name , " conf " ) = = 0 )
{
if ( argc - i > = 1 ) // at least one arg left
{
i + + ;
char * arg = argv [ i ] ;
char * equ = strchr ( arg , ' = ' ) ;
if ( equ )
{
* equ = 0 ;
2004-10-23 16:39:28 +02:00
g_ConfigDB . CreateValue ( CFG_COMMAND , arg )
2004-08-02 14:53:49 +02:00
- > m_String = ( equ + 1 ) ;
2004-06-09 16:10:31 +02:00
}
2004-08-02 14:53:49 +02:00
}
2004-05-24 22:25:48 +02:00
}
2004-08-02 14:53:49 +02:00
break ;
case ' e ' :
g_EntGraph = true ;
break ;
case ' f ' :
if ( strncmp ( name , " fixedframe " , 10 ) = = 0 )
g_FixedFrameTiming = true ;
break ;
case ' g ' :
if ( strncmp ( name , " g= " , 2 ) = = 0 )
{
g_Gamma = ( float ) atof ( argv [ i ] + 3 ) ;
if ( g_Gamma = = 0.0f )
g_Gamma = 1.0f ;
}
break ;
2004-11-07 23:46:57 +01:00
case ' l ' :
if ( strncmp ( name , " listfiles " , 9 ) = = 0 )
vfs_enable_file_listing ( true ) ;
break ;
2004-08-02 14:53:49 +02:00
case ' n ' :
if ( strncmp ( name , " novbo " , 5 ) = = 0 )
2004-10-23 16:39:28 +02:00
g_ConfigDB . CreateValue ( CFG_COMMAND , " novbo " ) - > m_String = " true " ;
2004-08-02 14:53:49 +02:00
else if ( strncmp ( name , " nopbuffer " , 9 ) = = 0 )
g_NoPBuffer = true ;
break ;
2004-11-19 23:58:01 +01:00
case ' q ' :
if ( strncmp ( name , " quickstart " , 10 ) = = 0 )
g_Quickstart = true ;
break ;
2004-08-02 14:53:49 +02:00
case ' s ' :
if ( strncmp ( name , " shadows " , 7 ) = = 0 )
2004-10-23 16:39:28 +02:00
g_ConfigDB . CreateValue ( CFG_COMMAND , " shadows " ) - > m_String = " true " ;
2004-08-02 14:53:49 +02:00
break ;
case ' v ' :
2004-10-23 16:39:28 +02:00
g_ConfigDB . CreateValue ( CFG_COMMAND , " vsync " ) - > m_String = " true " ;
2004-08-02 14:53:49 +02:00
break ;
case ' x ' :
if ( strncmp ( name , " xres= " , 6 ) = = 0 )
2004-10-23 16:39:28 +02:00
g_ConfigDB . CreateValue ( CFG_COMMAND , " xres " ) - > m_String = argv [ i ] + 6 ;
2004-08-02 14:53:49 +02:00
break ;
case ' y ' :
if ( strncmp ( name , " yres= " , 6 ) = = 0 )
2004-10-23 16:39:28 +02:00
g_ConfigDB . CreateValue ( CFG_COMMAND , " yres " ) - > m_String = argv [ i ] + 6 ;
break ;
case ' p ' :
if ( strncmp ( name , " profile= " , 8 ) = = 0 )
g_ConfigDB . CreateValue ( CFG_COMMAND , " profile " ) - > m_String = argv [ i ] + 9 ;
2004-08-02 14:53:49 +02:00
break ;
} // switch
2004-05-24 22:25:48 +02:00
}
2004-08-02 14:53:49 +02:00
2004-10-23 16:39:28 +02:00
2004-05-24 22:25:48 +02:00
}
2004-07-12 18:50:46 +02:00
static void InitScripting ( )
{
2004-12-08 16:34:15 +01:00
TIMER ( InitScripting )
2004-07-12 18:50:46 +02:00
// Create the scripting host. This needs to be done before the GUI is created.
new ScriptingHost ;
2004-07-20 21:30:35 +02:00
// It would be nice for onLoad code to be able to access the setTimeout() calls.
new CScheduler ;
2004-07-12 18:50:46 +02:00
// Register the JavaScript interfaces with the runtime
2004-10-07 21:23:35 +02:00
CEntity : : ScriptingInit ( ) ;
CBaseEntity : : ScriptingInit ( ) ;
2004-11-15 19:23:39 +01:00
JSI_Sound : : ScriptingInit ( ) ;
2005-03-30 18:14:19 +02:00
CProfileNode : : ScriptingInit ( ) ;
2005-01-11 17:58:16 +01:00
# ifndef NO_GUI
2004-07-12 18:50:46 +02:00
JSI_IGUIObject : : init ( ) ;
JSI_GUITypes : : init ( ) ;
2005-01-11 17:58:16 +01:00
# endif
2004-07-12 18:50:46 +02:00
JSI_Vector3D : : init ( ) ;
2004-10-07 21:23:35 +02:00
EntityCollection : : Init ( " EntityCollection " ) ;
2005-01-18 01:46:18 +01:00
SColour : : ScriptingInit ( ) ;
CPlayer : : ScriptingInit ( ) ;
PlayerCollection : : Init ( " PlayerCollection " ) ;
2004-11-11 08:09:32 +01:00
CDamageType : : ScriptingInit ( ) ;
2005-04-22 09:12:55 +02:00
CJSComplexPropertyAccessor < CEntity > : : ScriptingInit ( ) ; // <-- Doesn't really matter which we use, but we know CJSPropertyAccessor<T> is already being compiled for T = CEntity.
2004-10-23 16:39:28 +02:00
CScriptEvent : : ScriptingInit ( ) ;
2005-04-15 06:23:33 +02:00
CJSProgressTimer : : ScriptingInit ( ) ;
2005-05-10 09:13:25 +02:00
CProjectile : : ScriptingInit ( ) ;
2004-10-07 21:23:35 +02:00
2004-11-11 08:09:32 +01:00
g_ScriptingHost . DefineConstant ( " ORDER_NONE " , - 1 ) ;
g_ScriptingHost . DefineConstant ( " ORDER_GOTO " , CEntityOrder : : ORDER_GOTO ) ;
g_ScriptingHost . DefineConstant ( " ORDER_PATROL " , CEntityOrder : : ORDER_PATROL ) ;
g_ScriptingHost . DefineConstant ( " ORDER_ATTACK " , CEntityOrder : : ORDER_ATTACK_MELEE ) ;
2005-04-15 06:23:33 +02:00
g_ScriptingHost . DefineConstant ( " ORDER_GATHER " , CEntityOrder : : ORDER_GATHER ) ;
2004-11-11 08:09:32 +01:00
2004-08-03 01:14:54 +02:00
JSI_Camera : : init ( ) ;
JSI_Console : : init ( ) ;
2005-04-22 09:12:55 +02:00
new CGameEvents ;
2004-07-12 18:50:46 +02:00
}
2004-08-02 14:53:49 +02:00
2005-03-18 23:19:38 +01:00
static void InitVfs ( const char * argv0 )
2004-07-12 18:50:46 +02:00
{
2004-12-08 16:34:15 +01:00
TIMER ( InitVfs )
2004-07-12 18:50:46 +02:00
// set current directory to "$game_dir/data".
// this is necessary because it is otherwise unknown,
// especially if run from a shortcut / symlink.
//
// "../data" is relative to the executable (in "$game_dir/system").
//
// rationale for data/ being root: untrusted scripts must not be
// allowed to overwrite critical game (or worse, OS) files.
// the VFS prevents any accesses to files above this directory.
int err = file_rel_chdir ( argv0 , " ../data " ) ;
if ( err < 0 )
throw err ;
2004-12-09 21:17:09 +01:00
2004-07-12 18:50:46 +02:00
/ / display_startup_error ( L " error setting current directory. \n " \
// L"argv[0] is probably incorrect. please start the game via command-line.");
2005-03-27 03:47:36 +02:00
{
TIMER ( VFS_INIT ) ;
vfs_init ( ) ;
2005-04-29 15:17:17 +02:00
vfs_mount ( " " , " mods/official " , VFS_MOUNT_RECURSIVE | VFS_MOUNT_ARCHIVES | VFS_MOUNT_WATCH ) ;
2005-01-10 19:44:41 +01:00
vfs_mount ( " screenshots/ " , " screenshots " ) ;
2005-05-10 09:13:25 +02:00
vfs_mount ( " profiles/ " , " profiles " , VFS_MOUNT_RECURSIVE ) ;
2005-03-27 03:47:36 +02:00
}
/*
double t0 = get_time ( ) ;
for ( int i = 0 ; i < 30 * 4 * 5 ; i + + )
{
TIMER ( rebuild ) ;
vfs_rebuild ( ) ;
}
2005-05-11 20:56:30 +02:00
debug_printf ( " %f \n \n \n " , get_time ( ) - t0 ) ;
2005-03-27 03:47:36 +02:00
exit ( 1134 ) ;
/**/
2004-12-07 02:22:25 +01:00
// don't try vfs_display yet: SDL_Init hasn't yet redirected stdout
2004-07-12 18:50:46 +02:00
}
2004-12-08 16:34:15 +01:00
static void InitPs ( )
2004-06-21 16:14:12 +02:00
{
2004-09-22 16:01:50 +02:00
// console
2004-08-28 00:08:30 +02:00
{
2004-12-08 16:34:15 +01:00
TIMER ( ps_console )
2004-09-22 16:01:50 +02:00
float ConsoleHeight = g_yres * 0.6f ;
g_Console - > SetSize ( 0 , g_yres - ConsoleHeight , ( float ) g_xres , ConsoleHeight ) ;
2004-08-28 00:08:30 +02:00
// Calculate and store the line spacing
CFont font ( " console " ) ;
g_Console - > m_iFontHeight = font . GetLineSpacing ( ) ;
// Offset by an arbitrary amount, to make it fit more nicely
g_Console - > m_iFontOffset = 9 ;
}
2004-06-21 16:14:12 +02:00
2004-12-08 16:34:15 +01:00
// language and hotkeys
{
TIMER ( ps_lang_hotkeys )
2004-08-21 13:45:01 +02:00
2004-12-08 16:34:15 +01:00
CConfigValue * val = g_ConfigDB . GetValue ( CFG_SYSTEM , " language " ) ;
std : : string lang = " english " ;
if ( val )
val - > GetString ( lang ) ;
I18n : : LoadLanguage ( lang . c_str ( ) ) ;
2004-07-22 18:18:12 +02:00
2004-12-08 16:34:15 +01:00
loadHotkeys ( ) ;
}
2004-07-08 17:22:09 +02:00
2004-12-08 16:34:15 +01:00
# ifndef NO_GUI
{
// GUI uses VFS, so this must come after VFS init.
{ TIMER ( ps_gui_init )
g_GUI . Initialize ( ) ; }
{ TIMER ( ps_gui_setup_xml )
g_GUI . LoadXMLFile ( " gui/test/setup.xml " ) ; }
{ TIMER ( ps_gui_styles_xml )
g_GUI . LoadXMLFile ( " gui/test/styles.xml " ) ; }
{ TIMER ( ps_gui_sprite1_xml )
g_GUI . LoadXMLFile ( " gui/test/sprite1.xml " ) ; }
}
2004-10-07 23:06:08 +02:00
// Temporary hack until revised GUI structure is completed.
2004-12-08 16:34:15 +01:00
{
// TIMER(ps_gui_hack)
{ TIMER ( ps_gui_1 )
g_GUI . LoadXMLFile ( " gui/test/1_init.xml " ) ; }
{ TIMER ( ps_gui_2 )
g_GUI . LoadXMLFile ( " gui/test/2_mainmenu.xml " ) ; }
{ TIMER ( ps_gui_3 )
2004-12-12 20:34:38 +01:00
g_GUI . LoadXMLFile ( " gui/test/3_loading.xml " ) ; }
2004-12-08 16:34:15 +01:00
{ TIMER ( ps_gui_4 )
2004-12-12 20:34:38 +01:00
g_GUI . LoadXMLFile ( " gui/test/4_session.xml " ) ; }
2004-12-08 16:34:15 +01:00
{ TIMER ( ps_gui_6 )
2004-12-12 20:34:38 +01:00
g_GUI . LoadXMLFile ( " gui/test/6_subwindows.xml " ) ; }
2005-05-03 00:04:29 +02:00
{ TIMER ( ps_gui_6_1 )
g_GUI . LoadXMLFile ( " gui/test/6_1_manual.xml " ) ; }
{ TIMER ( ps_gui_6_2 )
g_GUI . LoadXMLFile ( " gui/test/6_2_jukebox.xml " ) ; }
2004-12-12 20:34:38 +01:00
{ TIMER ( ps_gui_7 )
g_GUI . LoadXMLFile ( " gui/test/7_atlas.xml " ) ; }
{ TIMER ( ps_gui_9 )
g_GUI . LoadXMLFile ( " gui/test/9_global.xml " ) ; }
2004-12-08 16:34:15 +01:00
}
2004-12-12 20:34:38 +01:00
// {
// TIMER(ps_gui_hello_xml)
// g_GUI.LoadXMLFile("gui/test/hello.xml");
// }
2004-06-21 16:14:12 +02:00
# endif
}
static void psShutdown ( )
{
# ifndef NO_GUI
g_GUI . Destroy ( ) ;
delete & g_GUI ;
# endif
delete g_Console ;
2004-07-24 21:38:12 +02:00
// disable the special Windows cursor, or free textures for OGL cursors
cursor_draw ( NULL ) ;
2004-07-08 17:22:09 +02:00
// close down Xerces if it was loaded
CXeromyces : : Terminate ( ) ;
2004-07-28 13:36:16 +02:00
MusicPlayer . release ( ) ;
2004-08-21 13:45:01 +02:00
2004-08-24 13:32:32 +02:00
// Unload the real language (since it depends on the scripting engine,
// which is going to be killed later) and use the English fallback messages
I18n : : LoadLanguage ( NULL ) ;
2004-06-21 16:14:12 +02:00
}
2004-07-12 18:50:46 +02:00
2004-12-08 16:34:15 +01:00
static void InitConfig ( int argc , char * argv [ ] )
{
TIMER ( InitConfig )
MICROLOG ( L " init config " ) ;
new CConfigDB ;
g_ConfigDB . SetConfigFile ( CFG_SYSTEM , false , " config/system.cfg " ) ;
g_ConfigDB . Reload ( CFG_SYSTEM ) ;
g_ConfigDB . SetConfigFile ( CFG_MOD , true , " config/mod.cfg " ) ;
// No point in reloading mod.cfg here - we haven't mounted mods yet
ParseArgs ( argc , argv ) ;
LoadGlobals ( ) ; // Collects information from system.cfg, the profile file, and any command-line overrides
// to fill in the globals.
}
static void InitRenderer ( )
{
TIMER ( InitRenderer )
// create renderer
new CRenderer ;
// set renderer options from command line options - NOVBO must be set before opening the renderer
g_Renderer . SetOptionBool ( CRenderer : : OPT_NOVBO , g_NoGLVBO ) ;
g_Renderer . SetOptionBool ( CRenderer : : OPT_SHADOWS , g_Shadows ) ;
g_Renderer . SetOptionBool ( CRenderer : : OPT_NOPBUFFER , g_NoPBuffer ) ;
g_Renderer . SetOptionFloat ( CRenderer : : OPT_LODBIAS , g_LodBias ) ;
// create terrain related stuff
new CTextureManager ;
// create the material manager
new CMaterialManager ;
new CMeshManager ;
// create actor related stuff
new CSkeletonAnimManager ;
new CObjectManager ;
new CUnitManager ;
MICROLOG ( L " init renderer " ) ;
g_Renderer . Open ( g_xres , g_yres , g_bpp ) ;
// Setup default lighting environment. Since the Renderer accesses the
// lighting environment through a pointer, this has to be done before
// the first Frame.
g_LightEnv . m_SunColor = RGBColor ( 1 , 1 , 1 ) ;
g_LightEnv . SetRotation ( DEGTORAD ( 270 ) ) ;
g_LightEnv . SetElevation ( DEGTORAD ( 45 ) ) ;
g_LightEnv . m_TerrainAmbientColor = RGBColor ( 0 , 0 , 0 ) ;
g_LightEnv . m_UnitsAmbientColor = RGBColor ( 0.4f , 0.4f , 0.4f ) ;
g_Renderer . SetLightEnv ( & g_LightEnv ) ;
// I haven't seen the camera affecting GUI rendering and such, but the
// viewport has to be updated according to the video mode
SViewPort vp ;
vp . m_X = 0 ;
vp . m_Y = 0 ;
vp . m_Width = g_xres ;
vp . m_Height = g_yres ;
g_Renderer . SetViewport ( vp ) ;
}
2005-03-22 03:17:55 +01:00
static int ProgressiveLoad ( )
{
wchar_t description [ 100 ] ;
int progress_percent ;
2005-03-27 03:47:36 +02:00
int ret = LDR_ProgressiveLoad ( 10e-3 , description , ARRAY_SIZE ( description ) , & progress_percent ) ;
2005-03-22 03:17:55 +01:00
switch ( ret )
{
// no load active => no-op (skip code below)
2005-05-11 06:39:21 +02:00
case 0 :
return 0 ;
2005-03-22 22:00:56 +01:00
// current task didn't complete. we only care about this insofar as the
// load process is therefore not yet finished.
2005-03-22 03:17:55 +01:00
case ERR_TIMED_OUT :
break ;
// just finished loading
2005-05-11 06:39:21 +02:00
case LDR_ALL_FINISHED :
2005-03-22 03:17:55 +01:00
g_Game - > ReallyStartGame ( ) ;
wcscpy_s ( description , ARRAY_SIZE ( description ) , L " Game is starting.. " ) ;
// LDR_ProgressiveLoad returns L""; set to valid text to
// avoid problems in converting to JSString
break ;
// error!
default :
CHECK_ERR ( ret ) ;
// can't do this above due to legit ERR_TIMED_OUT
break ;
}
2005-03-23 00:31:30 +01:00
# ifndef NO_GUI
2005-03-22 03:17:55 +01:00
// display progress / description in loading screen
CStrW i18n_description = translate ( description ) ;
JSString * js_desc = StringConvert : : wstring_to_jsstring ( g_ScriptingHost . getContext ( ) , i18n_description ) ;
g_ScriptingHost . SetGlobal ( " g_Progress " , INT_TO_JSVAL ( progress_percent ) ) ;
g_ScriptingHost . SetGlobal ( " g_LoadDescription " , STRING_TO_JSVAL ( js_desc ) ) ;
g_GUI . SendEventToAll ( " progress " ) ;
2005-03-23 00:31:30 +01:00
# endif
2005-03-22 03:17:55 +01:00
return 0 ;
}
2005-01-27 16:50:11 +01:00
u64 PREVTSC ;
2004-07-12 18:50:46 +02:00
static void Shutdown ( )
{
psShutdown ( ) ; // Must delete g_GUI before g_ScriptingHost
2004-08-05 15:07:51 +02:00
if ( g_Game )
2005-01-23 02:36:47 +01:00
EndGame ( ) ;
2004-08-21 13:45:01 +02:00
2004-07-20 21:30:35 +02:00
delete & g_Scheduler ;
2004-08-16 17:19:17 +02:00
delete & g_SessionManager ;
2004-07-20 21:30:35 +02:00
delete & g_Mouseover ;
delete & g_Selection ;
2004-07-12 18:50:46 +02:00
delete & g_Pathfinder ;
2004-08-05 15:07:51 +02:00
// Managed by CWorld
// delete &g_EntityManager;
2004-10-07 21:23:35 +02:00
2005-01-19 23:32:25 +01:00
delete & g_GameAttributes ;
2005-04-22 09:12:55 +02:00
delete & g_JSGameEvents ;
2005-01-19 23:32:25 +01:00
2004-07-12 18:50:46 +02:00
delete & g_EntityTemplateCollection ;
2004-10-07 21:23:35 +02:00
delete & g_ScriptingHost ;
2004-07-12 18:50:46 +02:00
// destroy actor related stuff
delete & g_UnitMan ;
delete & g_ObjMan ;
delete & g_SkelAnimMan ;
2004-09-23 14:42:37 +02:00
delete & g_MaterialManager ;
2004-11-26 22:34:35 +01:00
delete & g_MeshManager ;
2004-09-23 14:42:37 +02:00
2004-07-12 18:50:46 +02:00
// destroy terrain related stuff
delete & g_TexMan ;
// destroy renderer
delete & g_Renderer ;
delete & g_ConfigDB ;
2004-08-24 13:32:32 +02:00
2005-01-29 17:51:13 +01:00
// Shut down the network loop
CSocketBase : : Shutdown ( ) ;
2004-08-24 13:32:32 +02:00
// Really shut down the i18n system. Any future calls
// to translate() will crash.
I18n : : Shutdown ( ) ;
2004-10-15 15:29:04 +02:00
snd_shutdown ( ) ;
2004-10-21 01:16:38 +02:00
2004-12-07 23:10:46 +01:00
vfs_shutdown ( ) ;
2004-10-21 01:16:38 +02:00
h_mgr_shutdown ( ) ;
2005-01-07 01:52:05 +01:00
mem_shutdown ( ) ;
2004-07-12 18:50:46 +02:00
}
2005-01-11 17:58:16 +01:00
static void Init ( int argc , char * argv [ ] , bool setup_gfx = true )
2004-05-24 22:25:48 +02:00
{
2004-12-08 16:34:15 +01:00
# ifdef _WIN32
sle ( 11340106 ) ;
# endif
2004-07-15 21:12:54 +02:00
MICROLOG ( L " In init " ) ;
2004-07-10 16:14:36 +02:00
// If you ever want to catch a particular allocation:
2005-02-05 00:16:42 +01:00
//_CrtSetBreakAlloc(187);
2004-07-10 16:14:36 +02:00
2004-06-08 22:41:28 +02:00
# ifdef _MSC_VER
u64 TSC = rdtsc ( ) ;
2005-05-11 20:56:30 +02:00
debug_printf (
2004-06-08 22:41:28 +02:00
" ---------------------------------------- \n " \
2005-04-29 15:17:17 +02:00
" INITIALIZING \n " \
2005-03-18 23:19:38 +01:00
" ---------------------------------------- \n " ) ;
2004-06-08 22:41:28 +02:00
PREVTSC = TSC ;
# endif
2005-04-29 15:17:17 +02:00
// set 24 bit (float) FPU precision for faster divides / sqrts
# ifdef _M_IX86
_control87 ( _PC_24 , _MCW_PC ) ;
# endif
// detects CPU clock frequency and capabilities, which are prerequisites
// for using the TSC as a timer (desirable due to its high resolution).
// do this before lengthy init so we can time those accurately.
get_cpu_info ( ) ;
2004-08-24 13:32:32 +02:00
// Call LoadLanguage(NULL) to initialise the I18n system, but
// without loading an actual language file - translate() will
// just show the English key text, which is better than crashing
// from a null pointer when attempting to translate e.g. error messages.
// Real languages can only be loaded when the scripting system has
// been initialised.
MICROLOG ( L " init i18n " ) ;
I18n : : LoadLanguage ( NULL ) ;
2004-07-19 21:03:33 +02:00
// Do this as soon as possible, because it chdirs
// and will mess up the error reporting if anything
// crashes before the working directory is set.
MICROLOG ( L " init vfs " ) ;
2005-03-18 23:19:38 +01:00
const char * argv0 = argc ? argv [ 0 ] : NULL ;
2005-03-19 00:04:29 +01:00
// ScEd doesn't have a main(argc, argv), and so it has no argv. In that
// case, just pass NULL to InitVfs, which will work out the current
// directory for itself.
2005-03-18 23:19:38 +01:00
InitVfs ( argv0 ) ;
2004-07-19 21:03:33 +02:00
2004-07-11 18:03:26 +02:00
// Set up the console early, so that debugging
// messages can be logged to it. (The console's size
2004-12-08 16:34:15 +01:00
// and fonts are set later in InitPs())
2004-07-11 18:03:26 +02:00
g_Console = new CConsole ( ) ;
2005-01-11 17:58:16 +01:00
if ( setup_gfx )
2004-07-19 21:03:33 +02:00
{
2005-01-11 17:58:16 +01:00
MICROLOG ( L " init sdl " ) ;
// init SDL
if ( SDL_Init ( SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE ) < 0 )
{
LOG ( ERROR , LOG_CATEGORY , " SDL library initialization failed: %s " , SDL_GetError ( ) ) ;
throw PSERROR_System_SDLInitFailed ( ) ;
}
atexit ( SDL_Quit ) ;
SDL_EnableUNICODE ( 1 ) ;
2004-07-19 21:03:33 +02:00
}
2004-05-27 19:30:06 +02:00
2004-06-09 16:10:31 +02:00
// preferred video mode = current desktop settings
// (command line params may override these)
get_cur_vmode ( & g_xres , & g_yres , & g_bpp , & g_freq ) ;
2004-05-27 19:30:06 +02:00
2004-07-15 21:12:54 +02:00
MICROLOG ( L " init scripting " ) ;
2004-07-12 18:50:46 +02:00
InitScripting ( ) ; // before GUI
2004-07-14 14:26:49 +02:00
2004-12-08 16:34:15 +01:00
// g_ConfigDB, command line args, globals
InitConfig ( argc , argv ) ;
2004-07-09 04:04:30 +02:00
2004-05-24 22:25:48 +02:00
// GUI is notified in set_vmode, so this must come before that.
# ifndef NO_GUI
new CGUI ;
# endif
2004-07-10 23:33:31 +02:00
CConfigValue * val = g_ConfigDB . GetValue ( CFG_SYSTEM , " windowed " ) ;
bool windowed = false ;
if ( val ) val - > GetBool ( windowed ) ;
2004-07-14 14:26:49 +02:00
# ifdef _WIN32
2004-07-12 18:50:46 +02:00
sle ( 11340106 ) ;
2004-07-14 14:26:49 +02:00
# endif
2004-07-12 18:50:46 +02:00
2005-01-11 17:58:16 +01:00
if ( setup_gfx )
2004-07-19 21:03:33 +02:00
{
2005-01-11 17:58:16 +01:00
MICROLOG ( L " set vmode " ) ;
if ( set_vmode ( g_xres , g_yres , 32 , ! windowed ) < 0 )
{
LOG ( ERROR , LOG_CATEGORY , " Could not set %dx%d graphics mode: %s " , g_xres , g_yres , SDL_GetError ( ) ) ;
throw PSERROR_System_VmodeFailed ( ) ;
}
SDL_WM_SetCaption ( " 0 A.D. " , " 0 A.D. " ) ;
2004-07-19 21:03:33 +02:00
}
2004-11-19 23:58:01 +01:00
if ( ! g_Quickstart )
2004-12-07 02:22:25 +01:00
{
2004-11-19 23:58:01 +01:00
WriteSysInfo ( ) ;
2005-03-29 22:50:04 +02:00
vfs_display ( ) ;
2004-12-07 02:22:25 +01:00
}
2004-12-01 23:19:58 +01:00
else
2005-04-29 15:17:17 +02:00
{
2004-12-01 23:19:58 +01:00
// speed up startup by disabling all sound
// (OpenAL init will be skipped).
// must be called before first snd_open.
snd_disable ( true ) ;
2005-04-29 15:17:17 +02:00
}
2004-05-24 22:25:48 +02:00
2005-03-10 17:57:42 +01:00
if ( ! oglHaveExtension ( " GL_ARB_multitexture " ) | | ! oglHaveExtension ( " GL_ARB_texture_env_combine " ) | |
2004-08-25 13:44:11 +02:00
! glActiveTexture ) // prevent crashing later if multitexture support is falsely
// advertised (janwas 2004-08-25, for bug #18)
2004-07-19 21:03:33 +02:00
{
2004-08-15 22:57:31 +02:00
LOG ( ERROR , LOG_CATEGORY , " Required ARB_multitexture or ARB_texture_env_combine extension not available " ) ;
2004-07-19 21:03:33 +02:00
throw PSERROR_System_RequiredExtensionsMissing ( ) ;
}
2004-05-24 22:25:48 +02:00
// enable/disable VSync
// note: "GL_EXT_SWAP_CONTROL" is "historical" according to dox.
2005-03-10 17:57:42 +01:00
if ( oglHaveExtension ( " WGL_EXT_swap_control " ) )
2005-03-09 01:55:22 +01:00
wglSwapIntervalEXT ( g_VSync ? 1 : 0 ) ;
2004-05-24 22:25:48 +02:00
2004-07-15 21:12:54 +02:00
MICROLOG ( L " init ps " ) ;
2004-12-08 16:34:15 +01:00
InitPs ( ) ;
2004-06-02 22:39:21 +02:00
2004-12-08 16:34:15 +01:00
InitRenderer ( ) ;
2004-05-29 23:04:18 +02:00
2004-12-08 16:34:15 +01:00
TIMER ( init_after_InitRenderer ) ;
2004-08-05 15:07:51 +02:00
2004-05-24 22:25:48 +02:00
// This needs to be done after the renderer has loaded all its actors...
new CBaseEntityCollection ;
2004-08-05 15:07:51 +02:00
// CEntityManager is managed by CWorld
//new CEntityManager;
2004-05-29 05:32:33 +02:00
new CPathfindEngine ;
2004-07-20 21:30:35 +02:00
new CSelectedEntities ;
new CMouseoverEntities ;
2004-05-24 22:25:48 +02:00
2004-08-16 17:19:17 +02:00
new CSessionManager ;
2005-01-19 23:32:25 +01:00
new CGameAttributes ;
2004-08-16 17:19:17 +02:00
// Register a few Game/Network JS globals
2005-01-19 23:32:25 +01:00
g_ScriptingHost . SetGlobal ( " g_GameAttributes " , OBJECT_TO_JSVAL ( g_GameAttributes . GetScript ( ) ) ) ;
2004-08-16 17:19:17 +02:00
2004-07-21 14:28:23 +02:00
// Check for heap corruption after every allocation. Very, very slowly.
// (And it highlights the allocation just after the one you care about,
// so you need to run it again and tell it to break on the one before.)
/*
extern void memory_debug_extreme_turbo_plus ( ) ;
memory_debug_extreme_turbo_plus ( ) ;
_CrtSetBreakAlloc ( 36367 ) ;
//*/
2004-12-08 16:34:15 +01:00
// register input handlers
{
2005-02-05 08:25:41 +01:00
// This stack is constructed so the first added, will be the last
// one called. This is important, because each of the handlers
// has the potential to block events to go further down
// in the chain. I.e. the last one in the list added, is the
// only handler that can block all messages before they are
// processed.
2004-12-08 16:34:15 +01:00
in_add_handler ( game_view_handler ) ;
2004-05-24 22:25:48 +02:00
2004-12-08 16:34:15 +01:00
in_add_handler ( interactInputHandler ) ;
2004-07-20 21:30:35 +02:00
2005-02-05 08:25:41 +01:00
in_add_handler ( conInputHandler ) ;
2005-03-30 18:14:19 +02:00
in_add_handler ( profilehandler ) ;
in_add_handler ( hotkeyInputHandler ) ;
2005-02-05 08:25:41 +01:00
// I don't know how much this screws up, but the gui_handler needs
// to be after the hotkey, so that input boxes can be typed in
// without setting off hotkeys.
2004-07-20 21:30:35 +02:00
# ifndef NO_GUI
2004-12-08 16:34:15 +01:00
in_add_handler ( gui_handler ) ;
2004-07-20 21:30:35 +02:00
# endif
2005-02-05 08:25:41 +01:00
in_add_handler ( handler ) ; // must be after gui_handler. Should mayhap even be last.
2004-12-08 16:34:15 +01:00
}
2004-06-02 22:39:21 +02:00
2005-01-04 22:51:23 +01:00
# ifndef NO_GUI
g_GUI . SendEventToAll ( " load " ) ;
# endif
2005-01-11 17:58:16 +01:00
if ( setup_gfx )
{
MICROLOG ( L " render blank " ) ;
// render everything to a blank frame to force renderer to load everything
RenderNoCull ( ) ;
}
2004-05-24 22:25:48 +02:00
2004-06-07 21:51:52 +02:00
if ( g_FixedFrameTiming ) {
2004-07-31 17:57:18 +02:00
CCamera & g_Camera = * g_Game - > GetView ( ) - > GetCamera ( ) ;
2004-06-07 21:51:52 +02:00
#if 0 // TOPDOWN
g_Camera . SetProjection ( 1.0f , 10000.0f , DEGTORAD ( 90 ) ) ;
g_Camera . m_Orientation . SetIdentity ( ) ;
g_Camera . m_Orientation . RotateX ( DEGTORAD ( 90 ) ) ;
g_Camera . m_Orientation . Translate ( CELL_SIZE * 250 * 0.5 , 250 , CELL_SIZE * 250 * 0.5 ) ;
# else // std view
g_Camera . SetProjection ( 1.0f , 10000.0f , DEGTORAD ( 20 ) ) ;
g_Camera . m_Orientation . SetXRotation ( DEGTORAD ( 30 ) ) ;
g_Camera . m_Orientation . RotateY ( DEGTORAD ( - 45 ) ) ;
g_Camera . m_Orientation . Translate ( 350 , 350 , - 275 ) ;
# endif
g_Camera . UpdateFrustum ( ) ;
}
2004-06-16 17:44:24 +02:00
g_Console - > RegisterFunc ( Testing , L " Testing " ) ;
2005-05-11 20:56:30 +02:00
debug_printf (
2004-06-08 22:41:28 +02:00
" ---------------------------------------- \n " \
" READY (elapsed = %f ms) \n " \
2005-03-22 22:00:56 +01:00
" ---------------------------------------- \n "
) ;
2004-06-08 22:41:28 +02:00
2005-03-22 03:17:55 +01:00
2004-07-12 18:50:46 +02:00
}
2004-05-24 22:25:48 +02:00
2004-07-12 18:50:46 +02:00
static void Frame ( )
{
2004-07-15 21:12:54 +02:00
MICROLOG ( L " In frame " ) ;
2005-03-30 18:14:19 +02:00
PROFILE_START ( " update music " ) ;
2004-07-28 13:36:16 +02:00
MusicPlayer . update ( ) ;
2005-03-30 18:14:19 +02:00
PROFILE_END ( " update music " ) ;
2004-07-28 13:36:16 +02:00
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 ;
ONCE ( return ) ;
2004-07-17 13:13:21 +02:00
// first call: set last_time and return
2004-07-12 18:50:46 +02:00
assert ( TimeSinceLastFrame > = 0.0f ) ;
2004-05-24 22:25:48 +02:00
2005-03-30 18:14:19 +02:00
PROFILE_START ( " reload changed files " ) ;
2004-07-15 21:12:54 +02:00
MICROLOG ( L " reload files " ) ;
2005-03-30 18:14:19 +02:00
res_reload_changed_files ( ) ;
PROFILE_END ( " reload changed files " ) ;
2004-05-24 22:25:48 +02:00
2005-03-30 18:14:19 +02:00
PROFILE_START ( " progressive load " ) ;
2005-03-22 03:17:55 +01:00
ProgressiveLoad ( ) ;
2005-03-30 18:14:19 +02:00
PROFILE_END ( " progressive load " ) ;
2004-07-15 21:12:54 +02:00
2005-03-30 18:14:19 +02:00
PROFILE_START ( " input " ) ;
2005-03-22 03:17:55 +01:00
MICROLOG ( L " input " ) ;
2004-07-12 18:50:46 +02:00
in_get_events ( ) ;
2004-08-16 17:19:17 +02:00
g_SessionManager . Poll ( ) ;
2005-03-30 18:14:19 +02:00
PROFILE_END ( " input " ) ;
PROFILE_START ( " 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-03-30 18:14:19 +02:00
PROFILE_END ( " gui tick " ) ;
2004-12-19 00:25:58 +01:00
2005-03-30 18:14:19 +02:00
PROFILE_START ( " game logic " ) ;
2004-09-21 16:40:43 +02:00
if ( g_Game & & g_Game - > IsGameStarted ( ) )
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?
g_Mouseover . update ( TimeSinceLastFrame ) ;
g_Selection . update ( ) ;
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.
g_Scheduler . update ( ( uint ) ( TimeSinceLastFrame * 1000 ) ) ;
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
// ugly, but necessary. these are one-shot events, have to be reset.
2004-07-21 18:34:07 +02:00
// Spoof mousebuttonup events for the hotkey system
SDL_Event spoof ;
spoof . type = SDL_MOUSEBUTTONUP ;
spoof . button . button = SDL_BUTTON_WHEELUP ;
if ( mouseButtons [ SDL_BUTTON_WHEELUP ] )
hotkeyInputHandler ( & spoof ) ;
spoof . button . button = SDL_BUTTON_WHEELDOWN ;
if ( mouseButtons [ SDL_BUTTON_WHEELDOWN ] )
hotkeyInputHandler ( & spoof ) ;
2004-07-20 21:30:35 +02:00
mouseButtons [ SDL_BUTTON_WHEELUP ] = false ;
mouseButtons [ SDL_BUTTON_WHEELDOWN ] = false ;
2004-06-18 15:11:58 +02:00
2005-03-30 18:14:19 +02:00
PROFILE_START ( " render " ) ;
2004-07-12 18:50:46 +02:00
if ( g_active )
{
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
}
// 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
else
SDL_Delay ( 10 ) ;
2004-07-08 17:22:09 +02:00
2005-03-30 18:14:19 +02:00
PROFILE_END ( " render " ) ;
g_Profiler . Frame ( ) ;
2004-07-12 18:50:46 +02:00
calc_fps ( ) ;
if ( g_FixedFrameTiming & & frameCount = = 100 ) quit = true ;
}
2004-05-24 22:25:48 +02:00
2004-07-15 21:12:54 +02:00
2005-01-11 17:58:16 +01:00
# ifndef SCED
2004-07-12 18:50:46 +02:00
int main ( int argc , char * argv [ ] )
{
2005-03-30 18:14:19 +02:00
new CProfileManager ;
2004-07-15 21:12:54 +02:00
MICROLOG ( L " In main " ) ;
2005-01-25 19:56:43 +01:00
MICROLOG ( L " Init " ) ;
Init ( argc , argv , true ) ;
2004-06-13 17:35:08 +02:00
2005-04-03 07:02:00 +02:00
// Optionally, do some simple tests to ensure things aren't broken
// extern void PerformTests();
// PerformTests();
2004-11-14 19:56:13 +01:00
2005-01-25 19:56:43 +01:00
while ( ! quit )
2004-07-12 18:50:46 +02:00
{
2005-01-25 19:56:43 +01:00
MICROLOG ( L " (Simulation) Frame " ) ;
Frame ( ) ;
2004-07-12 18:50:46 +02:00
}
2005-01-25 19:56:43 +01:00
MICROLOG ( L " Shutdown " ) ;
Shutdown ( ) ;
2004-07-10 16:14:36 +02:00
2005-03-30 18:14:19 +02:00
delete & g_Profiler ;
2004-06-01 19:34:12 +02:00
exit ( 0 ) ;
2004-05-24 22:25:48 +02:00
}
2005-01-11 17:58:16 +01:00
# else // SCED:
void ScEd_Init ( )
{
2005-04-03 07:02:00 +02:00
new CProfileManager ;
2005-01-12 15:31:47 +01:00
g_Quickstart = true ;
2005-01-28 23:19:09 +01:00
Init ( 0 , NULL , false ) ;
2005-01-11 17:58:16 +01:00
}
void ScEd_Shutdown ( )
{
Shutdown ( ) ;
2005-04-03 07:02:00 +02:00
delete & g_Profiler ;
2005-01-11 17:58:16 +01:00
}
2005-01-17 05:52:02 +01:00
# endif // SCED