282 lines
8.1 KiB
C++
282 lines
8.1 KiB
C++
/***************************************************************************
|
|
|
|
file : main.cpp
|
|
created : Sat Sep 2 10:40:47 CEST 2000
|
|
copyright : (C) 2000 by Patrice & Eric Espie
|
|
email : torcs@free.fr
|
|
version : $Id$
|
|
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
#include <portability.h>
|
|
#include <tgfclient.h>
|
|
#include <tgfdata.h>
|
|
#include <tgf.h>
|
|
|
|
#ifdef WIN32
|
|
#ifndef HAVE_CONFIG_H
|
|
#define HAVE_CONFIG_H
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <raceman.h> // RACE_ENG_CFG
|
|
#include <iraceengine.h>
|
|
#include <iuserinterface.h>
|
|
|
|
// If defined in tgf.h:
|
|
// Use new Memory Manager ...
|
|
#ifdef __DEBUG_MEMORYMANAGER__
|
|
#include "memmanager.h"
|
|
|
|
// Use global variables for debugging ...
|
|
IUserInterface* piUserItf = 0;
|
|
GfModule* pmodUserItf = NULL;
|
|
IRaceEngine* piRaceEngine = 0;
|
|
GfModule* pmodRaceEngine = NULL;
|
|
// ... Use global variables for debugging
|
|
|
|
// Garbage Collection in case of GfuiApp().restart();
|
|
void ReleaseData(void)
|
|
{
|
|
// Shortcut: Use Memory Manager as garbage collector
|
|
GfMemoryManagerRelease(false); // Release the memory manager without dump
|
|
|
|
/*
|
|
// For debugging only ...
|
|
if (piUserItf && piRaceEngine)
|
|
{
|
|
// Shutdown and unload the user interface and race engine modules.
|
|
// piUserItf->shutdown();
|
|
// piRaceEngine->shutdown();
|
|
|
|
// GfModule::unload(pmodUserItf);
|
|
// GfModule::unload(pmodRaceEngine);
|
|
|
|
// Shutdown the data layer.
|
|
// GfData::shutdown(); << causes crashes if called from here
|
|
|
|
// Shortcut: Use Memory Manager as garbage collector
|
|
GfMemoryManagerRelease(false); // Release the memory manager without dump
|
|
}
|
|
// ... For debugging only
|
|
*/
|
|
}
|
|
#endif
|
|
// ... Use new Memory Manager
|
|
|
|
/*
|
|
* Function
|
|
* main
|
|
*
|
|
* Description
|
|
* Main function of the game
|
|
*
|
|
* Parameters
|
|
* argc Number of command line args, + 1 for the executable name
|
|
* argv Array of zero-terminated strings, 1 for each arg
|
|
*
|
|
* Return
|
|
* 0 status code if OK, non-0 otherwise.
|
|
*/
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
|
|
// If defined in tgf.h:
|
|
// Use new Memory Manager ...
|
|
#ifdef __DEBUG_MEMORYMANAGER__
|
|
|
|
#if defined(_DEBUG)
|
|
fprintf(stderr,"__DEBUG_MEMORYMANAGER__ enabled\n\n");
|
|
fprintf(stderr,"If debugging -> Attach to the process ... \n");
|
|
fprintf(stderr,"\nand than press [Enter] to start the program\n");
|
|
getchar();
|
|
#endif
|
|
|
|
// THIS HAS TO BE THE FIRST LINE OF CODE (except the console output)!!!
|
|
GfMemoryManagerInitialize();
|
|
|
|
// For hunting of corrupted memory blocks comment the following line
|
|
//GfMemoryManagerSetup(4); // Add 4 bytes per block
|
|
#else
|
|
// Use local variables ...
|
|
IUserInterface* piUserItf = 0;
|
|
GfModule* pmodUserItf = NULL;
|
|
IRaceEngine* piRaceEngine = 0;
|
|
GfModule* pmodRaceEngine = NULL;
|
|
// ... Use local variables
|
|
#endif
|
|
// ... Use new Memeory Manager
|
|
|
|
// Look for the "text-only" option flag in the command-line args.
|
|
bool bTextOnly = false;
|
|
for (int i = 1; i < argc; i++)
|
|
if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--textonly"))
|
|
{
|
|
bTextOnly = true;
|
|
break;
|
|
}
|
|
|
|
// Create and initialize the application (graphical or text-only UI).
|
|
GfApplication* pApp;
|
|
if (bTextOnly)
|
|
pApp = new GfApplication("Speed Dreams", VERSION_LONG, "an Open Motorsport Sim");
|
|
else
|
|
pApp = new GfuiApplication("Speed Dreams", VERSION_LONG, "an Open Motorsport Sim");
|
|
pApp->initialize(/*bLoggingEnabled=*/true, argc, argv);
|
|
|
|
// Register app. specific options and help text.
|
|
pApp->registerOption("s", "startrace", /* nHasValue = */ true);
|
|
pApp->registerOption("x", "textonly", /* nHasValue = */ false);
|
|
|
|
pApp->addOptionsHelpSyntaxLine("[-s|--startrace <race name> [-x|--textonly] ]");
|
|
pApp->addOptionsHelpExplainLine
|
|
("- race name : Name without extension of the selected raceman file,");
|
|
pApp->addOptionsHelpExplainLine
|
|
(" among the .xml files in <user settings>/config/raceman (no default)");
|
|
pApp->addOptionsHelpExplainLine
|
|
("- text-only : Run the specified race without any GUI (suitable for a headless computer)");
|
|
|
|
// Parse the command line for registered options.
|
|
if (!pApp->parseOptions())
|
|
return 1;
|
|
|
|
// Some more checks about command line options.
|
|
std::string strRaceToStart;
|
|
if (bTextOnly && (!pApp->hasOption("startrace", strRaceToStart) || strRaceToStart.empty()))
|
|
{
|
|
std::cerr << "Exiting from " << pApp->name()
|
|
<< " because no race specified in text-only mode." << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
// If "data dir" specified in any way, cd to it.
|
|
if(chdir(GfDataDir()))
|
|
{
|
|
GfLogError("Could not start %s : failed to cd to the datadir '%s' (%s)\n",
|
|
pApp->name().c_str(), GfDataDir(), strerror(errno));
|
|
return 1;
|
|
}
|
|
|
|
// Update user settings files from installed ones.
|
|
pApp->updateUserSettings();
|
|
|
|
// Initialize the event loop management layer (graphical or text-only UI).
|
|
GfEventLoop* pEventLoop;
|
|
if (bTextOnly)
|
|
pEventLoop = new GfEventLoop;
|
|
else
|
|
pEventLoop = new GfuiEventLoop;
|
|
pApp->setEventLoop(pEventLoop);
|
|
|
|
// When there's a GUI, setup the window / screen and menu infrastructure.
|
|
if (!bTextOnly && !dynamic_cast<GfuiApplication*>(pApp)->setupWindow())
|
|
{
|
|
std::cerr << "Exiting from " << pApp->name()
|
|
<< " after some error occurred (see above)." << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
// Load the user interface module (graphical or text-only UI).
|
|
pmodUserItf =
|
|
GfModule::load("modules/userinterface", (bTextOnly ? "textonly" : "legacymenu"));
|
|
|
|
// Check that it implements IUserInterface.
|
|
if (pmodUserItf)
|
|
{
|
|
piUserItf = pmodUserItf->getInterface<IUserInterface>();
|
|
}
|
|
|
|
// Initialize the data layer (needed by any race engine module).
|
|
GfData::initialize();
|
|
|
|
// Load the race engine module (specified in the user settings : raceengine.xml file).
|
|
void* hREParams =
|
|
GfParmReadFileLocal(RACE_ENG_CFG, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
|
|
const char* pszModName = GfParmGetStr(hREParams, "Modules", "racing", "standardgame");
|
|
|
|
pmodRaceEngine = GfModule::load("modules/racing", pszModName);
|
|
|
|
// Check that it implements IRaceEngine.
|
|
if (pmodRaceEngine)
|
|
{
|
|
piRaceEngine = pmodRaceEngine->getInterface<IRaceEngine>();
|
|
}
|
|
|
|
// Connect the race engine and the user interface modules.
|
|
if (piUserItf && piRaceEngine)
|
|
{
|
|
piRaceEngine->setUserInterface(*piUserItf);
|
|
piUserItf->setRaceEngine(*piRaceEngine);
|
|
}
|
|
|
|
if (piUserItf && piRaceEngine)
|
|
{
|
|
#ifdef __DEBUG_MEMORYMANAGER__
|
|
// Allow to use Garbage Collection in case of GfuiApp().restart();
|
|
pApp->ReleaseData = &ReleaseData;
|
|
#endif
|
|
|
|
// Enter the user interface.
|
|
if (piUserItf->activate())
|
|
{
|
|
// Game event loop (when it returns, it's simply because we are exiting).
|
|
pApp->eventLoop()();
|
|
}
|
|
|
|
// Shutdown and unload the user interface and race engine modules.
|
|
piUserItf->shutdown();
|
|
piRaceEngine->shutdown();
|
|
|
|
GfModule::unload(pmodUserItf);
|
|
GfModule::unload(pmodRaceEngine);
|
|
|
|
// Shutdown the data layer.
|
|
GfData::shutdown();
|
|
}
|
|
|
|
// Done with the app instance.
|
|
const std::string strAppName(pApp->name());
|
|
delete pApp;
|
|
|
|
// That's all (but trace what we are doing).
|
|
if (piUserItf && piRaceEngine)
|
|
GfLogInfo("Exiting normally from %s.\n", strAppName.c_str());
|
|
else
|
|
GfLogInfo("Exiting from %s after some error occurred (see above).\n", strAppName.c_str());
|
|
|
|
GfTraceShutdown();
|
|
|
|
// If defined in tgf.h:
|
|
// Use new Memory Manager ...
|
|
#ifdef __DEBUG_MEMORYMANAGER__
|
|
|
|
GfMemoryManagerSaveToFile();
|
|
|
|
// THIS HAS TO BE THE LAST LINE OF CODE BEFORE RETURN!!!
|
|
GfMemoryManagerRelease();
|
|
|
|
#endif
|
|
// ... Use new Memory Manager
|
|
|
|
return (piUserItf && piRaceEngine) ? 0 : 1;
|
|
}
|
|
|