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-06-03 21:43:19 +02:00
|
|
|
#include <fmod.h>
|
2004-05-24 22:25:48 +02:00
|
|
|
|
2004-05-28 15:07:54 +02:00
|
|
|
// Alan: For some reason if this gets included after anything else some
|
|
|
|
// compile time errors get thrown up todo with javascript internal typedefs
|
|
|
|
#include "scripting/ScriptingHost.h"
|
|
|
|
|
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"
|
|
|
|
#include "res/res.h"
|
2004-06-04 19:47:12 +02:00
|
|
|
#include "res/file.h"
|
2004-05-24 22:25:48 +02:00
|
|
|
#ifdef _M_IX86
|
|
|
|
#include "sysdep/ia32.h"
|
|
|
|
#endif
|
2004-06-02 22:39:21 +02:00
|
|
|
|
|
|
|
#include "ps/CConsole.h"
|
|
|
|
|
2004-05-29 23:04:18 +02:00
|
|
|
#include "Config.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"
|
|
|
|
#include "Model.h"
|
|
|
|
#include "UnitManager.h"
|
|
|
|
|
|
|
|
#include "BaseEntityCollection.h"
|
|
|
|
#include "Entity.h"
|
|
|
|
#include "EntityHandles.h"
|
|
|
|
#include "EntityManager.h"
|
2004-05-29 05:32:33 +02:00
|
|
|
#include "PathfindEngine.h"
|
2004-05-24 22:25:48 +02:00
|
|
|
|
2004-05-28 15:07:54 +02:00
|
|
|
|
2004-05-24 22:25:48 +02:00
|
|
|
#ifndef NO_GUI
|
|
|
|
#include "gui/GUI.h"
|
|
|
|
#endif
|
|
|
|
|
2004-06-03 21:43:19 +02:00
|
|
|
|
2004-06-02 22:39:21 +02:00
|
|
|
CConsole* g_Console = 0;
|
|
|
|
extern bool conInputHandler(const SDL_Event& ev);
|
|
|
|
|
2004-05-24 22:25:48 +02:00
|
|
|
|
|
|
|
|
|
|
|
u32 game_ticks;
|
|
|
|
|
|
|
|
bool keys[SDLK_LAST];
|
2004-05-26 00:02:57 +02:00
|
|
|
bool mouseButtons[5];
|
2004-05-24 22:25:48 +02:00
|
|
|
|
2004-06-03 03:43:33 +02:00
|
|
|
// Globals
|
|
|
|
int g_xres, g_yres;
|
|
|
|
int g_bpp;
|
|
|
|
int g_freq;
|
|
|
|
|
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
|
|
|
|
static bool g_NoPBuffer=false;
|
2004-05-24 22:25:48 +02:00
|
|
|
static bool g_VSync = false;
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
// mapfile to load or null for no map (and to use default terrain)
|
|
|
|
static const char* g_MapFile=0;
|
|
|
|
|
|
|
|
|
|
|
|
static Handle font;
|
|
|
|
|
|
|
|
|
|
|
|
extern CCamera g_Camera;
|
|
|
|
|
|
|
|
extern void terr_init();
|
|
|
|
extern void terr_update(float time);
|
|
|
|
extern bool terr_handler(const SDL_Event& ev);
|
|
|
|
|
|
|
|
extern int allow_reload();
|
|
|
|
extern int dir_add_watch(const char* const dir, bool watch_subdirs);
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-06-02 22:39:21 +02:00
|
|
|
|
|
|
|
void Testing (void)
|
|
|
|
{
|
|
|
|
g_Console->InsertMessage("Testing Function Registration");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-05-24 22:25:48 +02:00
|
|
|
static int write_sys_info()
|
|
|
|
{
|
|
|
|
get_gfx_info();
|
|
|
|
|
|
|
|
struct utsname un;
|
|
|
|
uname(&un);
|
|
|
|
|
2004-05-27 02:29:54 +02:00
|
|
|
FILE* const f = fopen("../logs/system_info.txt", "w");
|
2004-05-24 22:25:48 +02:00
|
|
|
if(!f)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
// .. OS
|
|
|
|
fprintf(f, "%s %s (%s)\n", un.sysname, un.release, un.version);
|
|
|
|
// .. 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");
|
|
|
|
// .. memory
|
|
|
|
fprintf(f, "%lu MB RAM; %lu MB free\n", tot_mem/MB, avl_mem/MB);
|
|
|
|
// .. 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-05-24 22:25:48 +02:00
|
|
|
// .. network name / ips
|
|
|
|
char hostname[100]; // possibly nodename != hostname
|
|
|
|
gethostname(hostname, sizeof(hostname));
|
|
|
|
fprintf(f, "%s\n", hostname);
|
2004-06-01 19:34:12 +02:00
|
|
|
hostent* host = gethostbyname(hostname);
|
|
|
|
if(host)
|
2004-05-24 22:25:48 +02:00
|
|
|
{
|
2004-06-01 19:34:12 +02:00
|
|
|
struct in_addr** ips = (struct in_addr**)host->h_addr_list;
|
2004-05-24 22:25:48 +02:00
|
|
|
for(int i = 0; ips && ips[i]; i++)
|
|
|
|
fprintf(f, "%s ", inet_ntoa(*ips[i]));
|
|
|
|
fprintf(f, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// error before GUI is initialized: display message, and quit
|
|
|
|
// TODO: localization
|
|
|
|
static void display_startup_error(const wchar_t* msg)
|
|
|
|
{
|
|
|
|
const wchar_t* caption = L"0ad startup problem";
|
|
|
|
|
|
|
|
write_sys_info();
|
|
|
|
wdisplay_msg(caption, msg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// error before GUI is initialized: display message, and quit
|
|
|
|
// TODO: localization
|
|
|
|
static void display_startup_error(const char* msg)
|
|
|
|
{
|
|
|
|
const char* caption = "0ad startup problem";
|
|
|
|
|
|
|
|
write_sys_info();
|
|
|
|
display_msg(caption, msg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int set_vmode(int w, int h, int bpp)
|
|
|
|
{
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
|
|
|
|
|
|
|
if(!SDL_SetVideoMode(w, h, bpp, SDL_OPENGL|SDL_FULLSCREEN))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
glViewport(0, 0, w, h);
|
|
|
|
|
|
|
|
#ifndef NO_GUI
|
|
|
|
g_GUI.UpdateResolution();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
oglInit(); // required after each mode change
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// break out of main loop
|
|
|
|
static bool quit = false;
|
|
|
|
|
|
|
|
static bool handler(const SDL_Event& ev)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
switch(ev.type)
|
|
|
|
{
|
|
|
|
case SDL_KEYDOWN:
|
|
|
|
c = ev.key.keysym.sym;
|
|
|
|
keys[c] = true;
|
2004-06-02 22:39:21 +02:00
|
|
|
|
2004-05-24 22:25:48 +02:00
|
|
|
switch(c)
|
|
|
|
{
|
|
|
|
case SDLK_ESCAPE:
|
|
|
|
quit = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SDL_KEYUP:
|
|
|
|
c = ev.key.keysym.sym;
|
|
|
|
keys[c] = false;
|
|
|
|
break;
|
2004-05-26 00:02:57 +02:00
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
|
|
c = ev.button.button;
|
|
|
|
if( c < 5 )
|
|
|
|
mouseButtons[c] = true;
|
|
|
|
break;
|
|
|
|
case SDL_MOUSEBUTTONUP:
|
|
|
|
c = ev.button.button;
|
|
|
|
if( c < 5 )
|
|
|
|
mouseButtons[c] = false;
|
|
|
|
break;
|
2004-05-24 22:25:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// RenderTerrain: iterate through all terrain patches and submit all patches in viewing frustum to
|
|
|
|
// the renderer
|
|
|
|
void RenderTerrain()
|
|
|
|
{
|
|
|
|
CFrustum frustum=g_Camera.GetFustum();
|
|
|
|
u32 patchesPerSide=g_Terrain.GetPatchesPerSide();
|
|
|
|
for (uint j=0; j<patchesPerSide; j++) {
|
|
|
|
for (uint i=0; i<patchesPerSide; i++) {
|
|
|
|
CPatch* patch=g_Terrain.GetPatch(i,j);
|
|
|
|
if (frustum.IsBoxVisible (CVector3D(0,0,0),patch->GetBounds())) {
|
|
|
|
g_Renderer.Submit(patch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-05-30 02:46:58 +02:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
2004-06-01 19:34:12 +02:00
|
|
|
// SubmitModelRecursive: recurse down given model, submitting it and all its descendents to the
|
2004-05-30 02:46:58 +02:00
|
|
|
// renderer
|
|
|
|
void SubmitModelRecursive(CModel* model)
|
|
|
|
{
|
|
|
|
g_Renderer.Submit(model);
|
|
|
|
|
|
|
|
const std::vector<CModel::Prop>& props=model->GetProps();
|
|
|
|
for (uint i=0;i<props.size();i++) {
|
|
|
|
SubmitModelRecursive(props[i].m_Model);
|
|
|
|
}
|
|
|
|
}
|
2004-05-24 22:25:48 +02:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// RenderModels: iterate through model list and submit all models in viewing frustum to the
|
|
|
|
// Renderer
|
|
|
|
void RenderModels()
|
|
|
|
{
|
|
|
|
CFrustum frustum=g_Camera.GetFustum();
|
|
|
|
|
|
|
|
const std::vector<CUnit*>& units=g_UnitMan.GetUnits();
|
2004-05-29 23:04:18 +02:00
|
|
|
for (uint i=0;i<units.size();++i) {
|
2004-05-30 02:46:58 +02:00
|
|
|
if (frustum.IsBoxVisible(CVector3D(0,0,0),units[i]->GetModel()->GetBounds())) {
|
2004-05-29 23:04:18 +02:00
|
|
|
SubmitModelRecursive(units[i]->GetModel());
|
2004-05-24 22:25:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// RenderNoCull: render absolutely everything to a blank frame to force renderer
|
|
|
|
// to load required assets
|
|
|
|
void RenderNoCull()
|
|
|
|
{
|
|
|
|
g_Renderer.BeginFrame();
|
|
|
|
g_Renderer.SetCamera(g_Camera);
|
|
|
|
|
|
|
|
uint i,j;
|
|
|
|
const std::vector<CUnit*>& units=g_UnitMan.GetUnits();
|
|
|
|
for (i=0;i<units.size();++i) {
|
2004-05-29 23:04:18 +02:00
|
|
|
SubmitModelRecursive(units[i]->GetModel());
|
2004-05-24 22:25:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
u32 patchesPerSide=g_Terrain.GetPatchesPerSide();
|
|
|
|
for (j=0; j<patchesPerSide; j++) {
|
|
|
|
for (i=0; i<patchesPerSide; i++) {
|
|
|
|
CPatch* patch=g_Terrain.GetPatch(i,j);
|
|
|
|
g_Renderer.Submit(patch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_Renderer.FlushFrame();
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
|
|
|
g_Renderer.EndFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void Render()
|
|
|
|
{
|
|
|
|
// start new frame
|
|
|
|
g_Renderer.BeginFrame();
|
|
|
|
g_Renderer.SetCamera(g_Camera);
|
|
|
|
|
|
|
|
// switch on wireframe for terrain if we want it
|
|
|
|
g_Renderer.SetTerrainRenderMode( SOLID );
|
|
|
|
|
|
|
|
RenderTerrain();
|
|
|
|
RenderModels();
|
|
|
|
g_Renderer.FlushFrame();
|
|
|
|
|
2004-05-29 05:32:33 +02:00
|
|
|
if( g_EntGraph )
|
|
|
|
{
|
|
|
|
glPushAttrib( GL_ENABLE_BIT );
|
|
|
|
glDisable( GL_LIGHTING );
|
|
|
|
glDisable( GL_TEXTURE_2D );
|
|
|
|
glDisable( GL_DEPTH_TEST );
|
|
|
|
glColor3f( 1.0f, 0.0f, 1.0f );
|
2004-05-26 22:57:25 +02:00
|
|
|
|
2004-05-29 05:32:33 +02:00
|
|
|
g_EntityManager.renderAll(); // <-- collision outlines, pathing routes
|
|
|
|
|
|
|
|
glPopAttrib();
|
|
|
|
}
|
2004-05-24 22:25:48 +02:00
|
|
|
|
|
|
|
// overlay mode
|
|
|
|
glPushAttrib(GL_ENABLE_BIT);
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
glBlendFunc(GL_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glAlphaFunc(GL_GREATER, 0.5);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
glOrtho(0.f, (float)g_xres, 0.f, (float)g_yres, -1.f, 1000.f);
|
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
|
|
|
|
// FPS counter
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(10, 30, 0);
|
|
|
|
font_bind(font);
|
|
|
|
glprintf("%d FPS", fps);
|
|
|
|
|
|
|
|
// view params
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(10, 90, 0);
|
|
|
|
extern float ViewFOV;
|
|
|
|
glprintf("FOV=%.1f", RADTODEG(ViewFOV));
|
|
|
|
|
|
|
|
#ifndef NO_GUI
|
|
|
|
// Temp GUI message GeeTODO
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(10, 60, 0);
|
|
|
|
glprintf("%s", g_GUI.TEMPmessage.c_str());
|
|
|
|
|
|
|
|
glLoadIdentity();
|
|
|
|
g_GUI.Draw();
|
|
|
|
#endif
|
|
|
|
|
2004-05-26 22:57:25 +02:00
|
|
|
|
2004-06-02 22:39:21 +02:00
|
|
|
g_Console->Render();
|
2004-05-26 22:57:25 +02:00
|
|
|
|
2004-05-24 22:25:48 +02:00
|
|
|
// restore
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopMatrix();
|
|
|
|
glPopAttrib();
|
|
|
|
|
|
|
|
g_Renderer.EndFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void do_tick()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// UpdateWorld: update time dependent data in the world to account for changes over
|
|
|
|
// the given time (in s)
|
|
|
|
void UpdateWorld(float time)
|
|
|
|
{
|
|
|
|
const std::vector<CUnit*>& units=g_UnitMan.GetUnits();
|
|
|
|
for (uint i=0;i<units.size();++i) {
|
2004-05-29 23:04:18 +02:00
|
|
|
units[i]->GetModel()->Update(time);
|
2004-05-24 22:25:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
g_EntityManager.updateAll( time );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ParseArgs(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
for (int i=1;i<argc;i++) {
|
|
|
|
if (argv[i][0]=='-') {
|
|
|
|
switch (argv[i][1]) {
|
|
|
|
case 'm':
|
|
|
|
if (argv[i][2]=='=') {
|
|
|
|
g_MapFile=argv[i]+3;
|
|
|
|
}
|
|
|
|
break;
|
2004-05-24 23:28:49 +02:00
|
|
|
case 'g':
|
|
|
|
if( argv[i][2] == '=' )
|
|
|
|
{
|
|
|
|
g_Gamma = (float)atof( argv[i] + 3 );
|
|
|
|
if( g_Gamma == 0.0f ) g_Gamma = 1.0f;
|
|
|
|
}
|
|
|
|
break;
|
2004-05-29 05:32:33 +02:00
|
|
|
case 'e':
|
|
|
|
g_EntGraph = true;
|
2004-05-26 00:02:57 +02:00
|
|
|
case 'v':
|
|
|
|
g_VSync = true;
|
|
|
|
break;
|
2004-05-24 22:25:48 +02:00
|
|
|
case 'n':
|
|
|
|
if (strncmp(argv[i]+1,"novbo",5)==0) {
|
|
|
|
g_NoGLVBO=true;
|
|
|
|
}
|
2004-05-29 23:04:18 +02:00
|
|
|
else if (strncmp(argv[i]+1,"nopbuffer",9)==0) {
|
|
|
|
g_NoPBuffer=true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
if (strncmp(argv[i]+1,"shadows",7)==0) {
|
|
|
|
g_Shadows=true;
|
|
|
|
}
|
2004-05-24 22:25:48 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
const int ERR_MSG_SIZE = 1000;
|
|
|
|
wchar_t err_msg[ERR_MSG_SIZE];
|
|
|
|
|
2004-05-27 19:30:06 +02:00
|
|
|
lib_init();
|
|
|
|
|
|
|
|
// set 24 bit (float) FPU precision for faster divides / sqrts
|
|
|
|
#ifdef _M_IX86
|
|
|
|
_control87(_PC_24, _MCW_PC);
|
|
|
|
#endif
|
|
|
|
|
2004-06-01 19:34:12 +02:00
|
|
|
|
2004-05-27 19:30:06 +02:00
|
|
|
detect();
|
|
|
|
|
|
|
|
// init SDL
|
|
|
|
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE) < 0)
|
|
|
|
{
|
|
|
|
swprintf(err_msg, ERR_MSG_SIZE, L"SDL library initialization failed: %s\n", SDL_GetError());
|
|
|
|
display_startup_error(err_msg);
|
|
|
|
}
|
|
|
|
atexit(SDL_Quit);
|
|
|
|
SDL_EnableUNICODE(1);
|
|
|
|
|
|
|
|
|
2004-06-03 21:43:19 +02:00
|
|
|
if(FSOUND_Init(44100, 32, 0) == 0)
|
|
|
|
{
|
|
|
|
swprintf(err_msg, ERR_MSG_SIZE, L"Failed to initialise FMOD");
|
|
|
|
display_startup_error(err_msg);
|
|
|
|
}
|
2004-05-24 22:25:48 +02:00
|
|
|
|
|
|
|
// set current directory to "$game_dir/data".
|
|
|
|
// this is necessary because it is otherwise unknown,
|
2004-05-27 19:30:06 +02:00
|
|
|
// especially if run from a shortcut / symlink.
|
2004-05-24 22:25:48 +02:00
|
|
|
//
|
|
|
|
// "../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(argv[0], "../data");
|
|
|
|
if(err < 0)
|
|
|
|
{
|
|
|
|
swprintf(err_msg, ERR_MSG_SIZE, L"error setting current directory.\n"\
|
|
|
|
L"argv[0] is probably incorrect. please start the game via command-line.");
|
|
|
|
display_startup_error(err_msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
ParseArgs(argc, argv);
|
|
|
|
|
|
|
|
|
2004-05-28 15:07:54 +02:00
|
|
|
// Create the scripting host. This needs to be done before the GUI is created.
|
|
|
|
new ScriptingHost;
|
2004-05-27 02:29:54 +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
|
|
|
|
|
|
|
|
// preferred video mode = current desktop settings
|
|
|
|
// (command line params may override these)
|
2004-06-01 19:34:12 +02:00
|
|
|
get_cur_vmode(&g_xres, &g_yres, &g_bpp, &g_freq);
|
2004-05-24 22:25:48 +02:00
|
|
|
|
|
|
|
for(int a = 1; a < argc; a++)
|
|
|
|
if(!strncmp(argv[a], "xres", 4))
|
|
|
|
g_xres = atoi(argv[a]+4);
|
|
|
|
else if(!strncmp(argv[a], "yres", 4))
|
|
|
|
g_yres = atoi(argv[a]+4);
|
|
|
|
// TODO: other command line options
|
|
|
|
|
|
|
|
if(set_vmode(g_xres, g_yres, 32) < 0)
|
|
|
|
{
|
|
|
|
swprintf(err_msg, ERR_MSG_SIZE, L"could not set %dx%d graphics mode: %s\n", g_xres, g_yres, SDL_GetError());
|
|
|
|
display_startup_error(err_msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
write_sys_info();
|
|
|
|
|
|
|
|
if(!oglExtAvail("GL_ARB_multitexture") || !oglExtAvail("GL_ARB_texture_env_combine"))
|
|
|
|
display_startup_error(L"required ARB_multitexture or ARB_texture_env_combine extension not available");
|
|
|
|
|
|
|
|
// enable/disable VSync
|
|
|
|
// note: "GL_EXT_SWAP_CONTROL" is "historical" according to dox.
|
|
|
|
if(oglExtAvail("WGL_EXT_swap_control"))
|
|
|
|
wglSwapIntervalEXT(g_VSync? 1 : 0);
|
|
|
|
|
|
|
|
|
|
|
|
if(SDL_SetGamma(g_Gamma, g_Gamma, g_Gamma) < 0)
|
|
|
|
{
|
|
|
|
debug_warn("SDL_SetGamma failed");
|
|
|
|
}
|
|
|
|
|
2004-05-30 02:46:58 +02:00
|
|
|
|
2004-06-03 03:43:33 +02:00
|
|
|
/// new CConfig;
|
2004-05-24 22:25:48 +02:00
|
|
|
|
2004-05-27 02:29:54 +02:00
|
|
|
// vfs_mount("gui", "gui", 0);
|
2004-05-24 22:25:48 +02:00
|
|
|
vfs_mount("", "mods/official/", 0);
|
|
|
|
//// dir_add_watch("mods\\official", false);
|
|
|
|
|
|
|
|
#ifndef NO_GUI
|
|
|
|
// GUI uses VFS, so this must come after VFS init.
|
|
|
|
g_GUI.Initialize();
|
|
|
|
g_GUI.LoadXMLFile("gui/styles.xml");
|
|
|
|
g_GUI.LoadXMLFile("gui/hello.xml");
|
|
|
|
g_GUI.LoadXMLFile("gui/sprite1.xml");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2004-05-27 01:47:46 +02:00
|
|
|
font = font_load("fonts/verdana.fnt");
|
2004-05-24 22:25:48 +02:00
|
|
|
|
2004-06-03 02:19:22 +02:00
|
|
|
g_Console = new CConsole(0, g_yres-600.f, 800.f, 600.f);
|
2004-06-02 22:39:21 +02:00
|
|
|
|
2004-05-29 23:04:18 +02:00
|
|
|
// create renderer
|
|
|
|
new CRenderer;
|
|
|
|
|
2004-05-24 22:25:48 +02:00
|
|
|
// set renderer options from command line options - NOVBO must be set before opening the renderer
|
2004-05-29 23:04:18 +02:00
|
|
|
g_Renderer.SetOptionBool(CRenderer::OPT_NOVBO,g_NoGLVBO);
|
|
|
|
g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWS,g_Shadows);
|
|
|
|
g_Renderer.SetOptionBool(CRenderer::OPT_NOPBUFFER,g_NoPBuffer);
|
|
|
|
|
|
|
|
// create terrain related stuff
|
|
|
|
new CTextureManager;
|
|
|
|
|
|
|
|
// create actor related stuff
|
|
|
|
new CSkeletonAnimManager;
|
|
|
|
new CObjectManager;
|
|
|
|
new CUnitManager;
|
2004-05-24 22:25:48 +02:00
|
|
|
|
2004-06-03 03:43:33 +02:00
|
|
|
g_Renderer.Open(g_xres,g_yres,g_bpp);
|
|
|
|
|
|
|
|
// terr_init loads a bunch of resources as well as setting up the terrain
|
2004-05-24 22:25:48 +02:00
|
|
|
terr_init();
|
|
|
|
|
|
|
|
|
|
|
|
// This needs to be done after the renderer has loaded all its actors...
|
|
|
|
new CBaseEntityCollection;
|
|
|
|
new CEntityManager;
|
2004-05-29 05:32:33 +02:00
|
|
|
new CPathfindEngine;
|
2004-05-24 22:25:48 +02:00
|
|
|
|
|
|
|
g_EntityTemplateCollection.loadTemplates();
|
|
|
|
|
|
|
|
|
2004-05-26 21:28:42 +02:00
|
|
|
// if no map name specified, load test01.pmp (for convenience during
|
|
|
|
// development. that means loading no map at all is currently impossible.
|
|
|
|
// is that a problem?
|
|
|
|
if(!g_MapFile)
|
|
|
|
g_MapFile = "test01.pmp";
|
|
|
|
|
|
|
|
|
2004-05-24 22:25:48 +02:00
|
|
|
// load a map if we were given one
|
|
|
|
if (g_MapFile) {
|
|
|
|
CStr mapfilename("mods/official/maps/scenarios/");
|
|
|
|
mapfilename+=g_MapFile;
|
|
|
|
try {
|
|
|
|
CMapReader reader;
|
|
|
|
reader.LoadMap(mapfilename);
|
|
|
|
} catch (...) {
|
|
|
|
char errmsg[256];
|
|
|
|
sprintf(errmsg, "Failed to load map %s\n", mapfilename.c_str());
|
|
|
|
display_startup_error(errmsg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize entities
|
|
|
|
|
|
|
|
g_EntityManager.dispatchAll( &CMessage( CMessage::EMSG_INIT ) );
|
|
|
|
|
|
|
|
#ifndef NO_GUI
|
|
|
|
in_add_handler(gui_handler);
|
|
|
|
#endif
|
2004-05-26 05:14:33 +02:00
|
|
|
in_add_handler(handler);
|
|
|
|
in_add_handler(terr_handler);
|
2004-05-24 22:25:48 +02:00
|
|
|
|
2004-06-02 22:39:21 +02:00
|
|
|
in_add_handler(conInputHandler);
|
|
|
|
|
2004-05-24 22:25:48 +02:00
|
|
|
// render everything to a blank frame to force renderer to load everything
|
|
|
|
RenderNoCull();
|
|
|
|
|
2004-06-02 22:39:21 +02:00
|
|
|
g_Console->RegisterFunc(Testing, "Testing");
|
|
|
|
|
2004-05-24 22:25:48 +02:00
|
|
|
|
|
|
|
// fixed timestep main loop
|
|
|
|
const double TICK_TIME = 30e-3; // [s]
|
|
|
|
double time0 = get_time();
|
|
|
|
|
2004-06-03 03:43:33 +02:00
|
|
|
// g_Config.Update();
|
2004-05-24 22:25:48 +02:00
|
|
|
while(!quit)
|
|
|
|
{
|
|
|
|
//g_Config.Update();
|
|
|
|
|
|
|
|
//// allow_reload();
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: limiter in case simulation can't keep up?
|
|
|
|
#if 0
|
|
|
|
double time1 = get_time();
|
|
|
|
while((time1-time0) > TICK_TIME)
|
|
|
|
{
|
|
|
|
game_ticks++;
|
|
|
|
in_get_events();
|
|
|
|
do_tick();
|
|
|
|
time0 += TICK_TIME;
|
|
|
|
}
|
|
|
|
UpdateWorld(float(time1-time0));
|
|
|
|
terr_update(float(time1-time0));
|
|
|
|
Render();
|
|
|
|
SDL_GL_SwapBuffers();
|
|
|
|
|
|
|
|
calc_fps();
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
double time1 = get_time();
|
|
|
|
|
2004-05-26 00:02:57 +02:00
|
|
|
mouseButtons[SDL_BUTTON_WHEELUP] = false;
|
|
|
|
mouseButtons[SDL_BUTTON_WHEELDOWN] = false;
|
|
|
|
|
2004-06-03 02:19:22 +02:00
|
|
|
float TimeSinceLastFrame = (float)(time1-time0);
|
2004-05-24 22:25:48 +02:00
|
|
|
in_get_events();
|
2004-06-03 02:19:22 +02:00
|
|
|
UpdateWorld(TimeSinceLastFrame);
|
|
|
|
terr_update(TimeSinceLastFrame);
|
|
|
|
g_Console->Update(TimeSinceLastFrame);
|
2004-05-24 22:25:48 +02:00
|
|
|
Render();
|
|
|
|
SDL_GL_SwapBuffers();
|
|
|
|
|
|
|
|
calc_fps();
|
|
|
|
time0=time1;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef NO_GUI
|
|
|
|
g_GUI.Destroy();
|
2004-06-03 03:43:33 +02:00
|
|
|
delete CGUI::GetSingletonPtr();
|
2004-05-24 22:25:48 +02:00
|
|
|
#endif
|
|
|
|
|
2004-05-28 15:07:54 +02:00
|
|
|
delete &g_ScriptingHost;
|
2004-06-03 03:43:33 +02:00
|
|
|
/// delete &g_Config;
|
2004-05-29 05:32:33 +02:00
|
|
|
delete &g_Pathfinder;
|
2004-05-24 22:25:48 +02:00
|
|
|
delete &g_EntityManager;
|
|
|
|
delete &g_EntityTemplateCollection;
|
|
|
|
|
2004-05-29 23:04:18 +02:00
|
|
|
// destroy actor related stuff
|
|
|
|
delete CUnitManager::GetSingletonPtr();
|
|
|
|
delete CObjectManager::GetSingletonPtr();
|
|
|
|
delete CSkeletonAnimManager::GetSingletonPtr();
|
|
|
|
|
|
|
|
// destroy terrain related stuff
|
|
|
|
delete CTextureManager::GetSingletonPtr();
|
|
|
|
|
|
|
|
// destroy renderer
|
|
|
|
delete CRenderer::GetSingletonPtr();
|
|
|
|
|
2004-06-03 21:43:19 +02:00
|
|
|
//shut down FMOD - needs adding to the atexit calls above
|
|
|
|
FSOUND_Close();
|
|
|
|
|
2004-06-01 19:34:12 +02:00
|
|
|
exit(0);
|
2004-05-24 22:25:48 +02:00
|
|
|
return 0;
|
|
|
|
}
|