2004-06-03 20:38:14 +02:00
# include "precompiled.h"
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
2004-07-12 18:50:46 +02: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
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"
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"
2004-05-24 22:25:48 +02:00
2004-07-12 18:50:46 +02:00
# include "scripting/ScriptingHost.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"
2004-07-08 17:22:09 +02:00
# include "gui/scripting/JSInterface_IGUIObject.h"
# include "gui/scripting/JSInterface_GUITypes.h"
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
# include "gui/GUI.h"
# 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"
2004-07-28 13:36:16 +02:00
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 ] ;
2004-07-20 21:30:35 +02:00
int mouse_x = 50 , 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-27 23:00:53 +02:00
CGameAttributes g_GameAttributes ;
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 ( ) ;
2004-11-19 23:58:01 +01:00
get_cpu_info ( ) ;
get_snd_info ( ) ;
get_mem_status ( ) ;
double t2 = get_time ( ) ;
2004-12-01 22:37:01 +01:00
debug_out ( " 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
fprintf ( f , " %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
fprintf ( f , " %s, %s " , un . machine , cpu_type ) ;
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
fprintf ( f , " %lu MB RAM; %lu MB free \n " , tot_mem / MB , avl_mem / MB ) ;
2004-11-19 23:58:01 +01:00
2004-05-24 22:25:48 +02:00
// .. graphics card
fprintf ( f , " %s \n " , gfx_card ) ;
2004-05-26 01:16:21 +02:00
fprintf ( f , " %s \n " , gfx_drv_ver ) ;
2004-06-01 19:34:12 +02:00
fprintf ( f , " %dx%d:%d@%d \n " , g_xres , g_yres , g_bpp , g_freq ) ;
2004-11-26 22:34:35 +01:00
fprintf ( f , " OpenGL: %s \n " , glGetString ( GL_VERSION ) ) ;
2004-10-23 20:13:54 +02:00
2004-11-19 23:58:01 +01:00
// .. sound card
fprintf ( f , " %s \n " , snd_card ) ;
fprintf ( f , " %s \n " , snd_drv_ver ) ;
2004-05-24 22:25:48 +02:00
// .. network name / ips
2004-07-12 18:50:46 +02:00
// note: can't use un.nodename because it is for an
// "implementation-defined communications network".
char hostname [ 128 ] ;
2004-06-16 17:44:24 +02:00
if ( gethostname ( hostname , sizeof ( hostname ) ) = = 0 ) // make sure it succeeded
2004-05-24 22:25:48 +02:00
{
2004-06-16 17:44:24 +02:00
fprintf ( f , " %s \n " , hostname ) ;
hostent * host = gethostbyname ( hostname ) ;
if ( host )
{
struct in_addr * * ips = ( struct in_addr * * ) host - > h_addr_list ;
for ( int i = 0 ; ips & & ips [ i ] ; i + + )
fprintf ( f , " %s " , inet_ntoa ( * ips [ i ] ) ) ;
fprintf ( f , " \n " ) ;
}
2004-05-24 22:25:48 +02:00
}
2004-06-07 21:51:52 +02:00
2004-07-19 21:03:33 +02:00
// Write extensions last, because there are lots of them
const char * exts = oglExtList ( ) ;
if ( ! exts ) exts = " {unknown} " ;
2004-10-23 20:13:54 +02:00
fprintf ( f , " \n Supported 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 ;
}
2004-09-23 14:42:37 +02:00
// use_bmp is for when you want high-speed output at the expense of huge files
2004-07-17 13:13:21 +02:00
static void WriteScreenshot ( bool use_bmp = false )
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
2004-09-23 14:42:37 +02:00
const char * file_format =
use_bmp ? " screenshots/screenshot%04d.bmp "
: " screenshots/screenshot%04d.png " ;
2004-07-17 13:13:21 +02:00
2004-07-09 04:04:30 +02:00
static int next_num = 1 ;
do
2004-07-17 13:13:21 +02:00
sprintf ( fn , file_format , next_num + + ) ;
2004-07-09 04:04:30 +02:00
while ( vfs_exists ( fn ) ) ;
const int w = g_xres , h = g_yres ;
const int bpp = 24 ;
const size_t size = w * h * bpp ;
void * img = mem_alloc ( size ) ;
2004-07-17 13:13:21 +02:00
glReadPixels ( 0 , 0 , w , h , use_bmp ? GL_BGR : GL_RGB , GL_UNSIGNED_BYTE , img ) ;
2004-07-09 04:04:30 +02:00
2004-07-17 13:13:21 +02:00
if ( tex_write ( fn , w , h , bpp , use_bmp ? TEX_BGR : 0 , 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 :
mouse_x = ev - > motion . x ;
mouse_y = ev - > motion . y ;
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 ( )
{
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 ( ) ;
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 ( ) ) ;
2004-05-24 22:25:48 +02:00
// start new frame
g_Renderer . BeginFrame ( ) ;
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
2004-08-05 15:07:51 +02:00
if ( g_Game )
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 " ) ;
g_Renderer . FlushFrame ( ) ;
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 )
{
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
}
g_Mouseover . renderSelectionOutlines ( ) ;
g_Selection . renderSelectionOutlines ( ) ;
glPopAttrib ( ) ;
}
else
g_Renderer . FlushFrame ( ) ;
2004-07-20 21:30:35 +02:00
2004-08-06 17:01:23 +02:00
oglCheck ( ) ;
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 ( ) ;
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 " ) ;
g_GUI . Draw ( ) ;
# 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
{
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 ( ) ;
2004-08-05 15:07:51 +02:00
if ( g_Game )
{
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-08-05 15:07:51 +02:00
static void InitDefaultGameAttributes ( )
{
2004-11-11 08:09:32 +01:00
g_GameAttributes . SetValue ( " mapFile " , L " combattest.pmp " ) ;
2004-08-05 15:07:51 +02:00
}
2004-08-02 14:53:49 +02:00
2004-10-23 16:39:28 +02:00
static void LoadProfile ( CStr profile )
{
CStr filename = CStr ( " profiles/ " ) + profile + CStr ( " .cfg " ) ;
g_ConfigDB . SetConfigFile ( CFG_USER , true , filename ) ;
g_ConfigDB . Reload ( CFG_USER ) ;
}
// 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
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 ' m ' :
if ( strncmp ( name , " m= " , 2 ) = = 0 )
2004-11-11 08:09:32 +01:00
g_GameAttributes . SetValue ( " mapFile " , CStr ( argv [ i ] + 3 ) ) ;
2004-08-02 14:53:49 +02:00
break ;
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 ( ) ;
2004-10-07 21:23:35 +02:00
2004-07-12 18:50:46 +02:00
JSI_IGUIObject : : init ( ) ;
JSI_GUITypes : : init ( ) ;
JSI_Vector3D : : init ( ) ;
2004-10-07 21:23:35 +02:00
EntityCollection : : Init ( " EntityCollection " ) ;
2004-11-11 08:09:32 +01:00
// PlayerCollection::Init( "PlayerCollection" );
CDamageType : : ScriptingInit ( ) ;
2004-10-07 21:23:35 +02:00
CJSPropertyAccessor < 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 ( ) ;
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 ) ;
2004-08-03 01:14:54 +02:00
JSI_Camera : : init ( ) ;
JSI_Console : : init ( ) ;
2004-07-12 18:50:46 +02:00
}
2004-08-02 14:53:49 +02:00
2004-07-12 18:50:46 +02:00
static void InitVfs ( char * argv0 )
{
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.");
vfs_mount ( " " , " mods/official " , 0 ) ;
2004-12-07 02:22:25 +01:00
vfs_mount ( " screenshots/ " , " screenshots " , 0 ) ;
2004-12-09 21:17:09 +01:00
vfs_mount ( " profiles/ " , " profiles " , 0 ) ;
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_5 )
2004-12-12 20:34:38 +01:00
g_GUI . LoadXMLFile ( " gui/test/5_manual.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 " ) ; }
{ 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
// We init the defaults here; command line options might want to override
InitDefaultGameAttributes ( ) ;
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 ) ;
}
2004-06-21 16:14:12 +02:00
extern u64 PREVTSC ;
2004-07-12 18:50:46 +02:00
static void Shutdown ( )
{
psShutdown ( ) ; // Must delete g_GUI before g_ScriptingHost
2004-11-11 08:09:32 +01:00
// Release script references to the globals before ScriptingHost shuts down
// g_GameAttributes.ReleaseScriptObject();
2004-08-05 15:07:51 +02:00
if ( g_Game )
delete g_Game ;
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
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
// 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
}
static void Init ( int argc , char * argv [ ] )
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:
2004-12-28 12:16:05 +01:00
//_CrtSetBreakAlloc(14246);
2004-07-10 16:14:36 +02:00
2004-06-08 22:41:28 +02:00
# ifdef _MSC_VER
u64 TSC = rdtsc ( ) ;
debug_out (
" ---------------------------------------- \n " \
" MAIN (elapsed = %f ms) \n " \
" ---------------------------------------- \n " , ( TSC - PREVTSC ) / 2e9 * 1e3 ) ;
PREVTSC = TSC ;
# endif
2004-07-15 21:12:54 +02:00
MICROLOG ( L " init lib " ) ;
2004-05-27 19:30:06 +02:00
lib_init ( ) ;
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-05-27 19:30:06 +02:00
// set 24 bit (float) FPU precision for faster divides / sqrts
# ifdef _M_IX86
_control87 ( _PC_24 , _MCW_PC ) ;
# endif
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 " ) ;
InitVfs ( argv [ 0 ] ) ;
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 ( ) ;
2004-07-15 21:12:54 +02:00
MICROLOG ( L " init sdl " ) ;
2004-05-27 19:30:06 +02:00
// init SDL
if ( SDL_Init ( SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE ) < 0 )
2004-07-19 21:03:33 +02:00
{
2004-08-15 22:57:31 +02:00
LOG ( ERROR , LOG_CATEGORY , " SDL library initialization failed: %s " , SDL_GetError ( ) ) ;
2004-07-19 21:03:33 +02:00
throw PSERROR_System_SDLInitFailed ( ) ;
}
2004-05-27 19:30:06 +02:00
atexit ( SDL_Quit ) ;
SDL_EnableUNICODE ( 1 ) ;
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
2004-07-15 21:12:54 +02:00
MICROLOG ( L " set vmode " ) ;
2004-07-12 18:50:46 +02:00
if ( set_vmode ( g_xres , g_yres , 32 , ! windowed ) < 0 )
2004-07-19 21:03:33 +02:00
{
2004-08-15 22:57:31 +02:00
LOG ( ERROR , LOG_CATEGORY , " Could not set %dx%d graphics mode: %s " , g_xres , g_yres , SDL_GetError ( ) ) ;
2004-07-19 21:03:33 +02:00
throw PSERROR_System_VmodeFailed ( ) ;
}
2004-07-28 13:36:16 +02:00
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 ( ) ;
2004-12-07 02:22:25 +01:00
vfs_display ( ) ;
}
2004-12-01 23:19:58 +01:00
else
// speed up startup by disabling all sound
// (OpenAL init will be skipped).
// must be called before first snd_open.
snd_disable ( true ) ;
2004-05-24 22:25:48 +02:00
2004-08-25 13:44:11 +02:00
if ( ! oglExtAvail ( " GL_ARB_multitexture " ) | | ! oglExtAvail ( " GL_ARB_texture_env_combine " ) | |
! 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.
2004-11-26 22:34:35 +01:00
/*if(oglExtAvail("WGL_EXT_swap_control"))
2004-11-08 23:21:50 +01:00
wglSwapIntervalEXT ( g_VSync ? 1 : 0 ) ; */
2004-05-24 22:25:48 +02:00
2004-06-11 20:02:57 +02:00
# ifdef _MSC_VER
u64 CURTSC = rdtsc ( ) ;
debug_out (
" ---------------------------------------- \n " \
2004-07-12 18:50:46 +02:00
" low-level ready (elapsed = %f ms) \n " \
2004-06-11 20:02:57 +02:00
" ---------------------------------------- \n " , ( CURTSC - PREVTSC ) / 2e9 * 1e3 ) ;
PREVTSC = CURTSC ;
# endif
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 ;
// Register a few Game/Network JS globals
g_ScriptingHost . SetGlobal ( " g_NetServerAttributes " , OBJECT_TO_JSVAL ( g_NetServerAttributes . GetJSObject ( ) ) ) ;
g_ScriptingHost . SetGlobal ( " g_GameAttributes " , OBJECT_TO_JSVAL ( g_GameAttributes . GetJSObject ( ) ) ) ;
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
{
in_add_handler ( handler ) ;
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
# 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
2004-12-08 16:34:15 +01:00
in_add_handler ( conInputHandler ) ;
2004-07-21 18:34:07 +02:00
2004-12-08 16:34:15 +01:00
in_add_handler ( hotkeyInputHandler ) ; // <- Leave this one until after all the others.
}
2004-06-02 22:39:21 +02:00
2005-01-04 22:51:23 +01:00
# ifndef NO_GUI
g_GUI . SendEventToAll ( " load " ) ;
# endif
2004-07-15 21:12:54 +02:00
MICROLOG ( L " render blank " ) ;
2004-05-24 22:25:48 +02:00
// render everything to a blank frame to force renderer to load everything
RenderNoCull ( ) ;
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 " ) ;
2004-06-08 22:41:28 +02:00
# ifdef _MSC_VER
2004-06-11 20:02:57 +02:00
{
2004-06-08 22:41:28 +02:00
u64 CURTSC = rdtsc ( ) ;
debug_out (
" ---------------------------------------- \n " \
" READY (elapsed = %f ms) \n " \
" ---------------------------------------- \n " , ( CURTSC - PREVTSC ) / 2e9 * 1e3 ) ;
PREVTSC = CURTSC ;
2004-06-11 20:02:57 +02:00
}
2004-06-08 22:41:28 +02:00
# endif
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 " ) ;
2004-07-28 13:36:16 +02:00
MusicPlayer . update ( ) ;
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
2004-07-15 21:12:54 +02:00
MICROLOG ( L " reload files " ) ;
2004-07-12 18:50:46 +02:00
res_reload_changed_files ( ) ;
2004-05-24 22:25:48 +02:00
2004-07-15 21:12:54 +02: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 ( ) ;
2004-07-20 21:30:35 +02:00
2004-12-19 00:25:58 +01:00
g_GUI . TickObjects ( ) ;
2004-09-21 16:40:43 +02:00
if ( g_Game & & g_Game - > IsGameStarted ( ) )
2004-08-05 15:07:51 +02:00
{
g_Game - > Update ( TimeSinceLastFrame ) ;
if ( ! g_FixedFrameTiming )
g_Game - > GetView ( ) - > Update ( float ( TimeSinceLastFrame ) ) ;
2004-07-21 18:34:07 +02:00
2004-08-05 15:07:51 +02:00
// TODO Where does GameView end and other things begin?
g_Mouseover . update ( TimeSinceLastFrame ) ;
g_Selection . 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 )
debug_out ( " snd_update failed \n " ) ;
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 )
debug_out ( " snd_update (pos=0 version) failed \n " ) ;
}
2004-07-20 21:30:35 +02:00
g_Console - > Update ( TimeSinceLastFrame ) ;
// 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
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 " ) ;
2004-12-28 12:16:05 +01:00
SDL_GL_SwapBuffers ( ) ;
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
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
2004-08-24 13:32:32 +02:00
// Choose when to override the standard exception handling behaviour
// (opening the debugger when available, or crashing when not) with
// code that generates a crash log/dump.
2004-11-30 16:52:10 +01:00
# if defined(_WIN32) && ( defined(NDEBUG) || defined(TESTING) )
# define CUSTOM_EXCEPTION_HANDLER
# endif
2004-07-15 21:12:54 +02:00
# ifdef CUSTOM_EXCEPTION_HANDLER
# include <excpt.h>
# endif
2004-07-12 18:50:46 +02:00
int main ( int argc , char * argv [ ] )
{
2004-07-15 21:12:54 +02:00
MICROLOG ( L " In main " ) ;
# ifdef CUSTOM_EXCEPTION_HANDLER
__try
2004-07-12 18:50:46 +02:00
{
2004-07-15 21:12:54 +02:00
# endif
MICROLOG ( L " Init " ) ;
2004-07-12 18:50:46 +02:00
Init ( argc , argv ) ;
2004-06-13 17:35:08 +02:00
2004-11-30 16:52:10 +01:00
// Do some limited tests to ensure things aren't broken
# ifndef NDEBUG
2004-12-08 16:34:15 +01:00
{
2004-11-14 19:56:13 +01:00
extern void PerformTests ( ) ;
PerformTests ( ) ;
2004-12-08 16:34:15 +01:00
}
2004-11-30 16:52:10 +01:00
# endif
2004-11-14 19:56:13 +01:00
2004-07-12 18:50:46 +02:00
while ( ! quit )
2004-07-15 21:12:54 +02:00
{
2004-07-20 21:30:35 +02:00
MICROLOG ( L " (Simulation) Frame " ) ;
2004-07-12 18:50:46 +02:00
Frame ( ) ;
2004-07-15 21:12:54 +02:00
}
2004-06-13 17:35:08 +02:00
2004-09-05 13:27:23 +02:00
//_CrtMemDumpAllObjectsSince(NULL);
2004-07-15 21:12:54 +02:00
MICROLOG ( L " Shutdown " ) ;
2004-07-12 18:50:46 +02:00
Shutdown ( ) ;
2004-07-15 21:12:54 +02:00
# ifdef CUSTOM_EXCEPTION_HANDLER
2004-07-12 18:50:46 +02:00
}
2004-07-15 21:12:54 +02:00
__except ( debug_main_exception_filter ( GetExceptionCode ( ) , GetExceptionInformation ( ) ) )
2004-07-12 18:50:46 +02:00
{
}
2004-07-15 21:12:54 +02:00
# endif
2004-07-10 16:14:36 +02:00
2004-06-01 19:34:12 +02:00
exit ( 0 ) ;
2004-05-24 22:25:48 +02:00
}