mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-12-03 09:22:45 +00:00
1710 lines
44 KiB
C++
1710 lines
44 KiB
C++
|
/*
|
||
|
===========================================================================
|
||
|
|
||
|
Doom 3 BFG Edition GPL Source Code
|
||
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||
|
|
||
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||
|
|
||
|
Doom 3 BFG Edition Source Code 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 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||
|
|
||
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||
|
|
||
|
===========================================================================
|
||
|
*/
|
||
|
|
||
|
#include "../idlib/precompiled.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "Common_local.h"
|
||
|
|
||
|
#include "ConsoleHistory.h"
|
||
|
#include "../renderer/AutoRenderBink.h"
|
||
|
|
||
|
#include "../sound/sound.h"
|
||
|
|
||
|
#include "../../doomclassic/doom/doomlib.h"
|
||
|
#include "../../doomclassic/doom/d_event.h"
|
||
|
#include "../../doomclassic/doom/d_main.h"
|
||
|
|
||
|
|
||
|
|
||
|
#include "../sys/sys_savegame.h"
|
||
|
|
||
|
#if defined( _DEBUG )
|
||
|
#define BUILD_DEBUG "-debug"
|
||
|
#else
|
||
|
#define BUILD_DEBUG ""
|
||
|
#endif
|
||
|
|
||
|
struct version_s {
|
||
|
version_s() { sprintf( string, "%s.%d%s %s %s %s", ENGINE_VERSION, BUILD_NUMBER, BUILD_DEBUG, BUILD_STRING, __DATE__, __TIME__ ); }
|
||
|
char string[256];
|
||
|
} version;
|
||
|
|
||
|
idCVar com_version( "si_version", version.string, CVAR_SYSTEM|CVAR_ROM|CVAR_SERVERINFO, "engine version" );
|
||
|
idCVar com_forceGenericSIMD( "com_forceGenericSIMD", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "force generic platform independent SIMD" );
|
||
|
|
||
|
#ifdef ID_RETAIL
|
||
|
idCVar com_allowConsole( "com_allowConsole", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_INIT, "allow toggling console with the tilde key" );
|
||
|
#else
|
||
|
idCVar com_allowConsole( "com_allowConsole", "1", CVAR_BOOL | CVAR_SYSTEM | CVAR_INIT, "allow toggling console with the tilde key" );
|
||
|
#endif
|
||
|
|
||
|
idCVar com_developer( "developer", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "developer mode" );
|
||
|
idCVar com_speeds( "com_speeds", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "show engine timings" );
|
||
|
idCVar com_showFPS( "com_showFPS", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_ARCHIVE|CVAR_NOCHEAT, "show frames rendered per second" );
|
||
|
idCVar com_showMemoryUsage( "com_showMemoryUsage", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "show total and per frame memory usage" );
|
||
|
idCVar com_updateLoadSize( "com_updateLoadSize", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "update the load size after loading a map" );
|
||
|
|
||
|
idCVar com_productionMode( "com_productionMode", "0", CVAR_SYSTEM | CVAR_BOOL, "0 - no special behavior, 1 - building a production build, 2 - running a production build" );
|
||
|
|
||
|
idCVar com_japaneseCensorship( "com_japaneseCensorship", "0", CVAR_NOCHEAT, "Enable Japanese censorship" );
|
||
|
|
||
|
idCVar preload_CommonAssets( "preload_CommonAssets", "1", CVAR_SYSTEM | CVAR_BOOL, "preload common assets" );
|
||
|
|
||
|
idCVar net_inviteOnly( "net_inviteOnly", "1", CVAR_BOOL | CVAR_ARCHIVE, "whether or not the private server you create allows friends to join or invite only" );
|
||
|
|
||
|
extern idCVar g_demoMode;
|
||
|
|
||
|
idCVar com_engineHz( "com_engineHz", "60", CVAR_FLOAT | CVAR_ARCHIVE, "Frames per second the engine runs at", 10.0f, 1024.0f );
|
||
|
float com_engineHz_latched = 60.0f; // Latched version of cvar, updated between map loads
|
||
|
int64 com_engineHz_numerator = 100LL * 1000LL;
|
||
|
int64 com_engineHz_denominator = 100LL * 60LL;
|
||
|
|
||
|
HWND com_hwndMsg = NULL;
|
||
|
|
||
|
#ifdef __DOOM_DLL__
|
||
|
idGame * game = NULL;
|
||
|
idGameEdit * gameEdit = NULL;
|
||
|
#endif
|
||
|
|
||
|
idCommonLocal commonLocal;
|
||
|
idCommon * common = &commonLocal;
|
||
|
|
||
|
|
||
|
idCVar com_skipIntroVideos( "com_skipIntroVideos", "0", CVAR_BOOL , "skips intro videos" );
|
||
|
|
||
|
// For doom classic
|
||
|
struct Globals;
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
idCommonLocal::idCommonLocal
|
||
|
==================
|
||
|
*/
|
||
|
idCommonLocal::idCommonLocal() :
|
||
|
readSnapshotIndex( 0 ),
|
||
|
writeSnapshotIndex( 0 ),
|
||
|
optimalTimeBuffered( 0.0f ),
|
||
|
optimalTimeBufferedWindow( 0.0f ),
|
||
|
optimalPCTBuffer( 0.5f ),
|
||
|
lastPacifierSessionTime( 0 ),
|
||
|
lastPacifierGuiTime( 0 ),
|
||
|
lastPacifierDialogState( false ),
|
||
|
showShellRequested( false ),
|
||
|
currentGame( DOOM3_BFG ),
|
||
|
idealCurrentGame( DOOM3_BFG ),
|
||
|
doomClassicMaterial( NULL )
|
||
|
{
|
||
|
|
||
|
snapCurrent.localTime = -1;
|
||
|
snapPrevious.localTime = -1;
|
||
|
snapCurrent.serverTime = -1;
|
||
|
snapPrevious.serverTime = -1;
|
||
|
snapTimeBuffered = 0.0f;
|
||
|
effectiveSnapRate = 0.0f;
|
||
|
totalBufferedTime = 0;
|
||
|
totalRecvTime = 0;
|
||
|
|
||
|
com_fullyInitialized = false;
|
||
|
com_refreshOnPrint = false;
|
||
|
com_errorEntered = ERP_NONE;
|
||
|
com_shuttingDown = false;
|
||
|
com_isJapaneseSKU = false;
|
||
|
|
||
|
logFile = NULL;
|
||
|
|
||
|
strcpy( errorMessage, "" );
|
||
|
|
||
|
rd_buffer = NULL;
|
||
|
rd_buffersize = 0;
|
||
|
rd_flush = NULL;
|
||
|
|
||
|
gameDLL = 0;
|
||
|
|
||
|
loadGUI = NULL;
|
||
|
nextLoadTip = 0;
|
||
|
isHellMap = false;
|
||
|
wipeForced = false;
|
||
|
defaultLoadscreen = false;
|
||
|
|
||
|
menuSoundWorld = NULL;
|
||
|
|
||
|
insideUpdateScreen = false;
|
||
|
insideExecuteMapChange = false;
|
||
|
|
||
|
mapSpawnData.savegameFile = NULL;
|
||
|
|
||
|
currentMapName.Clear();
|
||
|
aviDemoShortName.Clear();
|
||
|
|
||
|
renderWorld = NULL;
|
||
|
soundWorld = NULL;
|
||
|
menuSoundWorld = NULL;
|
||
|
readDemo = NULL;
|
||
|
writeDemo = NULL;
|
||
|
|
||
|
gameFrame = 0;
|
||
|
gameTimeResidual = 0;
|
||
|
syncNextGameFrame = true;
|
||
|
mapSpawned = false;
|
||
|
aviCaptureMode = false;
|
||
|
timeDemo = TD_NO;
|
||
|
|
||
|
nextSnapshotSendTime = 0;
|
||
|
nextUsercmdSendTime = 0;
|
||
|
|
||
|
clientPrediction = 0;
|
||
|
|
||
|
saveFile = NULL;
|
||
|
stringsFile = NULL;
|
||
|
|
||
|
ClearWipe();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
idCommonLocal::Quit
|
||
|
==================
|
||
|
*/
|
||
|
void idCommonLocal::Quit() {
|
||
|
|
||
|
// don't try to shutdown if we are in a recursive error
|
||
|
if ( !com_errorEntered ) {
|
||
|
Shutdown();
|
||
|
}
|
||
|
Sys_Quit();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
============================================================================
|
||
|
|
||
|
COMMAND LINE FUNCTIONS
|
||
|
|
||
|
+ characters separate the commandLine string into multiple console
|
||
|
command lines.
|
||
|
|
||
|
All of these are valid:
|
||
|
|
||
|
doom +set test blah +map test
|
||
|
doom set test blah+map test
|
||
|
doom set test blah + map test
|
||
|
|
||
|
============================================================================
|
||
|
*/
|
||
|
|
||
|
#define MAX_CONSOLE_LINES 32
|
||
|
int com_numConsoleLines;
|
||
|
idCmdArgs com_consoleLines[MAX_CONSOLE_LINES];
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
idCommonLocal::ParseCommandLine
|
||
|
==================
|
||
|
*/
|
||
|
void idCommonLocal::ParseCommandLine( int argc, const char * const * argv ) {
|
||
|
int i, current_count;
|
||
|
|
||
|
com_numConsoleLines = 0;
|
||
|
current_count = 0;
|
||
|
// API says no program path
|
||
|
for ( i = 0; i < argc; i++ ) {
|
||
|
if ( idStr::Icmp( argv[ i ], "+connect_lobby" ) == 0 ) {
|
||
|
// Handle Steam bootable invites.
|
||
|
session->HandleBootableInvite( _atoi64( argv[ i + 1 ] ) );
|
||
|
} else if ( argv[ i ][ 0 ] == '+' ) {
|
||
|
com_numConsoleLines++;
|
||
|
com_consoleLines[ com_numConsoleLines-1 ].AppendArg( argv[ i ] + 1 );
|
||
|
} else {
|
||
|
if ( !com_numConsoleLines ) {
|
||
|
com_numConsoleLines++;
|
||
|
}
|
||
|
com_consoleLines[ com_numConsoleLines-1 ].AppendArg( argv[ i ] );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
idCommonLocal::SafeMode
|
||
|
|
||
|
Check for "safe" on the command line, which will
|
||
|
skip loading of config file (DoomConfig.cfg)
|
||
|
==================
|
||
|
*/
|
||
|
bool idCommonLocal::SafeMode() {
|
||
|
int i;
|
||
|
|
||
|
for ( i = 0 ; i < com_numConsoleLines ; i++ ) {
|
||
|
if ( !idStr::Icmp( com_consoleLines[ i ].Argv(0), "safe" )
|
||
|
|| !idStr::Icmp( com_consoleLines[ i ].Argv(0), "cvar_restart" ) ) {
|
||
|
com_consoleLines[ i ].Clear();
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
idCommonLocal::StartupVariable
|
||
|
|
||
|
Searches for command line parameters that are set commands.
|
||
|
If match is not NULL, only that cvar will be looked for.
|
||
|
That is necessary because cddir and basedir need to be set
|
||
|
before the filesystem is started, but all other sets should
|
||
|
be after execing the config and default.
|
||
|
==================
|
||
|
*/
|
||
|
void idCommonLocal::StartupVariable( const char *match ) {
|
||
|
int i = 0;
|
||
|
while ( i < com_numConsoleLines ) {
|
||
|
if ( strcmp( com_consoleLines[ i ].Argv( 0 ), "set" ) != 0 ) {
|
||
|
i++;
|
||
|
continue;
|
||
|
}
|
||
|
const char * s = com_consoleLines[ i ].Argv(1);
|
||
|
|
||
|
if ( !match || !idStr::Icmp( s, match ) ) {
|
||
|
cvarSystem->SetCVarString( s, com_consoleLines[ i ].Argv( 2 ) );
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
idCommonLocal::AddStartupCommands
|
||
|
|
||
|
Adds command line parameters as script statements
|
||
|
Commands are separated by + signs
|
||
|
|
||
|
Returns true if any late commands were added, which
|
||
|
will keep the demoloop from immediately starting
|
||
|
==================
|
||
|
*/
|
||
|
void idCommonLocal::AddStartupCommands() {
|
||
|
// quote every token, so args with semicolons can work
|
||
|
for ( int i = 0; i < com_numConsoleLines; i++ ) {
|
||
|
if ( !com_consoleLines[i].Argc() ) {
|
||
|
continue;
|
||
|
}
|
||
|
// directly as tokenized so nothing gets screwed
|
||
|
cmdSystem->BufferCommandArgs( CMD_EXEC_APPEND, com_consoleLines[i] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
idCommonLocal::WriteConfigToFile
|
||
|
==================
|
||
|
*/
|
||
|
void idCommonLocal::WriteConfigToFile( const char *filename ) {
|
||
|
idFile * f = fileSystem->OpenFileWrite( filename );
|
||
|
if ( !f ) {
|
||
|
Printf ("Couldn't write %s.\n", filename );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
idKeyInput::WriteBindings( f );
|
||
|
cvarSystem->WriteFlaggedVariables( CVAR_ARCHIVE, "set", f );
|
||
|
fileSystem->CloseFile( f );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idCommonLocal::WriteConfiguration
|
||
|
|
||
|
Writes key bindings and archived cvars to config file if modified
|
||
|
===============
|
||
|
*/
|
||
|
void idCommonLocal::WriteConfiguration() {
|
||
|
// if we are quiting without fully initializing, make sure
|
||
|
// we don't write out anything
|
||
|
if ( !com_fullyInitialized ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !( cvarSystem->GetModifiedFlags() & CVAR_ARCHIVE ) ) {
|
||
|
return;
|
||
|
}
|
||
|
cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE );
|
||
|
|
||
|
// save to the profile
|
||
|
idLocalUser * user = session->GetSignInManager().GetMasterLocalUser();
|
||
|
if ( user != NULL ) {
|
||
|
user->SaveProfileSettings();
|
||
|
}
|
||
|
|
||
|
#ifdef CONFIG_FILE
|
||
|
// disable printing out the "Writing to:" message
|
||
|
bool developer = com_developer.GetBool();
|
||
|
com_developer.SetBool( false );
|
||
|
|
||
|
WriteConfigToFile( CONFIG_FILE );
|
||
|
|
||
|
// restore the developer cvar
|
||
|
com_developer.SetBool( developer );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
KeysFromBinding()
|
||
|
Returns the key bound to the command
|
||
|
===============
|
||
|
*/
|
||
|
const char* idCommonLocal::KeysFromBinding( const char *bind ) {
|
||
|
return idKeyInput::KeysFromBinding( bind );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
BindingFromKey()
|
||
|
Returns the binding bound to key
|
||
|
===============
|
||
|
*/
|
||
|
const char* idCommonLocal::BindingFromKey( const char *key ) {
|
||
|
return idKeyInput::BindingFromKey( key );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
ButtonState()
|
||
|
Returns the state of the button
|
||
|
===============
|
||
|
*/
|
||
|
int idCommonLocal::ButtonState( int key ) {
|
||
|
return usercmdGen->ButtonState(key);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
ButtonState()
|
||
|
Returns the state of the key
|
||
|
===============
|
||
|
*/
|
||
|
int idCommonLocal::KeyState( int key ) {
|
||
|
return usercmdGen->KeyState(key);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idCmdSystemLocal::PrintMemInfo_f
|
||
|
|
||
|
This prints out memory debugging data
|
||
|
============
|
||
|
*/
|
||
|
CONSOLE_COMMAND( printMemInfo, "prints memory debugging data", NULL ) {
|
||
|
MemInfo_t mi;
|
||
|
memset( &mi, 0, sizeof( mi ) );
|
||
|
mi.filebase = commonLocal.GetCurrentMapName();
|
||
|
|
||
|
renderSystem->PrintMemInfo( &mi ); // textures and models
|
||
|
soundSystem->PrintMemInfo( &mi ); // sounds
|
||
|
|
||
|
common->Printf( " Used image memory: %s bytes\n", idStr::FormatNumber( mi.imageAssetsTotal ).c_str() );
|
||
|
mi.assetTotals += mi.imageAssetsTotal;
|
||
|
|
||
|
common->Printf( " Used model memory: %s bytes\n", idStr::FormatNumber( mi.modelAssetsTotal ).c_str() );
|
||
|
mi.assetTotals += mi.modelAssetsTotal;
|
||
|
|
||
|
common->Printf( " Used sound memory: %s bytes\n", idStr::FormatNumber( mi.soundAssetsTotal ).c_str() );
|
||
|
mi.assetTotals += mi.soundAssetsTotal;
|
||
|
|
||
|
common->Printf( " Used asset memory: %s bytes\n", idStr::FormatNumber( mi.assetTotals ).c_str() );
|
||
|
|
||
|
// write overview file
|
||
|
idFile *f;
|
||
|
|
||
|
f = fileSystem->OpenFileAppend( "maps/printmeminfo.txt" );
|
||
|
if ( !f ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
f->Printf( "total(%s ) image(%s ) model(%s ) sound(%s ): %s\n", idStr::FormatNumber( mi.assetTotals ).c_str(), idStr::FormatNumber( mi.imageAssetsTotal ).c_str(),
|
||
|
idStr::FormatNumber( mi.modelAssetsTotal ).c_str(), idStr::FormatNumber( mi.soundAssetsTotal ).c_str(), mi.filebase.c_str() );
|
||
|
|
||
|
fileSystem->CloseFile( f );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
Com_Error_f
|
||
|
|
||
|
Just throw a fatal error to test error shutdown procedures.
|
||
|
==================
|
||
|
*/
|
||
|
CONSOLE_COMMAND( error, "causes an error", NULL ) {
|
||
|
if ( !com_developer.GetBool() ) {
|
||
|
commonLocal.Printf( "error may only be used in developer mode\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( args.Argc() > 1 ) {
|
||
|
commonLocal.FatalError( "Testing fatal error" );
|
||
|
} else {
|
||
|
commonLocal.Error( "Testing drop error" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
Com_Freeze_f
|
||
|
|
||
|
Just freeze in place for a given number of seconds to test error recovery.
|
||
|
==================
|
||
|
*/
|
||
|
CONSOLE_COMMAND( freeze, "freezes the game for a number of seconds", NULL ) {
|
||
|
float s;
|
||
|
int start, now;
|
||
|
|
||
|
if ( args.Argc() != 2 ) {
|
||
|
commonLocal.Printf( "freeze <seconds>\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !com_developer.GetBool() ) {
|
||
|
commonLocal.Printf( "freeze may only be used in developer mode\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
s = atof( args.Argv(1) );
|
||
|
|
||
|
start = eventLoop->Milliseconds();
|
||
|
|
||
|
while ( 1 ) {
|
||
|
now = eventLoop->Milliseconds();
|
||
|
if ( ( now - start ) * 0.001f > s ) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
Com_Crash_f
|
||
|
|
||
|
A way to force a bus error for development reasons
|
||
|
=================
|
||
|
*/
|
||
|
CONSOLE_COMMAND( crash, "causes a crash", NULL ) {
|
||
|
if ( !com_developer.GetBool() ) {
|
||
|
commonLocal.Printf( "crash may only be used in developer mode\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
* ( int * ) 0 = 0x12345678;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
Com_Quit_f
|
||
|
=================
|
||
|
*/
|
||
|
CONSOLE_COMMAND_SHIP( quit, "quits the game", NULL ) {
|
||
|
commonLocal.Quit();
|
||
|
}
|
||
|
CONSOLE_COMMAND_SHIP( exit, "exits the game", NULL ) {
|
||
|
commonLocal.Quit();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
Com_WriteConfig_f
|
||
|
|
||
|
Write the config file to a specific name
|
||
|
===============
|
||
|
*/
|
||
|
CONSOLE_COMMAND( writeConfig, "writes a config file", NULL ) {
|
||
|
idStr filename;
|
||
|
|
||
|
if ( args.Argc() != 2 ) {
|
||
|
commonLocal.Printf( "Usage: writeconfig <filename>\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
filename = args.Argv(1);
|
||
|
filename.DefaultFileExtension( ".cfg" );
|
||
|
commonLocal.Printf( "Writing %s.\n", filename.c_str() );
|
||
|
commonLocal.WriteConfigToFile( filename );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
========================
|
||
|
idCommonLocal::CheckStartupStorageRequirements
|
||
|
========================
|
||
|
*/
|
||
|
void idCommonLocal::CheckStartupStorageRequirements() {
|
||
|
int64 availableSpace = 0;
|
||
|
// ------------------------------------------------------------------------
|
||
|
// Savegame and Profile required storage
|
||
|
// ------------------------------------------------------------------------
|
||
|
{
|
||
|
// Make sure the save path exists in case it was deleted.
|
||
|
// If the path cannot be created we can safely assume there is no
|
||
|
// free space because in that case nothing can be saved anyway.
|
||
|
const char * savepath = cvarSystem->GetCVarString( "fs_savepath" );
|
||
|
idStr directory = savepath;
|
||
|
//idStr directory = fs_savepath.GetString();
|
||
|
directory += "\\"; // so it doesn't think the last part is a file and ignores in the directory creation
|
||
|
fileSystem->CreateOSPath( directory );
|
||
|
|
||
|
// Get the free space on the save path.
|
||
|
availableSpace = Sys_GetDriveFreeSpaceInBytes( savepath );
|
||
|
|
||
|
// If free space fails then get space on drive as a fall back
|
||
|
// (the directory will be created later anyway)
|
||
|
if ( availableSpace <= 1 ) {
|
||
|
idStr savePath( savepath );
|
||
|
if ( savePath.Length() >= 3 ) {
|
||
|
if ( savePath[ 1 ] == ':' && savePath[ 2 ] == '\\' &&
|
||
|
( ( savePath[ 0 ] >= 'A' && savePath[ 0 ] <= 'Z' ) ||
|
||
|
( savePath[ 0 ] >= 'a' && savePath[ 0 ] <= 'z' ) ) ) {
|
||
|
savePath = savePath.Left( 3 );
|
||
|
availableSpace = Sys_GetDriveFreeSpaceInBytes( savePath );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const int MIN_SAVE_STORAGE_PROFILE = 1024 * 1024;
|
||
|
const int MIN_SAVE_STORAGE_SAVEGAME = MIN_SAVEGAME_SIZE_BYTES;
|
||
|
|
||
|
uint64 requiredSizeBytes = MIN_SAVE_STORAGE_SAVEGAME + MIN_SAVE_STORAGE_PROFILE;
|
||
|
|
||
|
idLib::Printf( "requiredSizeBytes: %lld\n", requiredSizeBytes );
|
||
|
|
||
|
if ( (int64)( requiredSizeBytes - availableSpace ) > 0 ) {
|
||
|
class idSWFScriptFunction_Continue : public idSWFScriptFunction_RefCounted {
|
||
|
public:
|
||
|
virtual ~idSWFScriptFunction_Continue() {}
|
||
|
idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
|
||
|
common->Dialog().ClearDialog( GDM_INSUFFICENT_STORAGE_SPACE );
|
||
|
common->Quit();
|
||
|
return idSWFScriptVar();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
idStaticList< idSWFScriptFunction *, 4 > callbacks;
|
||
|
idStaticList< idStrId, 4 > optionText;
|
||
|
callbacks.Append( new (TAG_SWF) idSWFScriptFunction_Continue() );
|
||
|
optionText.Append( idStrId( "#STR_SWF_ACCEPT" ) );
|
||
|
|
||
|
// build custom space required string
|
||
|
// #str_dlg_space_required ~= "There is insufficient storage available. Please free %s and try again."
|
||
|
idStr format = idStrId( "#str_dlg_startup_insufficient_storage" ).GetLocalizedString();
|
||
|
idStr size;
|
||
|
if ( requiredSizeBytes > ( 1024 * 1024 ) ) {
|
||
|
size = va( "%.1f MB", (float)requiredSizeBytes / ( 1024.0f * 1024.0f ) + 0.1f ); // +0.1 to avoid truncation
|
||
|
} else {
|
||
|
size = va( "%.1f KB", (float)requiredSizeBytes / 1024.0f + 0.1f );
|
||
|
}
|
||
|
idStr msg = va( format.c_str(), size.c_str() );
|
||
|
|
||
|
common->Dialog().AddDynamicDialog( GDM_INSUFFICENT_STORAGE_SPACE, callbacks, optionText, true, msg );
|
||
|
}
|
||
|
|
||
|
|
||
|
session->GetAchievementSystem().Start();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idCommonLocal::JapaneseCensorship
|
||
|
===============
|
||
|
*/
|
||
|
bool idCommonLocal::JapaneseCensorship() const {
|
||
|
return com_japaneseCensorship.GetBool() || com_isJapaneseSKU;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idCommonLocal::FilterLangList
|
||
|
===============
|
||
|
*/
|
||
|
void idCommonLocal::FilterLangList( idStrList* list, idStr lang ) {
|
||
|
|
||
|
idStr temp;
|
||
|
for( int i = 0; i < list->Num(); i++ ) {
|
||
|
temp = (*list)[i];
|
||
|
temp = temp.Right(temp.Length()-strlen("strings/"));
|
||
|
temp = temp.Left(lang.Length());
|
||
|
if(idStr::Icmp(temp, lang) != 0) {
|
||
|
list->RemoveIndex(i);
|
||
|
i--;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idCommonLocal::InitLanguageDict
|
||
|
===============
|
||
|
*/
|
||
|
extern idCVar sys_lang;
|
||
|
void idCommonLocal::InitLanguageDict() {
|
||
|
idStr fileName;
|
||
|
|
||
|
//D3XP: Instead of just loading a single lang file for each language
|
||
|
//we are going to load all files that begin with the language name
|
||
|
//similar to the way pak files work. So you can place english001.lang
|
||
|
//to add new strings to the english language dictionary
|
||
|
idFileList* langFiles;
|
||
|
langFiles = fileSystem->ListFilesTree( "strings", ".lang", true );
|
||
|
|
||
|
idStrList langList = langFiles->GetList();
|
||
|
|
||
|
// Loop through the list and filter
|
||
|
idStrList currentLangList = langList;
|
||
|
FilterLangList( ¤tLangList, sys_lang.GetString() );
|
||
|
|
||
|
if ( currentLangList.Num() == 0 ) {
|
||
|
// reset to english and try to load again
|
||
|
sys_lang.SetString( ID_LANG_ENGLISH );
|
||
|
currentLangList = langList;
|
||
|
FilterLangList( ¤tLangList, sys_lang.GetString() );
|
||
|
}
|
||
|
|
||
|
idLocalization::ClearDictionary();
|
||
|
for( int i = 0; i < currentLangList.Num(); i++ ) {
|
||
|
//common->Printf("%s\n", currentLangList[i].c_str());
|
||
|
const byte * buffer = NULL;
|
||
|
int len = fileSystem->ReadFile( currentLangList[i], (void**)&buffer );
|
||
|
if ( len <= 0 ) {
|
||
|
assert( false && "couldn't read the language dict file" );
|
||
|
break;
|
||
|
}
|
||
|
idLocalization::LoadDictionary( buffer, len, currentLangList[i] );
|
||
|
fileSystem->FreeFile( (void *)buffer );
|
||
|
}
|
||
|
|
||
|
fileSystem->FreeFileList(langFiles);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
ReloadLanguage_f
|
||
|
=================
|
||
|
*/
|
||
|
CONSOLE_COMMAND( reloadLanguage, "reload language dict", NULL ) {
|
||
|
commonLocal.InitLanguageDict();
|
||
|
}
|
||
|
|
||
|
#include "../renderer/Image.h"
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
Com_StartBuild_f
|
||
|
=================
|
||
|
*/
|
||
|
CONSOLE_COMMAND( startBuild, "prepares to make a build", NULL ) {
|
||
|
globalImages->StartBuild();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
Com_FinishBuild_f
|
||
|
=================
|
||
|
*/
|
||
|
CONSOLE_COMMAND( finishBuild, "finishes the build process", NULL ) {
|
||
|
if ( game ) {
|
||
|
game->CacheDictionaryMedia( NULL );
|
||
|
}
|
||
|
globalImages->FinishBuild( ( args.Argc() > 1 ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
idCommonLocal::RenderSplash
|
||
|
=================
|
||
|
*/
|
||
|
void idCommonLocal::RenderSplash() {
|
||
|
const float sysWidth = renderSystem->GetWidth() * renderSystem->GetPixelAspect();
|
||
|
const float sysHeight = renderSystem->GetHeight();
|
||
|
const float sysAspect = sysWidth / sysHeight;
|
||
|
const float splashAspect = 16.0f / 9.0f;
|
||
|
const float adjustment = sysAspect / splashAspect;
|
||
|
const float barHeight = ( adjustment >= 1.0f ) ? 0.0f : ( 1.0f - adjustment ) * (float)SCREEN_HEIGHT * 0.25f;
|
||
|
const float barWidth = ( adjustment <= 1.0f ) ? 0.0f : ( adjustment - 1.0f ) * (float)SCREEN_WIDTH * 0.25f;
|
||
|
if ( barHeight > 0.0f ) {
|
||
|
renderSystem->SetColor( colorBlack );
|
||
|
renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, barHeight, 0, 0, 1, 1, whiteMaterial );
|
||
|
renderSystem->DrawStretchPic( 0, SCREEN_HEIGHT - barHeight, SCREEN_WIDTH, barHeight, 0, 0, 1, 1, whiteMaterial );
|
||
|
}
|
||
|
if ( barWidth > 0.0f ) {
|
||
|
renderSystem->SetColor( colorBlack );
|
||
|
renderSystem->DrawStretchPic( 0, 0, barWidth, SCREEN_HEIGHT, 0, 0, 1, 1, whiteMaterial );
|
||
|
renderSystem->DrawStretchPic( SCREEN_WIDTH - barWidth, 0, barWidth, SCREEN_HEIGHT, 0, 0, 1, 1, whiteMaterial );
|
||
|
}
|
||
|
renderSystem->SetColor4( 1, 1, 1, 1 );
|
||
|
renderSystem->DrawStretchPic( barWidth, barHeight, SCREEN_WIDTH - barWidth * 2.0f, SCREEN_HEIGHT - barHeight * 2.0f, 0, 0, 1, 1, splashScreen );
|
||
|
|
||
|
const emptyCommand_t * cmd = renderSystem->SwapCommandBuffers( &time_frontend, &time_backend, &time_shadows, &time_gpu );
|
||
|
renderSystem->RenderCommandBuffers( cmd );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
idCommonLocal::RenderBink
|
||
|
=================
|
||
|
*/
|
||
|
void idCommonLocal::RenderBink( const char * path ) {
|
||
|
const float sysWidth = renderSystem->GetWidth() * renderSystem->GetPixelAspect();
|
||
|
const float sysHeight = renderSystem->GetHeight();
|
||
|
const float sysAspect = sysWidth / sysHeight;
|
||
|
const float movieAspect = ( 16.0f / 9.0f );
|
||
|
const float imageWidth = SCREEN_WIDTH * movieAspect / sysAspect;
|
||
|
const float chop = 0.5f * ( SCREEN_WIDTH - imageWidth );
|
||
|
|
||
|
idStr materialText;
|
||
|
materialText.Format( "{ translucent { videoMap %s } }", path );
|
||
|
|
||
|
idMaterial * material = const_cast<idMaterial*>( declManager->FindMaterial( "splashbink" ) );
|
||
|
material->Parse( materialText.c_str(), materialText.Length(), false );
|
||
|
material->ResetCinematicTime( Sys_Milliseconds() );
|
||
|
|
||
|
while ( Sys_Milliseconds() <= material->GetCinematicStartTime() + material->CinematicLength() ) {
|
||
|
renderSystem->DrawStretchPic( chop, 0, imageWidth, SCREEN_HEIGHT, 0, 0, 1, 1, material );
|
||
|
const emptyCommand_t * cmd = renderSystem->SwapCommandBuffers( &time_frontend, &time_backend, &time_shadows, &time_gpu );
|
||
|
renderSystem->RenderCommandBuffers( cmd );
|
||
|
Sys_GenerateEvents();
|
||
|
Sys_Sleep( 10 );
|
||
|
}
|
||
|
|
||
|
material->MakeDefault();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
idCommonLocal::InitSIMD
|
||
|
=================
|
||
|
*/
|
||
|
void idCommonLocal::InitSIMD() {
|
||
|
idSIMD::InitProcessor( "doom", com_forceGenericSIMD.GetBool() );
|
||
|
com_forceGenericSIMD.ClearModified();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
idCommonLocal::LoadGameDLL
|
||
|
=================
|
||
|
*/
|
||
|
void idCommonLocal::LoadGameDLL() {
|
||
|
#ifdef __DOOM_DLL__
|
||
|
char dllPath[ MAX_OSPATH ];
|
||
|
|
||
|
gameImport_t gameImport;
|
||
|
gameExport_t gameExport;
|
||
|
GetGameAPI_t GetGameAPI;
|
||
|
|
||
|
fileSystem->FindDLL( "game", dllPath, true );
|
||
|
|
||
|
if ( !dllPath[ 0 ] ) {
|
||
|
common->FatalError( "couldn't find game dynamic library" );
|
||
|
return;
|
||
|
}
|
||
|
common->DPrintf( "Loading game DLL: '%s'\n", dllPath );
|
||
|
gameDLL = sys->DLL_Load( dllPath );
|
||
|
if ( !gameDLL ) {
|
||
|
common->FatalError( "couldn't load game dynamic library" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const char * functionName = "GetGameAPI";
|
||
|
GetGameAPI = (GetGameAPI_t) Sys_DLL_GetProcAddress( gameDLL, functionName );
|
||
|
if ( !GetGameAPI ) {
|
||
|
Sys_DLL_Unload( gameDLL );
|
||
|
gameDLL = NULL;
|
||
|
common->FatalError( "couldn't find game DLL API" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
gameImport.version = GAME_API_VERSION;
|
||
|
gameImport.sys = ::sys;
|
||
|
gameImport.common = ::common;
|
||
|
gameImport.cmdSystem = ::cmdSystem;
|
||
|
gameImport.cvarSystem = ::cvarSystem;
|
||
|
gameImport.fileSystem = ::fileSystem;
|
||
|
gameImport.renderSystem = ::renderSystem;
|
||
|
gameImport.soundSystem = ::soundSystem;
|
||
|
gameImport.renderModelManager = ::renderModelManager;
|
||
|
gameImport.uiManager = ::uiManager;
|
||
|
gameImport.declManager = ::declManager;
|
||
|
gameImport.AASFileManager = ::AASFileManager;
|
||
|
gameImport.collisionModelManager = ::collisionModelManager;
|
||
|
|
||
|
gameExport = *GetGameAPI( &gameImport );
|
||
|
|
||
|
if ( gameExport.version != GAME_API_VERSION ) {
|
||
|
Sys_DLL_Unload( gameDLL );
|
||
|
gameDLL = NULL;
|
||
|
common->FatalError( "wrong game DLL API version" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
game = gameExport.game;
|
||
|
gameEdit = gameExport.gameEdit;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
// initialize the game object
|
||
|
if ( game != NULL ) {
|
||
|
game->Init();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
idCommonLocal::UnloadGameDLL
|
||
|
=================
|
||
|
*/
|
||
|
void idCommonLocal::CleanupShell() {
|
||
|
if ( game != NULL ) {
|
||
|
game->Shell_Cleanup();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
idCommonLocal::UnloadGameDLL
|
||
|
=================
|
||
|
*/
|
||
|
void idCommonLocal::UnloadGameDLL() {
|
||
|
|
||
|
// shut down the game object
|
||
|
if ( game != NULL ) {
|
||
|
game->Shutdown();
|
||
|
}
|
||
|
|
||
|
#ifdef __DOOM_DLL__
|
||
|
|
||
|
if ( gameDLL ) {
|
||
|
Sys_DLL_Unload( gameDLL );
|
||
|
gameDLL = NULL;
|
||
|
}
|
||
|
game = NULL;
|
||
|
gameEdit = NULL;
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
idCommonLocal::IsInitialized
|
||
|
=================
|
||
|
*/
|
||
|
bool idCommonLocal::IsInitialized() const {
|
||
|
return com_fullyInitialized;
|
||
|
}
|
||
|
|
||
|
|
||
|
//======================================================================================
|
||
|
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
idCommonLocal::Init
|
||
|
=================
|
||
|
*/
|
||
|
void idCommonLocal::Init( int argc, const char * const * argv, const char *cmdline ) {
|
||
|
try {
|
||
|
// set interface pointers used by idLib
|
||
|
idLib::sys = sys;
|
||
|
idLib::common = common;
|
||
|
idLib::cvarSystem = cvarSystem;
|
||
|
idLib::fileSystem = fileSystem;
|
||
|
|
||
|
// initialize idLib
|
||
|
idLib::Init();
|
||
|
|
||
|
// clear warning buffer
|
||
|
ClearWarnings( GAME_NAME " initialization" );
|
||
|
|
||
|
idLib::Printf( va( "Command line: %s\n", cmdline ) );
|
||
|
//::MessageBox( NULL, cmdline, "blah", MB_OK );
|
||
|
// parse command line options
|
||
|
idCmdArgs args;
|
||
|
if ( cmdline ) {
|
||
|
// tokenize if the OS doesn't do it for us
|
||
|
args.TokenizeString( cmdline, true );
|
||
|
argv = args.GetArgs( &argc );
|
||
|
}
|
||
|
ParseCommandLine( argc, argv );
|
||
|
|
||
|
// init console command system
|
||
|
cmdSystem->Init();
|
||
|
|
||
|
// init CVar system
|
||
|
cvarSystem->Init();
|
||
|
|
||
|
// register all static CVars
|
||
|
idCVar::RegisterStaticVars();
|
||
|
|
||
|
idLib::Printf( "QA Timing INIT: %06dms\n", Sys_Milliseconds() );
|
||
|
|
||
|
// print engine version
|
||
|
Printf( "%s\n", version.string );
|
||
|
|
||
|
// initialize key input/binding, done early so bind command exists
|
||
|
idKeyInput::Init();
|
||
|
|
||
|
// init the console so we can take prints
|
||
|
console->Init();
|
||
|
|
||
|
// get architecture info
|
||
|
Sys_Init();
|
||
|
|
||
|
// initialize networking
|
||
|
Sys_InitNetworking();
|
||
|
|
||
|
// override cvars from command line
|
||
|
StartupVariable( NULL );
|
||
|
|
||
|
consoleUsed = com_allowConsole.GetBool();
|
||
|
|
||
|
if ( Sys_AlreadyRunning() ) {
|
||
|
Sys_Quit();
|
||
|
}
|
||
|
|
||
|
// initialize processor specific SIMD implementation
|
||
|
InitSIMD();
|
||
|
|
||
|
// initialize the file system
|
||
|
fileSystem->Init();
|
||
|
|
||
|
const char * defaultLang = Sys_DefaultLanguage();
|
||
|
com_isJapaneseSKU = ( idStr::Icmp( defaultLang, ID_LANG_JAPANESE ) == 0 );
|
||
|
|
||
|
// Allow the system to set a default lanugage
|
||
|
Sys_SetLanguageFromSystem();
|
||
|
|
||
|
// Pre-allocate our 20 MB save buffer here on time, instead of on-demand for each save....
|
||
|
|
||
|
saveFile.SetNameAndType( SAVEGAME_CHECKPOINT_FILENAME, SAVEGAMEFILE_BINARY );
|
||
|
saveFile.PreAllocate( MIN_SAVEGAME_SIZE_BYTES );
|
||
|
|
||
|
stringsFile.SetNameAndType( SAVEGAME_STRINGS_FILENAME, SAVEGAMEFILE_BINARY );
|
||
|
stringsFile.PreAllocate( MAX_SAVEGAME_STRING_TABLE_SIZE );
|
||
|
|
||
|
fileSystem->BeginLevelLoad( "_startup", saveFile.GetDataPtr(), saveFile.GetAllocated() );
|
||
|
|
||
|
// initialize the declaration manager
|
||
|
declManager->Init();
|
||
|
|
||
|
// init journalling, etc
|
||
|
eventLoop->Init();
|
||
|
|
||
|
// init the parallel job manager
|
||
|
parallelJobManager->Init();
|
||
|
|
||
|
// exec the startup scripts
|
||
|
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "exec default.cfg\n" );
|
||
|
|
||
|
#ifdef CONFIG_FILE
|
||
|
// skip the config file if "safe" is on the command line
|
||
|
if ( !SafeMode() && !g_demoMode.GetBool() ) {
|
||
|
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "exec " CONFIG_FILE "\n" );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "exec autoexec.cfg\n" );
|
||
|
|
||
|
// run cfg execution
|
||
|
cmdSystem->ExecuteCommandBuffer();
|
||
|
|
||
|
// re-override anything from the config files with command line args
|
||
|
StartupVariable( NULL );
|
||
|
|
||
|
// if any archived cvars are modified after this, we will trigger a writing of the config file
|
||
|
cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE );
|
||
|
|
||
|
// init OpenGL, which will open a window and connect sound and input hardware
|
||
|
renderSystem->InitOpenGL();
|
||
|
|
||
|
// Support up to 2 digits after the decimal point
|
||
|
com_engineHz_denominator = 100LL * com_engineHz.GetFloat();
|
||
|
com_engineHz_latched = com_engineHz.GetFloat();
|
||
|
|
||
|
// start the sound system, but don't do any hardware operations yet
|
||
|
soundSystem->Init();
|
||
|
|
||
|
// initialize the renderSystem data structures
|
||
|
renderSystem->Init();
|
||
|
|
||
|
whiteMaterial = declManager->FindMaterial( "_white" );
|
||
|
|
||
|
if ( idStr::Icmp( sys_lang.GetString(), ID_LANG_FRENCH ) == 0 ) {
|
||
|
// If the user specified french, we show french no matter what SKU
|
||
|
splashScreen = declManager->FindMaterial( "guis/assets/splash/legal_french" );
|
||
|
} else if ( idStr::Icmp( defaultLang, ID_LANG_FRENCH ) == 0 ) {
|
||
|
// If the lead sku is french (ie: europe), display figs
|
||
|
splashScreen = declManager->FindMaterial( "guis/assets/splash/legal_figs" );
|
||
|
} else {
|
||
|
// Otherwise show it in english
|
||
|
splashScreen = declManager->FindMaterial( "guis/assets/splash/legal_english" );
|
||
|
}
|
||
|
|
||
|
const int legalMinTime = 4000;
|
||
|
const bool showVideo = ( !com_skipIntroVideos.GetBool () && fileSystem->UsingResourceFiles() );
|
||
|
if ( showVideo ) {
|
||
|
RenderBink( "video\\loadvideo.bik" );
|
||
|
RenderSplash();
|
||
|
RenderSplash();
|
||
|
} else {
|
||
|
idLib::Printf( "Skipping Intro Videos!\n" );
|
||
|
// display the legal splash screen
|
||
|
// No clue why we have to render this twice to show up...
|
||
|
RenderSplash();
|
||
|
RenderSplash();
|
||
|
}
|
||
|
|
||
|
|
||
|
int legalStartTime = Sys_Milliseconds();
|
||
|
declManager->Init2();
|
||
|
|
||
|
// initialize string database so we can use it for loading messages
|
||
|
InitLanguageDict();
|
||
|
|
||
|
// spawn the game thread, even if we are going to run without SMP
|
||
|
// one meg stack, because it can parse decls from gui surfaces (unfortunately)
|
||
|
// use a lower priority so job threads can run on the same core
|
||
|
gameThread.StartWorkerThread( "Game/Draw", CORE_1B, THREAD_BELOW_NORMAL, 0x100000 );
|
||
|
// boost this thread's priority, so it will prevent job threads from running while
|
||
|
// the render back end still has work to do
|
||
|
|
||
|
// init the user command input code
|
||
|
usercmdGen->Init();
|
||
|
|
||
|
Sys_SetRumble( 0, 0, 0 );
|
||
|
|
||
|
// initialize the user interfaces
|
||
|
uiManager->Init();
|
||
|
|
||
|
// startup the script debugger
|
||
|
// DebuggerServerInit();
|
||
|
|
||
|
// load the game dll
|
||
|
LoadGameDLL();
|
||
|
|
||
|
// On the PC touch them all so they get included in the resource build
|
||
|
if ( !fileSystem->UsingResourceFiles() ) {
|
||
|
declManager->FindMaterial( "guis/assets/splash/legal_english" );
|
||
|
declManager->FindMaterial( "guis/assets/splash/legal_french" );
|
||
|
declManager->FindMaterial( "guis/assets/splash/legal_figs" );
|
||
|
// register the japanese font so it gets included
|
||
|
renderSystem->RegisterFont( "DFPHeiseiGothicW7" );
|
||
|
// Make sure all videos get touched because you can bring videos from one map to another, they need to be included in all maps
|
||
|
for ( int i = 0; i < declManager->GetNumDecls( DECL_VIDEO ); i++ ) {
|
||
|
declManager->DeclByIndex( DECL_VIDEO, i );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fileSystem->UnloadResourceContainer( "_ordered" );
|
||
|
|
||
|
// the same idRenderWorld will be used for all games
|
||
|
// and demos, insuring that level specific models
|
||
|
// will be freed
|
||
|
renderWorld = renderSystem->AllocRenderWorld();
|
||
|
soundWorld = soundSystem->AllocSoundWorld( renderWorld );
|
||
|
|
||
|
menuSoundWorld = soundSystem->AllocSoundWorld( NULL );
|
||
|
menuSoundWorld->PlaceListener( vec3_origin, mat3_identity, 0 );
|
||
|
|
||
|
// init the session
|
||
|
session->Initialize();
|
||
|
session->InitializeSoundRelatedSystems();
|
||
|
|
||
|
InitializeMPMapsModes();
|
||
|
|
||
|
// leaderboards need to be initialized after InitializeMPMapsModes, which populates the MP Map list.
|
||
|
if( game != NULL ) {
|
||
|
game->Leaderboards_Init();
|
||
|
}
|
||
|
|
||
|
CreateMainMenu();
|
||
|
|
||
|
commonDialog.Init();
|
||
|
|
||
|
// load the console history file
|
||
|
consoleHistory.LoadHistoryFile();
|
||
|
|
||
|
AddStartupCommands();
|
||
|
|
||
|
StartMenu( true );
|
||
|
|
||
|
while ( Sys_Milliseconds() - legalStartTime < legalMinTime ) {
|
||
|
RenderSplash();
|
||
|
Sys_GenerateEvents();
|
||
|
Sys_Sleep( 10 );
|
||
|
};
|
||
|
|
||
|
// print all warnings queued during initialization
|
||
|
PrintWarnings();
|
||
|
|
||
|
// remove any prints from the notify lines
|
||
|
console->ClearNotifyLines();
|
||
|
|
||
|
CheckStartupStorageRequirements();
|
||
|
|
||
|
|
||
|
if ( preload_CommonAssets.GetBool() && fileSystem->UsingResourceFiles() ) {
|
||
|
idPreloadManifest manifest;
|
||
|
manifest.LoadManifest( "_common.preload" );
|
||
|
globalImages->Preload( manifest, false );
|
||
|
soundSystem->Preload( manifest );
|
||
|
}
|
||
|
|
||
|
fileSystem->EndLevelLoad();
|
||
|
|
||
|
// Initialize support for Doom classic.
|
||
|
doomClassicMaterial = declManager->FindMaterial( "_doomClassic" );
|
||
|
idImage *image = globalImages->GetImage( "_doomClassic" );
|
||
|
if ( image != NULL ) {
|
||
|
idImageOpts opts;
|
||
|
opts.format = FMT_RGBA8;
|
||
|
opts.colorFormat = CFM_DEFAULT;
|
||
|
opts.width = DOOMCLASSIC_RENDERWIDTH;
|
||
|
opts.height = DOOMCLASSIC_RENDERHEIGHT;
|
||
|
opts.numLevels = 1;
|
||
|
image->AllocImage( opts, TF_LINEAR, TR_REPEAT );
|
||
|
}
|
||
|
|
||
|
com_fullyInitialized = true;
|
||
|
|
||
|
|
||
|
// No longer need the splash screen
|
||
|
if ( splashScreen != NULL ) {
|
||
|
for ( int i = 0; i < splashScreen->GetNumStages(); i++ ) {
|
||
|
idImage * image = splashScreen->GetStage( i )->texture.image;
|
||
|
if ( image != NULL ) {
|
||
|
image->PurgeImage();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Printf( "--- Common Initialization Complete ---\n" );
|
||
|
|
||
|
idLib::Printf( "QA Timing IIS: %06dms\n", Sys_Milliseconds() );
|
||
|
} catch( idException & ) {
|
||
|
Sys_Error( "Error during initialization" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
idCommonLocal::Shutdown
|
||
|
=================
|
||
|
*/
|
||
|
void idCommonLocal::Shutdown() {
|
||
|
|
||
|
if ( com_shuttingDown ) {
|
||
|
return;
|
||
|
}
|
||
|
com_shuttingDown = true;
|
||
|
|
||
|
|
||
|
// Kill any pending saves...
|
||
|
printf( "session->GetSaveGameManager().CancelToTerminate();\n" );
|
||
|
session->GetSaveGameManager().CancelToTerminate();
|
||
|
|
||
|
// kill sound first
|
||
|
printf( "soundSystem->StopAllSounds();\n" );
|
||
|
soundSystem->StopAllSounds();
|
||
|
|
||
|
// shutdown the script debugger
|
||
|
// DebuggerServerShutdown();
|
||
|
|
||
|
if ( aviCaptureMode ) {
|
||
|
printf( "EndAVICapture();\n" );
|
||
|
EndAVICapture();
|
||
|
}
|
||
|
|
||
|
printf( "Stop();\n" );
|
||
|
Stop();
|
||
|
|
||
|
printf( "CleanupShell();\n" );
|
||
|
CleanupShell();
|
||
|
|
||
|
printf( "delete loadGUI;\n" );
|
||
|
delete loadGUI;
|
||
|
loadGUI = NULL;
|
||
|
|
||
|
printf( "delete renderWorld;\n" );
|
||
|
delete renderWorld;
|
||
|
renderWorld = NULL;
|
||
|
|
||
|
printf( "delete soundWorld;\n" );
|
||
|
delete soundWorld;
|
||
|
soundWorld = NULL;
|
||
|
|
||
|
printf( "delete menuSoundWorld;\n" );
|
||
|
delete menuSoundWorld;
|
||
|
menuSoundWorld = NULL;
|
||
|
|
||
|
// shut down the session
|
||
|
printf( "session->ShutdownSoundRelatedSystems();\n" );
|
||
|
session->ShutdownSoundRelatedSystems();
|
||
|
printf( "session->Shutdown();\n" );
|
||
|
session->Shutdown();
|
||
|
|
||
|
// shutdown, deallocate leaderboard definitions.
|
||
|
if( game != NULL ) {
|
||
|
printf( "game->Leaderboards_Shutdown();\n" );
|
||
|
game->Leaderboards_Shutdown();
|
||
|
}
|
||
|
|
||
|
// shut down the user interfaces
|
||
|
printf( "uiManager->Shutdown();\n" );
|
||
|
uiManager->Shutdown();
|
||
|
|
||
|
// shut down the sound system
|
||
|
printf( "soundSystem->Shutdown();\n" );
|
||
|
soundSystem->Shutdown();
|
||
|
|
||
|
// shut down the user command input code
|
||
|
printf( "usercmdGen->Shutdown();\n" );
|
||
|
usercmdGen->Shutdown();
|
||
|
|
||
|
// shut down the event loop
|
||
|
printf( "eventLoop->Shutdown();\n" );
|
||
|
eventLoop->Shutdown();
|
||
|
|
||
|
// shutdown the decl manager
|
||
|
printf( "declManager->Shutdown();\n" );
|
||
|
declManager->Shutdown();
|
||
|
|
||
|
// shut down the renderSystem
|
||
|
printf( "renderSystem->Shutdown();\n" );
|
||
|
renderSystem->Shutdown();
|
||
|
|
||
|
printf( "commonDialog.Shutdown();\n" );
|
||
|
commonDialog.Shutdown();
|
||
|
|
||
|
// unload the game dll
|
||
|
printf( "UnloadGameDLL();\n" );
|
||
|
UnloadGameDLL();
|
||
|
|
||
|
printf( "saveFile.Clear( true );\n" );
|
||
|
saveFile.Clear( true );
|
||
|
printf( "stringsFile.Clear( true );\n" );
|
||
|
stringsFile.Clear( true );
|
||
|
|
||
|
// only shut down the log file after all output is done
|
||
|
printf( "CloseLogFile();\n" );
|
||
|
CloseLogFile();
|
||
|
|
||
|
// shut down the file system
|
||
|
printf( "fileSystem->Shutdown( false );\n" );
|
||
|
fileSystem->Shutdown( false );
|
||
|
|
||
|
// shut down non-portable system services
|
||
|
printf( "Sys_Shutdown();\n" );
|
||
|
Sys_Shutdown();
|
||
|
|
||
|
// shut down the console
|
||
|
printf( "console->Shutdown();\n" );
|
||
|
console->Shutdown();
|
||
|
|
||
|
// shut down the key system
|
||
|
printf( "idKeyInput::Shutdown();\n" );
|
||
|
idKeyInput::Shutdown();
|
||
|
|
||
|
// shut down the cvar system
|
||
|
printf( "cvarSystem->Shutdown();\n" );
|
||
|
cvarSystem->Shutdown();
|
||
|
|
||
|
// shut down the console command system
|
||
|
printf( "cmdSystem->Shutdown();\n" );
|
||
|
cmdSystem->Shutdown();
|
||
|
|
||
|
// free any buffered warning messages
|
||
|
printf( "ClearWarnings( GAME_NAME \" shutdown\" );\n" );
|
||
|
ClearWarnings( GAME_NAME " shutdown" );
|
||
|
printf( "warningCaption.Clear();\n" );
|
||
|
warningCaption.Clear();
|
||
|
printf( "errorList.Clear();\n" );
|
||
|
errorList.Clear();
|
||
|
|
||
|
// shutdown idLib
|
||
|
printf( "idLib::ShutDown();\n" );
|
||
|
idLib::ShutDown();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
========================
|
||
|
idCommonLocal::CreateMainMenu
|
||
|
========================
|
||
|
*/
|
||
|
void idCommonLocal::CreateMainMenu() {
|
||
|
if ( game != NULL ) {
|
||
|
// note which media we are going to need to load
|
||
|
declManager->BeginLevelLoad();
|
||
|
renderSystem->BeginLevelLoad();
|
||
|
soundSystem->BeginLevelLoad();
|
||
|
uiManager->BeginLevelLoad();
|
||
|
|
||
|
// create main inside an "empty" game level load - so assets get
|
||
|
// purged automagically when we transition to a "real" map
|
||
|
game->Shell_CreateMenu( false );
|
||
|
game->Shell_Show( true );
|
||
|
game->Shell_SyncWithSession();
|
||
|
|
||
|
// load
|
||
|
renderSystem->EndLevelLoad();
|
||
|
soundSystem->EndLevelLoad();
|
||
|
declManager->EndLevelLoad();
|
||
|
uiManager->EndLevelLoad( "" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idCommonLocal::Stop
|
||
|
|
||
|
called on errors and game exits
|
||
|
===============
|
||
|
*/
|
||
|
void idCommonLocal::Stop( bool resetSession ) {
|
||
|
ClearWipe();
|
||
|
|
||
|
// clear mapSpawned and demo playing flags
|
||
|
UnloadMap();
|
||
|
|
||
|
soundSystem->StopAllSounds();
|
||
|
|
||
|
insideUpdateScreen = false;
|
||
|
insideExecuteMapChange = false;
|
||
|
|
||
|
// drop all guis
|
||
|
ExitMenu();
|
||
|
|
||
|
if ( resetSession ) {
|
||
|
session->QuitMatchToTitle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idCommonLocal::BusyWait
|
||
|
===============
|
||
|
*/
|
||
|
void idCommonLocal::BusyWait() {
|
||
|
Sys_GenerateEvents();
|
||
|
|
||
|
const bool captureToImage = false;
|
||
|
UpdateScreen( captureToImage );
|
||
|
|
||
|
session->UpdateSignInManager();
|
||
|
session->Pump();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idCommonLocal::WaitForSessionState
|
||
|
===============
|
||
|
*/
|
||
|
bool idCommonLocal::WaitForSessionState( idSession::sessionState_t desiredState ) {
|
||
|
if ( session->GetState() == desiredState ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
while ( true ) {
|
||
|
BusyWait();
|
||
|
|
||
|
idSession::sessionState_t sessionState = session->GetState();
|
||
|
if ( sessionState == desiredState ) {
|
||
|
return true;
|
||
|
}
|
||
|
if ( sessionState != idSession::LOADING &&
|
||
|
sessionState != idSession::SEARCHING &&
|
||
|
sessionState != idSession::CONNECTING &&
|
||
|
sessionState != idSession::BUSY &&
|
||
|
sessionState != desiredState ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
Sys_Sleep( 10 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
========================
|
||
|
idCommonLocal::LeaveGame
|
||
|
========================
|
||
|
*/
|
||
|
void idCommonLocal::LeaveGame() {
|
||
|
|
||
|
const bool captureToImage = false;
|
||
|
UpdateScreen( captureToImage );
|
||
|
|
||
|
ResetNetworkingState();
|
||
|
|
||
|
|
||
|
Stop( false );
|
||
|
|
||
|
CreateMainMenu();
|
||
|
|
||
|
StartMenu();
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idCommonLocal::ProcessEvent
|
||
|
===============
|
||
|
*/
|
||
|
bool idCommonLocal::ProcessEvent( const sysEvent_t *event ) {
|
||
|
// hitting escape anywhere brings up the menu
|
||
|
if ( game && game->IsInGame() ) {
|
||
|
if ( event->evType == SE_KEY && event->evValue2 == 1 && ( event->evValue == K_ESCAPE || event->evValue == K_JOY9 ) ) {
|
||
|
if ( !game->Shell_IsActive() ) {
|
||
|
|
||
|
// menus / etc
|
||
|
if ( MenuEvent( event ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
console->Close();
|
||
|
|
||
|
StartMenu();
|
||
|
return true;
|
||
|
} else {
|
||
|
console->Close();
|
||
|
|
||
|
// menus / etc
|
||
|
if ( MenuEvent( event ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
game->Shell_ClosePause();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// let the pull-down console take it if desired
|
||
|
if ( console->ProcessEvent( event, false ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
if ( session->ProcessInputEvent( event ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if ( Dialog().IsDialogActive() ) {
|
||
|
Dialog().HandleDialogEvent( event );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Let Doom classic run events.
|
||
|
if ( IsPlayingDoomClassic() ) {
|
||
|
// Translate the event to Doom classic format.
|
||
|
event_t classicEvent;
|
||
|
if ( event->evType == SE_KEY ) {
|
||
|
|
||
|
if( event->evValue2 == 1 ) {
|
||
|
classicEvent.type = ev_keydown;
|
||
|
} else if( event->evValue2 == 0 ) {
|
||
|
classicEvent.type = ev_keyup;
|
||
|
}
|
||
|
|
||
|
DoomLib::SetPlayer( 0 );
|
||
|
|
||
|
extern Globals * g;
|
||
|
if ( g != NULL ) {
|
||
|
classicEvent.data1 = DoomLib::RemapControl( event->GetKey() );
|
||
|
|
||
|
D_PostEvent( &classicEvent );
|
||
|
}
|
||
|
DoomLib::SetPlayer( -1 );
|
||
|
}
|
||
|
|
||
|
// Let the classics eat all events.
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// menus / etc
|
||
|
if ( MenuEvent( event ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// if we aren't in a game, force the console to take it
|
||
|
if ( !mapSpawned ) {
|
||
|
console->ProcessEvent( event, true );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// in game, exec bindings for all key downs
|
||
|
if ( event->evType == SE_KEY && event->evValue2 == 1 ) {
|
||
|
idKeyInput::ExecKeyBinding( event->evValue );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
========================
|
||
|
idCommonLocal::ResetPlayerInput
|
||
|
========================
|
||
|
*/
|
||
|
void idCommonLocal::ResetPlayerInput( int playerIndex ) {
|
||
|
userCmdMgr.ResetPlayer( playerIndex );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
========================
|
||
|
idCommonLocal::SwitchToGame
|
||
|
========================
|
||
|
*/
|
||
|
void idCommonLocal::SwitchToGame( currentGame_t newGame ) {
|
||
|
idealCurrentGame = newGame;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
========================
|
||
|
idCommonLocal::PerformGameSwitch
|
||
|
========================
|
||
|
*/
|
||
|
void idCommonLocal::PerformGameSwitch() {
|
||
|
// If the session state is past the menu, we should be in Doom 3.
|
||
|
// This will happen if, for example, we accept an invite while playing
|
||
|
// Doom or Doom 2.
|
||
|
if ( session->GetState() > idSession::IDLE ) {
|
||
|
idealCurrentGame = DOOM3_BFG;
|
||
|
}
|
||
|
|
||
|
if ( currentGame == idealCurrentGame ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const int DOOM_CLASSIC_HZ = 35;
|
||
|
|
||
|
if ( idealCurrentGame == DOOM_CLASSIC || idealCurrentGame == DOOM2_CLASSIC ) {
|
||
|
// Pause Doom 3 sound.
|
||
|
if ( menuSoundWorld != NULL ) {
|
||
|
menuSoundWorld->Pause();
|
||
|
}
|
||
|
|
||
|
DoomLib::skipToNew = false;
|
||
|
DoomLib::skipToLoad = false;
|
||
|
|
||
|
// Reset match parameters for the classics.
|
||
|
DoomLib::matchParms = idMatchParameters();
|
||
|
|
||
|
// The classics use the usercmd manager too, clear it.
|
||
|
userCmdMgr.SetDefaults();
|
||
|
|
||
|
// Classics need a local user too.
|
||
|
session->UpdateSignInManager();
|
||
|
session->GetSignInManager().RegisterLocalUser( 0 );
|
||
|
|
||
|
com_engineHz_denominator = 100LL * DOOM_CLASSIC_HZ;
|
||
|
com_engineHz_latched = DOOM_CLASSIC_HZ;
|
||
|
|
||
|
DoomLib::SetCurrentExpansion( idealCurrentGame );
|
||
|
|
||
|
} else if ( idealCurrentGame == DOOM3_BFG ) {
|
||
|
DoomLib::Interface.Shutdown();
|
||
|
com_engineHz_denominator = 100LL * com_engineHz.GetFloat();
|
||
|
com_engineHz_latched = com_engineHz.GetFloat();
|
||
|
|
||
|
// Don't MoveToPressStart if we have an invite, we need to go
|
||
|
// directly to the lobby.
|
||
|
if ( session->GetState() <= idSession::IDLE ) {
|
||
|
session->MoveToPressStart();
|
||
|
}
|
||
|
|
||
|
// Unpause Doom 3 sound.
|
||
|
if ( menuSoundWorld != NULL ) {
|
||
|
menuSoundWorld->UnPause();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
currentGame = idealCurrentGame;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
Common_WritePrecache_f
|
||
|
==================
|
||
|
*/
|
||
|
CONSOLE_COMMAND( writePrecache, "writes precache commands", NULL ) {
|
||
|
if ( args.Argc() != 2 ) {
|
||
|
common->Printf( "USAGE: writePrecache <execFile>\n" );
|
||
|
return;
|
||
|
}
|
||
|
idStr str = args.Argv(1);
|
||
|
str.DefaultFileExtension( ".cfg" );
|
||
|
idFile *f = fileSystem->OpenFileWrite( str );
|
||
|
declManager->WritePrecacheCommands( f );
|
||
|
renderModelManager->WritePrecacheCommands( f );
|
||
|
uiManager->WritePrecacheCommands( f );
|
||
|
|
||
|
fileSystem->CloseFile( f );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
Common_Disconnect_f
|
||
|
================
|
||
|
*/
|
||
|
CONSOLE_COMMAND_SHIP( disconnect, "disconnects from a game", NULL ) {
|
||
|
session->QuitMatch();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
Common_Hitch_f
|
||
|
===============
|
||
|
*/
|
||
|
CONSOLE_COMMAND( hitch, "hitches the game", NULL ) {
|
||
|
if ( args.Argc() == 2 ) {
|
||
|
Sys_Sleep( atoi(args.Argv(1)) );
|
||
|
} else {
|
||
|
Sys_Sleep( 100 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CONSOLE_COMMAND( showStringMemory, "shows memory used by strings", NULL ) {
|
||
|
idStr::ShowMemoryUsage_f( args );
|
||
|
}
|
||
|
CONSOLE_COMMAND( showDictMemory, "shows memory used by dictionaries", NULL ) {
|
||
|
idDict::ShowMemoryUsage_f( args );
|
||
|
}
|
||
|
CONSOLE_COMMAND( listDictKeys, "lists all keys used by dictionaries", NULL ) {
|
||
|
idDict::ListKeys_f( args );
|
||
|
}
|
||
|
CONSOLE_COMMAND( listDictValues, "lists all values used by dictionaries", NULL ) {
|
||
|
idDict::ListValues_f( args );
|
||
|
}
|
||
|
CONSOLE_COMMAND( testSIMD, "test SIMD code", NULL ) {
|
||
|
idSIMD::Test_f( args );
|
||
|
}
|