Common.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "Common_local.h"
  23. #include "ConsoleHistory.h"
  24. #include "../renderer/AutoRenderBink.h"
  25. #include "../sound/sound.h"
  26. #include "../../doomclassic/doom/doomlib.h"
  27. #include "../../doomclassic/doom/d_event.h"
  28. #include "../../doomclassic/doom/d_main.h"
  29. #include "../sys/sys_savegame.h"
  30. #if defined( _DEBUG )
  31. #define BUILD_DEBUG "-debug"
  32. #else
  33. #define BUILD_DEBUG ""
  34. #endif
  35. struct version_s {
  36. version_s() { sprintf( string, "%s.%d%s %s %s %s", ENGINE_VERSION, BUILD_NUMBER, BUILD_DEBUG, BUILD_STRING, __DATE__, __TIME__ ); }
  37. char string[256];
  38. } version;
  39. idCVar com_version( "si_version", version.string, CVAR_SYSTEM|CVAR_ROM|CVAR_SERVERINFO, "engine version" );
  40. idCVar com_forceGenericSIMD( "com_forceGenericSIMD", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "force generic platform independent SIMD" );
  41. #ifdef ID_RETAIL
  42. idCVar com_allowConsole( "com_allowConsole", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_INIT, "allow toggling console with the tilde key" );
  43. #else
  44. idCVar com_allowConsole( "com_allowConsole", "1", CVAR_BOOL | CVAR_SYSTEM | CVAR_INIT, "allow toggling console with the tilde key" );
  45. #endif
  46. idCVar com_developer( "developer", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "developer mode" );
  47. idCVar com_speeds( "com_speeds", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "show engine timings" );
  48. idCVar com_showFPS( "com_showFPS", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_ARCHIVE|CVAR_NOCHEAT, "show frames rendered per second" );
  49. idCVar com_showMemoryUsage( "com_showMemoryUsage", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "show total and per frame memory usage" );
  50. idCVar com_updateLoadSize( "com_updateLoadSize", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "update the load size after loading a map" );
  51. idCVar com_productionMode( "com_productionMode", "0", CVAR_SYSTEM | CVAR_BOOL, "0 - no special behavior, 1 - building a production build, 2 - running a production build" );
  52. idCVar com_japaneseCensorship( "com_japaneseCensorship", "0", CVAR_NOCHEAT, "Enable Japanese censorship" );
  53. idCVar preload_CommonAssets( "preload_CommonAssets", "1", CVAR_SYSTEM | CVAR_BOOL, "preload common assets" );
  54. 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" );
  55. extern idCVar g_demoMode;
  56. idCVar com_engineHz( "com_engineHz", "60", CVAR_FLOAT | CVAR_ARCHIVE, "Frames per second the engine runs at", 10.0f, 1024.0f );
  57. float com_engineHz_latched = 60.0f; // Latched version of cvar, updated between map loads
  58. int64 com_engineHz_numerator = 100LL * 1000LL;
  59. int64 com_engineHz_denominator = 100LL * 60LL;
  60. HWND com_hwndMsg = NULL;
  61. #ifdef __DOOM_DLL__
  62. idGame * game = NULL;
  63. idGameEdit * gameEdit = NULL;
  64. #endif
  65. idCommonLocal commonLocal;
  66. idCommon * common = &commonLocal;
  67. idCVar com_skipIntroVideos( "com_skipIntroVideos", "0", CVAR_BOOL , "skips intro videos" );
  68. // For doom classic
  69. struct Globals;
  70. /*
  71. ==================
  72. idCommonLocal::idCommonLocal
  73. ==================
  74. */
  75. idCommonLocal::idCommonLocal() :
  76. readSnapshotIndex( 0 ),
  77. writeSnapshotIndex( 0 ),
  78. optimalTimeBuffered( 0.0f ),
  79. optimalTimeBufferedWindow( 0.0f ),
  80. optimalPCTBuffer( 0.5f ),
  81. lastPacifierSessionTime( 0 ),
  82. lastPacifierGuiTime( 0 ),
  83. lastPacifierDialogState( false ),
  84. showShellRequested( false ),
  85. currentGame( DOOM3_BFG ),
  86. idealCurrentGame( DOOM3_BFG ),
  87. doomClassicMaterial( NULL )
  88. {
  89. snapCurrent.localTime = -1;
  90. snapPrevious.localTime = -1;
  91. snapCurrent.serverTime = -1;
  92. snapPrevious.serverTime = -1;
  93. snapTimeBuffered = 0.0f;
  94. effectiveSnapRate = 0.0f;
  95. totalBufferedTime = 0;
  96. totalRecvTime = 0;
  97. com_fullyInitialized = false;
  98. com_refreshOnPrint = false;
  99. com_errorEntered = ERP_NONE;
  100. com_shuttingDown = false;
  101. com_isJapaneseSKU = false;
  102. logFile = NULL;
  103. strcpy( errorMessage, "" );
  104. rd_buffer = NULL;
  105. rd_buffersize = 0;
  106. rd_flush = NULL;
  107. gameDLL = 0;
  108. loadGUI = NULL;
  109. nextLoadTip = 0;
  110. isHellMap = false;
  111. wipeForced = false;
  112. defaultLoadscreen = false;
  113. menuSoundWorld = NULL;
  114. insideUpdateScreen = false;
  115. insideExecuteMapChange = false;
  116. mapSpawnData.savegameFile = NULL;
  117. currentMapName.Clear();
  118. aviDemoShortName.Clear();
  119. renderWorld = NULL;
  120. soundWorld = NULL;
  121. menuSoundWorld = NULL;
  122. readDemo = NULL;
  123. writeDemo = NULL;
  124. gameFrame = 0;
  125. gameTimeResidual = 0;
  126. syncNextGameFrame = true;
  127. mapSpawned = false;
  128. aviCaptureMode = false;
  129. timeDemo = TD_NO;
  130. nextSnapshotSendTime = 0;
  131. nextUsercmdSendTime = 0;
  132. clientPrediction = 0;
  133. saveFile = NULL;
  134. stringsFile = NULL;
  135. ClearWipe();
  136. }
  137. /*
  138. ==================
  139. idCommonLocal::Quit
  140. ==================
  141. */
  142. void idCommonLocal::Quit() {
  143. // don't try to shutdown if we are in a recursive error
  144. if ( !com_errorEntered ) {
  145. Shutdown();
  146. }
  147. Sys_Quit();
  148. }
  149. /*
  150. ============================================================================
  151. COMMAND LINE FUNCTIONS
  152. + characters separate the commandLine string into multiple console
  153. command lines.
  154. All of these are valid:
  155. doom +set test blah +map test
  156. doom set test blah+map test
  157. doom set test blah + map test
  158. ============================================================================
  159. */
  160. #define MAX_CONSOLE_LINES 32
  161. int com_numConsoleLines;
  162. idCmdArgs com_consoleLines[MAX_CONSOLE_LINES];
  163. /*
  164. ==================
  165. idCommonLocal::ParseCommandLine
  166. ==================
  167. */
  168. void idCommonLocal::ParseCommandLine( int argc, const char * const * argv ) {
  169. int i, current_count;
  170. com_numConsoleLines = 0;
  171. current_count = 0;
  172. // API says no program path
  173. for ( i = 0; i < argc; i++ ) {
  174. if ( idStr::Icmp( argv[ i ], "+connect_lobby" ) == 0 ) {
  175. // Handle Steam bootable invites.
  176. session->HandleBootableInvite( _atoi64( argv[ i + 1 ] ) );
  177. } else if ( argv[ i ][ 0 ] == '+' ) {
  178. com_numConsoleLines++;
  179. com_consoleLines[ com_numConsoleLines-1 ].AppendArg( argv[ i ] + 1 );
  180. } else {
  181. if ( !com_numConsoleLines ) {
  182. com_numConsoleLines++;
  183. }
  184. com_consoleLines[ com_numConsoleLines-1 ].AppendArg( argv[ i ] );
  185. }
  186. }
  187. }
  188. /*
  189. ==================
  190. idCommonLocal::SafeMode
  191. Check for "safe" on the command line, which will
  192. skip loading of config file (DoomConfig.cfg)
  193. ==================
  194. */
  195. bool idCommonLocal::SafeMode() {
  196. int i;
  197. for ( i = 0 ; i < com_numConsoleLines ; i++ ) {
  198. if ( !idStr::Icmp( com_consoleLines[ i ].Argv(0), "safe" )
  199. || !idStr::Icmp( com_consoleLines[ i ].Argv(0), "cvar_restart" ) ) {
  200. com_consoleLines[ i ].Clear();
  201. return true;
  202. }
  203. }
  204. return false;
  205. }
  206. /*
  207. ==================
  208. idCommonLocal::StartupVariable
  209. Searches for command line parameters that are set commands.
  210. If match is not NULL, only that cvar will be looked for.
  211. That is necessary because cddir and basedir need to be set
  212. before the filesystem is started, but all other sets should
  213. be after execing the config and default.
  214. ==================
  215. */
  216. void idCommonLocal::StartupVariable( const char *match ) {
  217. int i = 0;
  218. while ( i < com_numConsoleLines ) {
  219. if ( strcmp( com_consoleLines[ i ].Argv( 0 ), "set" ) != 0 ) {
  220. i++;
  221. continue;
  222. }
  223. const char * s = com_consoleLines[ i ].Argv(1);
  224. if ( !match || !idStr::Icmp( s, match ) ) {
  225. cvarSystem->SetCVarString( s, com_consoleLines[ i ].Argv( 2 ) );
  226. }
  227. i++;
  228. }
  229. }
  230. /*
  231. ==================
  232. idCommonLocal::AddStartupCommands
  233. Adds command line parameters as script statements
  234. Commands are separated by + signs
  235. Returns true if any late commands were added, which
  236. will keep the demoloop from immediately starting
  237. ==================
  238. */
  239. void idCommonLocal::AddStartupCommands() {
  240. // quote every token, so args with semicolons can work
  241. for ( int i = 0; i < com_numConsoleLines; i++ ) {
  242. if ( !com_consoleLines[i].Argc() ) {
  243. continue;
  244. }
  245. // directly as tokenized so nothing gets screwed
  246. cmdSystem->BufferCommandArgs( CMD_EXEC_APPEND, com_consoleLines[i] );
  247. }
  248. }
  249. /*
  250. ==================
  251. idCommonLocal::WriteConfigToFile
  252. ==================
  253. */
  254. void idCommonLocal::WriteConfigToFile( const char *filename ) {
  255. idFile * f = fileSystem->OpenFileWrite( filename );
  256. if ( !f ) {
  257. Printf ("Couldn't write %s.\n", filename );
  258. return;
  259. }
  260. idKeyInput::WriteBindings( f );
  261. cvarSystem->WriteFlaggedVariables( CVAR_ARCHIVE, "set", f );
  262. fileSystem->CloseFile( f );
  263. }
  264. /*
  265. ===============
  266. idCommonLocal::WriteConfiguration
  267. Writes key bindings and archived cvars to config file if modified
  268. ===============
  269. */
  270. void idCommonLocal::WriteConfiguration() {
  271. // if we are quiting without fully initializing, make sure
  272. // we don't write out anything
  273. if ( !com_fullyInitialized ) {
  274. return;
  275. }
  276. if ( !( cvarSystem->GetModifiedFlags() & CVAR_ARCHIVE ) ) {
  277. return;
  278. }
  279. cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE );
  280. // save to the profile
  281. idLocalUser * user = session->GetSignInManager().GetMasterLocalUser();
  282. if ( user != NULL ) {
  283. user->SaveProfileSettings();
  284. }
  285. #ifdef CONFIG_FILE
  286. // disable printing out the "Writing to:" message
  287. bool developer = com_developer.GetBool();
  288. com_developer.SetBool( false );
  289. WriteConfigToFile( CONFIG_FILE );
  290. // restore the developer cvar
  291. com_developer.SetBool( developer );
  292. #endif
  293. }
  294. /*
  295. ===============
  296. KeysFromBinding()
  297. Returns the key bound to the command
  298. ===============
  299. */
  300. const char* idCommonLocal::KeysFromBinding( const char *bind ) {
  301. return idKeyInput::KeysFromBinding( bind );
  302. }
  303. /*
  304. ===============
  305. BindingFromKey()
  306. Returns the binding bound to key
  307. ===============
  308. */
  309. const char* idCommonLocal::BindingFromKey( const char *key ) {
  310. return idKeyInput::BindingFromKey( key );
  311. }
  312. /*
  313. ===============
  314. ButtonState()
  315. Returns the state of the button
  316. ===============
  317. */
  318. int idCommonLocal::ButtonState( int key ) {
  319. return usercmdGen->ButtonState(key);
  320. }
  321. /*
  322. ===============
  323. ButtonState()
  324. Returns the state of the key
  325. ===============
  326. */
  327. int idCommonLocal::KeyState( int key ) {
  328. return usercmdGen->KeyState(key);
  329. }
  330. /*
  331. ============
  332. idCmdSystemLocal::PrintMemInfo_f
  333. This prints out memory debugging data
  334. ============
  335. */
  336. CONSOLE_COMMAND( printMemInfo, "prints memory debugging data", NULL ) {
  337. MemInfo_t mi;
  338. memset( &mi, 0, sizeof( mi ) );
  339. mi.filebase = commonLocal.GetCurrentMapName();
  340. renderSystem->PrintMemInfo( &mi ); // textures and models
  341. soundSystem->PrintMemInfo( &mi ); // sounds
  342. common->Printf( " Used image memory: %s bytes\n", idStr::FormatNumber( mi.imageAssetsTotal ).c_str() );
  343. mi.assetTotals += mi.imageAssetsTotal;
  344. common->Printf( " Used model memory: %s bytes\n", idStr::FormatNumber( mi.modelAssetsTotal ).c_str() );
  345. mi.assetTotals += mi.modelAssetsTotal;
  346. common->Printf( " Used sound memory: %s bytes\n", idStr::FormatNumber( mi.soundAssetsTotal ).c_str() );
  347. mi.assetTotals += mi.soundAssetsTotal;
  348. common->Printf( " Used asset memory: %s bytes\n", idStr::FormatNumber( mi.assetTotals ).c_str() );
  349. // write overview file
  350. idFile *f;
  351. f = fileSystem->OpenFileAppend( "maps/printmeminfo.txt" );
  352. if ( !f ) {
  353. return;
  354. }
  355. f->Printf( "total(%s ) image(%s ) model(%s ) sound(%s ): %s\n", idStr::FormatNumber( mi.assetTotals ).c_str(), idStr::FormatNumber( mi.imageAssetsTotal ).c_str(),
  356. idStr::FormatNumber( mi.modelAssetsTotal ).c_str(), idStr::FormatNumber( mi.soundAssetsTotal ).c_str(), mi.filebase.c_str() );
  357. fileSystem->CloseFile( f );
  358. }
  359. /*
  360. ==================
  361. Com_Error_f
  362. Just throw a fatal error to test error shutdown procedures.
  363. ==================
  364. */
  365. CONSOLE_COMMAND( error, "causes an error", NULL ) {
  366. if ( !com_developer.GetBool() ) {
  367. commonLocal.Printf( "error may only be used in developer mode\n" );
  368. return;
  369. }
  370. if ( args.Argc() > 1 ) {
  371. commonLocal.FatalError( "Testing fatal error" );
  372. } else {
  373. commonLocal.Error( "Testing drop error" );
  374. }
  375. }
  376. /*
  377. ==================
  378. Com_Freeze_f
  379. Just freeze in place for a given number of seconds to test error recovery.
  380. ==================
  381. */
  382. CONSOLE_COMMAND( freeze, "freezes the game for a number of seconds", NULL ) {
  383. float s;
  384. int start, now;
  385. if ( args.Argc() != 2 ) {
  386. commonLocal.Printf( "freeze <seconds>\n" );
  387. return;
  388. }
  389. if ( !com_developer.GetBool() ) {
  390. commonLocal.Printf( "freeze may only be used in developer mode\n" );
  391. return;
  392. }
  393. s = atof( args.Argv(1) );
  394. start = eventLoop->Milliseconds();
  395. while ( 1 ) {
  396. now = eventLoop->Milliseconds();
  397. if ( ( now - start ) * 0.001f > s ) {
  398. break;
  399. }
  400. }
  401. }
  402. /*
  403. =================
  404. Com_Crash_f
  405. A way to force a bus error for development reasons
  406. =================
  407. */
  408. CONSOLE_COMMAND( crash, "causes a crash", NULL ) {
  409. if ( !com_developer.GetBool() ) {
  410. commonLocal.Printf( "crash may only be used in developer mode\n" );
  411. return;
  412. }
  413. * ( int * ) 0 = 0x12345678;
  414. }
  415. /*
  416. =================
  417. Com_Quit_f
  418. =================
  419. */
  420. CONSOLE_COMMAND_SHIP( quit, "quits the game", NULL ) {
  421. commonLocal.Quit();
  422. }
  423. CONSOLE_COMMAND_SHIP( exit, "exits the game", NULL ) {
  424. commonLocal.Quit();
  425. }
  426. /*
  427. ===============
  428. Com_WriteConfig_f
  429. Write the config file to a specific name
  430. ===============
  431. */
  432. CONSOLE_COMMAND( writeConfig, "writes a config file", NULL ) {
  433. idStr filename;
  434. if ( args.Argc() != 2 ) {
  435. commonLocal.Printf( "Usage: writeconfig <filename>\n" );
  436. return;
  437. }
  438. filename = args.Argv(1);
  439. filename.DefaultFileExtension( ".cfg" );
  440. commonLocal.Printf( "Writing %s.\n", filename.c_str() );
  441. commonLocal.WriteConfigToFile( filename );
  442. }
  443. /*
  444. ========================
  445. idCommonLocal::CheckStartupStorageRequirements
  446. ========================
  447. */
  448. void idCommonLocal::CheckStartupStorageRequirements() {
  449. int64 availableSpace = 0;
  450. // ------------------------------------------------------------------------
  451. // Savegame and Profile required storage
  452. // ------------------------------------------------------------------------
  453. {
  454. // Make sure the save path exists in case it was deleted.
  455. // If the path cannot be created we can safely assume there is no
  456. // free space because in that case nothing can be saved anyway.
  457. const char * savepath = cvarSystem->GetCVarString( "fs_savepath" );
  458. idStr directory = savepath;
  459. //idStr directory = fs_savepath.GetString();
  460. directory += "\\"; // so it doesn't think the last part is a file and ignores in the directory creation
  461. fileSystem->CreateOSPath( directory );
  462. // Get the free space on the save path.
  463. availableSpace = Sys_GetDriveFreeSpaceInBytes( savepath );
  464. // If free space fails then get space on drive as a fall back
  465. // (the directory will be created later anyway)
  466. if ( availableSpace <= 1 ) {
  467. idStr savePath( savepath );
  468. if ( savePath.Length() >= 3 ) {
  469. if ( savePath[ 1 ] == ':' && savePath[ 2 ] == '\\' &&
  470. ( ( savePath[ 0 ] >= 'A' && savePath[ 0 ] <= 'Z' ) ||
  471. ( savePath[ 0 ] >= 'a' && savePath[ 0 ] <= 'z' ) ) ) {
  472. savePath = savePath.Left( 3 );
  473. availableSpace = Sys_GetDriveFreeSpaceInBytes( savePath );
  474. }
  475. }
  476. }
  477. }
  478. const int MIN_SAVE_STORAGE_PROFILE = 1024 * 1024;
  479. const int MIN_SAVE_STORAGE_SAVEGAME = MIN_SAVEGAME_SIZE_BYTES;
  480. uint64 requiredSizeBytes = MIN_SAVE_STORAGE_SAVEGAME + MIN_SAVE_STORAGE_PROFILE;
  481. idLib::Printf( "requiredSizeBytes: %lld\n", requiredSizeBytes );
  482. if ( (int64)( requiredSizeBytes - availableSpace ) > 0 ) {
  483. class idSWFScriptFunction_Continue : public idSWFScriptFunction_RefCounted {
  484. public:
  485. virtual ~idSWFScriptFunction_Continue() {}
  486. idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
  487. common->Dialog().ClearDialog( GDM_INSUFFICENT_STORAGE_SPACE );
  488. common->Quit();
  489. return idSWFScriptVar();
  490. }
  491. };
  492. idStaticList< idSWFScriptFunction *, 4 > callbacks;
  493. idStaticList< idStrId, 4 > optionText;
  494. callbacks.Append( new (TAG_SWF) idSWFScriptFunction_Continue() );
  495. optionText.Append( idStrId( "#STR_SWF_ACCEPT" ) );
  496. // build custom space required string
  497. // #str_dlg_space_required ~= "There is insufficient storage available. Please free %s and try again."
  498. idStr format = idStrId( "#str_dlg_startup_insufficient_storage" ).GetLocalizedString();
  499. idStr size;
  500. if ( requiredSizeBytes > ( 1024 * 1024 ) ) {
  501. size = va( "%.1f MB", (float)requiredSizeBytes / ( 1024.0f * 1024.0f ) + 0.1f ); // +0.1 to avoid truncation
  502. } else {
  503. size = va( "%.1f KB", (float)requiredSizeBytes / 1024.0f + 0.1f );
  504. }
  505. idStr msg = va( format.c_str(), size.c_str() );
  506. common->Dialog().AddDynamicDialog( GDM_INSUFFICENT_STORAGE_SPACE, callbacks, optionText, true, msg );
  507. }
  508. session->GetAchievementSystem().Start();
  509. }
  510. /*
  511. ===============
  512. idCommonLocal::JapaneseCensorship
  513. ===============
  514. */
  515. bool idCommonLocal::JapaneseCensorship() const {
  516. return com_japaneseCensorship.GetBool() || com_isJapaneseSKU;
  517. }
  518. /*
  519. ===============
  520. idCommonLocal::FilterLangList
  521. ===============
  522. */
  523. void idCommonLocal::FilterLangList( idStrList* list, idStr lang ) {
  524. idStr temp;
  525. for( int i = 0; i < list->Num(); i++ ) {
  526. temp = (*list)[i];
  527. temp = temp.Right(temp.Length()-strlen("strings/"));
  528. temp = temp.Left(lang.Length());
  529. if(idStr::Icmp(temp, lang) != 0) {
  530. list->RemoveIndex(i);
  531. i--;
  532. }
  533. }
  534. }
  535. /*
  536. ===============
  537. idCommonLocal::InitLanguageDict
  538. ===============
  539. */
  540. extern idCVar sys_lang;
  541. void idCommonLocal::InitLanguageDict() {
  542. idStr fileName;
  543. //D3XP: Instead of just loading a single lang file for each language
  544. //we are going to load all files that begin with the language name
  545. //similar to the way pak files work. So you can place english001.lang
  546. //to add new strings to the english language dictionary
  547. idFileList* langFiles;
  548. langFiles = fileSystem->ListFilesTree( "strings", ".lang", true );
  549. idStrList langList = langFiles->GetList();
  550. // Loop through the list and filter
  551. idStrList currentLangList = langList;
  552. FilterLangList( &currentLangList, sys_lang.GetString() );
  553. if ( currentLangList.Num() == 0 ) {
  554. // reset to english and try to load again
  555. sys_lang.SetString( ID_LANG_ENGLISH );
  556. currentLangList = langList;
  557. FilterLangList( &currentLangList, sys_lang.GetString() );
  558. }
  559. idLocalization::ClearDictionary();
  560. for( int i = 0; i < currentLangList.Num(); i++ ) {
  561. //common->Printf("%s\n", currentLangList[i].c_str());
  562. const byte * buffer = NULL;
  563. int len = fileSystem->ReadFile( currentLangList[i], (void**)&buffer );
  564. if ( len <= 0 ) {
  565. assert( false && "couldn't read the language dict file" );
  566. break;
  567. }
  568. idLocalization::LoadDictionary( buffer, len, currentLangList[i] );
  569. fileSystem->FreeFile( (void *)buffer );
  570. }
  571. fileSystem->FreeFileList(langFiles);
  572. }
  573. /*
  574. =================
  575. ReloadLanguage_f
  576. =================
  577. */
  578. CONSOLE_COMMAND( reloadLanguage, "reload language dict", NULL ) {
  579. commonLocal.InitLanguageDict();
  580. }
  581. #include "../renderer/Image.h"
  582. /*
  583. =================
  584. Com_StartBuild_f
  585. =================
  586. */
  587. CONSOLE_COMMAND( startBuild, "prepares to make a build", NULL ) {
  588. globalImages->StartBuild();
  589. }
  590. /*
  591. =================
  592. Com_FinishBuild_f
  593. =================
  594. */
  595. CONSOLE_COMMAND( finishBuild, "finishes the build process", NULL ) {
  596. if ( game ) {
  597. game->CacheDictionaryMedia( NULL );
  598. }
  599. globalImages->FinishBuild( ( args.Argc() > 1 ) );
  600. }
  601. /*
  602. =================
  603. idCommonLocal::RenderSplash
  604. =================
  605. */
  606. void idCommonLocal::RenderSplash() {
  607. const float sysWidth = renderSystem->GetWidth() * renderSystem->GetPixelAspect();
  608. const float sysHeight = renderSystem->GetHeight();
  609. const float sysAspect = sysWidth / sysHeight;
  610. const float splashAspect = 16.0f / 9.0f;
  611. const float adjustment = sysAspect / splashAspect;
  612. const float barHeight = ( adjustment >= 1.0f ) ? 0.0f : ( 1.0f - adjustment ) * (float)SCREEN_HEIGHT * 0.25f;
  613. const float barWidth = ( adjustment <= 1.0f ) ? 0.0f : ( adjustment - 1.0f ) * (float)SCREEN_WIDTH * 0.25f;
  614. if ( barHeight > 0.0f ) {
  615. renderSystem->SetColor( colorBlack );
  616. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, barHeight, 0, 0, 1, 1, whiteMaterial );
  617. renderSystem->DrawStretchPic( 0, SCREEN_HEIGHT - barHeight, SCREEN_WIDTH, barHeight, 0, 0, 1, 1, whiteMaterial );
  618. }
  619. if ( barWidth > 0.0f ) {
  620. renderSystem->SetColor( colorBlack );
  621. renderSystem->DrawStretchPic( 0, 0, barWidth, SCREEN_HEIGHT, 0, 0, 1, 1, whiteMaterial );
  622. renderSystem->DrawStretchPic( SCREEN_WIDTH - barWidth, 0, barWidth, SCREEN_HEIGHT, 0, 0, 1, 1, whiteMaterial );
  623. }
  624. renderSystem->SetColor4( 1, 1, 1, 1 );
  625. renderSystem->DrawStretchPic( barWidth, barHeight, SCREEN_WIDTH - barWidth * 2.0f, SCREEN_HEIGHT - barHeight * 2.0f, 0, 0, 1, 1, splashScreen );
  626. const emptyCommand_t * cmd = renderSystem->SwapCommandBuffers( &time_frontend, &time_backend, &time_shadows, &time_gpu );
  627. renderSystem->RenderCommandBuffers( cmd );
  628. }
  629. /*
  630. =================
  631. idCommonLocal::RenderBink
  632. =================
  633. */
  634. void idCommonLocal::RenderBink( const char * path ) {
  635. const float sysWidth = renderSystem->GetWidth() * renderSystem->GetPixelAspect();
  636. const float sysHeight = renderSystem->GetHeight();
  637. const float sysAspect = sysWidth / sysHeight;
  638. const float movieAspect = ( 16.0f / 9.0f );
  639. const float imageWidth = SCREEN_WIDTH * movieAspect / sysAspect;
  640. const float chop = 0.5f * ( SCREEN_WIDTH - imageWidth );
  641. idStr materialText;
  642. materialText.Format( "{ translucent { videoMap %s } }", path );
  643. idMaterial * material = const_cast<idMaterial*>( declManager->FindMaterial( "splashbink" ) );
  644. material->Parse( materialText.c_str(), materialText.Length(), false );
  645. material->ResetCinematicTime( Sys_Milliseconds() );
  646. while ( Sys_Milliseconds() <= material->GetCinematicStartTime() + material->CinematicLength() ) {
  647. renderSystem->DrawStretchPic( chop, 0, imageWidth, SCREEN_HEIGHT, 0, 0, 1, 1, material );
  648. const emptyCommand_t * cmd = renderSystem->SwapCommandBuffers( &time_frontend, &time_backend, &time_shadows, &time_gpu );
  649. renderSystem->RenderCommandBuffers( cmd );
  650. Sys_GenerateEvents();
  651. Sys_Sleep( 10 );
  652. }
  653. material->MakeDefault();
  654. }
  655. /*
  656. =================
  657. idCommonLocal::InitSIMD
  658. =================
  659. */
  660. void idCommonLocal::InitSIMD() {
  661. idSIMD::InitProcessor( "doom", com_forceGenericSIMD.GetBool() );
  662. com_forceGenericSIMD.ClearModified();
  663. }
  664. /*
  665. =================
  666. idCommonLocal::LoadGameDLL
  667. =================
  668. */
  669. void idCommonLocal::LoadGameDLL() {
  670. #ifdef __DOOM_DLL__
  671. char dllPath[ MAX_OSPATH ];
  672. gameImport_t gameImport;
  673. gameExport_t gameExport;
  674. GetGameAPI_t GetGameAPI;
  675. fileSystem->FindDLL( "game", dllPath, true );
  676. if ( !dllPath[ 0 ] ) {
  677. common->FatalError( "couldn't find game dynamic library" );
  678. return;
  679. }
  680. common->DPrintf( "Loading game DLL: '%s'\n", dllPath );
  681. gameDLL = sys->DLL_Load( dllPath );
  682. if ( !gameDLL ) {
  683. common->FatalError( "couldn't load game dynamic library" );
  684. return;
  685. }
  686. const char * functionName = "GetGameAPI";
  687. GetGameAPI = (GetGameAPI_t) Sys_DLL_GetProcAddress( gameDLL, functionName );
  688. if ( !GetGameAPI ) {
  689. Sys_DLL_Unload( gameDLL );
  690. gameDLL = NULL;
  691. common->FatalError( "couldn't find game DLL API" );
  692. return;
  693. }
  694. gameImport.version = GAME_API_VERSION;
  695. gameImport.sys = ::sys;
  696. gameImport.common = ::common;
  697. gameImport.cmdSystem = ::cmdSystem;
  698. gameImport.cvarSystem = ::cvarSystem;
  699. gameImport.fileSystem = ::fileSystem;
  700. gameImport.renderSystem = ::renderSystem;
  701. gameImport.soundSystem = ::soundSystem;
  702. gameImport.renderModelManager = ::renderModelManager;
  703. gameImport.uiManager = ::uiManager;
  704. gameImport.declManager = ::declManager;
  705. gameImport.AASFileManager = ::AASFileManager;
  706. gameImport.collisionModelManager = ::collisionModelManager;
  707. gameExport = *GetGameAPI( &gameImport );
  708. if ( gameExport.version != GAME_API_VERSION ) {
  709. Sys_DLL_Unload( gameDLL );
  710. gameDLL = NULL;
  711. common->FatalError( "wrong game DLL API version" );
  712. return;
  713. }
  714. game = gameExport.game;
  715. gameEdit = gameExport.gameEdit;
  716. #endif
  717. // initialize the game object
  718. if ( game != NULL ) {
  719. game->Init();
  720. }
  721. }
  722. /*
  723. =================
  724. idCommonLocal::UnloadGameDLL
  725. =================
  726. */
  727. void idCommonLocal::CleanupShell() {
  728. if ( game != NULL ) {
  729. game->Shell_Cleanup();
  730. }
  731. }
  732. /*
  733. =================
  734. idCommonLocal::UnloadGameDLL
  735. =================
  736. */
  737. void idCommonLocal::UnloadGameDLL() {
  738. // shut down the game object
  739. if ( game != NULL ) {
  740. game->Shutdown();
  741. }
  742. #ifdef __DOOM_DLL__
  743. if ( gameDLL ) {
  744. Sys_DLL_Unload( gameDLL );
  745. gameDLL = NULL;
  746. }
  747. game = NULL;
  748. gameEdit = NULL;
  749. #endif
  750. }
  751. /*
  752. =================
  753. idCommonLocal::IsInitialized
  754. =================
  755. */
  756. bool idCommonLocal::IsInitialized() const {
  757. return com_fullyInitialized;
  758. }
  759. //======================================================================================
  760. /*
  761. =================
  762. idCommonLocal::Init
  763. =================
  764. */
  765. void idCommonLocal::Init( int argc, const char * const * argv, const char *cmdline ) {
  766. try {
  767. // set interface pointers used by idLib
  768. idLib::sys = sys;
  769. idLib::common = common;
  770. idLib::cvarSystem = cvarSystem;
  771. idLib::fileSystem = fileSystem;
  772. // initialize idLib
  773. idLib::Init();
  774. // clear warning buffer
  775. ClearWarnings( GAME_NAME " initialization" );
  776. idLib::Printf( va( "Command line: %s\n", cmdline ) );
  777. //::MessageBox( NULL, cmdline, "blah", MB_OK );
  778. // parse command line options
  779. idCmdArgs args;
  780. if ( cmdline ) {
  781. // tokenize if the OS doesn't do it for us
  782. args.TokenizeString( cmdline, true );
  783. argv = args.GetArgs( &argc );
  784. }
  785. ParseCommandLine( argc, argv );
  786. // init console command system
  787. cmdSystem->Init();
  788. // init CVar system
  789. cvarSystem->Init();
  790. // register all static CVars
  791. idCVar::RegisterStaticVars();
  792. idLib::Printf( "QA Timing INIT: %06dms\n", Sys_Milliseconds() );
  793. // print engine version
  794. Printf( "%s\n", version.string );
  795. // initialize key input/binding, done early so bind command exists
  796. idKeyInput::Init();
  797. // init the console so we can take prints
  798. console->Init();
  799. // get architecture info
  800. Sys_Init();
  801. // initialize networking
  802. Sys_InitNetworking();
  803. // override cvars from command line
  804. StartupVariable( NULL );
  805. consoleUsed = com_allowConsole.GetBool();
  806. if ( Sys_AlreadyRunning() ) {
  807. Sys_Quit();
  808. }
  809. // initialize processor specific SIMD implementation
  810. InitSIMD();
  811. // initialize the file system
  812. fileSystem->Init();
  813. const char * defaultLang = Sys_DefaultLanguage();
  814. com_isJapaneseSKU = ( idStr::Icmp( defaultLang, ID_LANG_JAPANESE ) == 0 );
  815. // Allow the system to set a default lanugage
  816. Sys_SetLanguageFromSystem();
  817. // Pre-allocate our 20 MB save buffer here on time, instead of on-demand for each save....
  818. saveFile.SetNameAndType( SAVEGAME_CHECKPOINT_FILENAME, SAVEGAMEFILE_BINARY );
  819. saveFile.PreAllocate( MIN_SAVEGAME_SIZE_BYTES );
  820. stringsFile.SetNameAndType( SAVEGAME_STRINGS_FILENAME, SAVEGAMEFILE_BINARY );
  821. stringsFile.PreAllocate( MAX_SAVEGAME_STRING_TABLE_SIZE );
  822. fileSystem->BeginLevelLoad( "_startup", saveFile.GetDataPtr(), saveFile.GetAllocated() );
  823. // initialize the declaration manager
  824. declManager->Init();
  825. // init journalling, etc
  826. eventLoop->Init();
  827. // init the parallel job manager
  828. parallelJobManager->Init();
  829. // exec the startup scripts
  830. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "exec default.cfg\n" );
  831. #ifdef CONFIG_FILE
  832. // skip the config file if "safe" is on the command line
  833. if ( !SafeMode() && !g_demoMode.GetBool() ) {
  834. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "exec " CONFIG_FILE "\n" );
  835. }
  836. #endif
  837. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "exec autoexec.cfg\n" );
  838. // run cfg execution
  839. cmdSystem->ExecuteCommandBuffer();
  840. // re-override anything from the config files with command line args
  841. StartupVariable( NULL );
  842. // if any archived cvars are modified after this, we will trigger a writing of the config file
  843. cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE );
  844. // init OpenGL, which will open a window and connect sound and input hardware
  845. renderSystem->InitOpenGL();
  846. // Support up to 2 digits after the decimal point
  847. com_engineHz_denominator = 100LL * com_engineHz.GetFloat();
  848. com_engineHz_latched = com_engineHz.GetFloat();
  849. // start the sound system, but don't do any hardware operations yet
  850. soundSystem->Init();
  851. // initialize the renderSystem data structures
  852. renderSystem->Init();
  853. whiteMaterial = declManager->FindMaterial( "_white" );
  854. if ( idStr::Icmp( sys_lang.GetString(), ID_LANG_FRENCH ) == 0 ) {
  855. // If the user specified french, we show french no matter what SKU
  856. splashScreen = declManager->FindMaterial( "guis/assets/splash/legal_french" );
  857. } else if ( idStr::Icmp( defaultLang, ID_LANG_FRENCH ) == 0 ) {
  858. // If the lead sku is french (ie: europe), display figs
  859. splashScreen = declManager->FindMaterial( "guis/assets/splash/legal_figs" );
  860. } else {
  861. // Otherwise show it in english
  862. splashScreen = declManager->FindMaterial( "guis/assets/splash/legal_english" );
  863. }
  864. const int legalMinTime = 4000;
  865. const bool showVideo = ( !com_skipIntroVideos.GetBool () && fileSystem->UsingResourceFiles() );
  866. if ( showVideo ) {
  867. RenderBink( "video\\loadvideo.bik" );
  868. RenderSplash();
  869. RenderSplash();
  870. } else {
  871. idLib::Printf( "Skipping Intro Videos!\n" );
  872. // display the legal splash screen
  873. // No clue why we have to render this twice to show up...
  874. RenderSplash();
  875. RenderSplash();
  876. }
  877. int legalStartTime = Sys_Milliseconds();
  878. declManager->Init2();
  879. // initialize string database so we can use it for loading messages
  880. InitLanguageDict();
  881. // spawn the game thread, even if we are going to run without SMP
  882. // one meg stack, because it can parse decls from gui surfaces (unfortunately)
  883. // use a lower priority so job threads can run on the same core
  884. gameThread.StartWorkerThread( "Game/Draw", CORE_1B, THREAD_BELOW_NORMAL, 0x100000 );
  885. // boost this thread's priority, so it will prevent job threads from running while
  886. // the render back end still has work to do
  887. // init the user command input code
  888. usercmdGen->Init();
  889. Sys_SetRumble( 0, 0, 0 );
  890. // initialize the user interfaces
  891. uiManager->Init();
  892. // startup the script debugger
  893. // DebuggerServerInit();
  894. // load the game dll
  895. LoadGameDLL();
  896. // On the PC touch them all so they get included in the resource build
  897. if ( !fileSystem->UsingResourceFiles() ) {
  898. declManager->FindMaterial( "guis/assets/splash/legal_english" );
  899. declManager->FindMaterial( "guis/assets/splash/legal_french" );
  900. declManager->FindMaterial( "guis/assets/splash/legal_figs" );
  901. // register the japanese font so it gets included
  902. renderSystem->RegisterFont( "DFPHeiseiGothicW7" );
  903. // Make sure all videos get touched because you can bring videos from one map to another, they need to be included in all maps
  904. for ( int i = 0; i < declManager->GetNumDecls( DECL_VIDEO ); i++ ) {
  905. declManager->DeclByIndex( DECL_VIDEO, i );
  906. }
  907. }
  908. fileSystem->UnloadResourceContainer( "_ordered" );
  909. // the same idRenderWorld will be used for all games
  910. // and demos, insuring that level specific models
  911. // will be freed
  912. renderWorld = renderSystem->AllocRenderWorld();
  913. soundWorld = soundSystem->AllocSoundWorld( renderWorld );
  914. menuSoundWorld = soundSystem->AllocSoundWorld( NULL );
  915. menuSoundWorld->PlaceListener( vec3_origin, mat3_identity, 0 );
  916. // init the session
  917. session->Initialize();
  918. session->InitializeSoundRelatedSystems();
  919. InitializeMPMapsModes();
  920. // leaderboards need to be initialized after InitializeMPMapsModes, which populates the MP Map list.
  921. if( game != NULL ) {
  922. game->Leaderboards_Init();
  923. }
  924. CreateMainMenu();
  925. commonDialog.Init();
  926. // load the console history file
  927. consoleHistory.LoadHistoryFile();
  928. AddStartupCommands();
  929. StartMenu( true );
  930. while ( Sys_Milliseconds() - legalStartTime < legalMinTime ) {
  931. RenderSplash();
  932. Sys_GenerateEvents();
  933. Sys_Sleep( 10 );
  934. };
  935. // print all warnings queued during initialization
  936. PrintWarnings();
  937. // remove any prints from the notify lines
  938. console->ClearNotifyLines();
  939. CheckStartupStorageRequirements();
  940. if ( preload_CommonAssets.GetBool() && fileSystem->UsingResourceFiles() ) {
  941. idPreloadManifest manifest;
  942. manifest.LoadManifest( "_common.preload" );
  943. globalImages->Preload( manifest, false );
  944. soundSystem->Preload( manifest );
  945. }
  946. fileSystem->EndLevelLoad();
  947. // Initialize support for Doom classic.
  948. doomClassicMaterial = declManager->FindMaterial( "_doomClassic" );
  949. idImage *image = globalImages->GetImage( "_doomClassic" );
  950. if ( image != NULL ) {
  951. idImageOpts opts;
  952. opts.format = FMT_RGBA8;
  953. opts.colorFormat = CFM_DEFAULT;
  954. opts.width = DOOMCLASSIC_RENDERWIDTH;
  955. opts.height = DOOMCLASSIC_RENDERHEIGHT;
  956. opts.numLevels = 1;
  957. image->AllocImage( opts, TF_LINEAR, TR_REPEAT );
  958. }
  959. com_fullyInitialized = true;
  960. // No longer need the splash screen
  961. if ( splashScreen != NULL ) {
  962. for ( int i = 0; i < splashScreen->GetNumStages(); i++ ) {
  963. idImage * image = splashScreen->GetStage( i )->texture.image;
  964. if ( image != NULL ) {
  965. image->PurgeImage();
  966. }
  967. }
  968. }
  969. Printf( "--- Common Initialization Complete ---\n" );
  970. idLib::Printf( "QA Timing IIS: %06dms\n", Sys_Milliseconds() );
  971. } catch( idException & ) {
  972. Sys_Error( "Error during initialization" );
  973. }
  974. }
  975. /*
  976. =================
  977. idCommonLocal::Shutdown
  978. =================
  979. */
  980. void idCommonLocal::Shutdown() {
  981. if ( com_shuttingDown ) {
  982. return;
  983. }
  984. com_shuttingDown = true;
  985. // Kill any pending saves...
  986. printf( "session->GetSaveGameManager().CancelToTerminate();\n" );
  987. session->GetSaveGameManager().CancelToTerminate();
  988. // kill sound first
  989. printf( "soundSystem->StopAllSounds();\n" );
  990. soundSystem->StopAllSounds();
  991. // shutdown the script debugger
  992. // DebuggerServerShutdown();
  993. if ( aviCaptureMode ) {
  994. printf( "EndAVICapture();\n" );
  995. EndAVICapture();
  996. }
  997. printf( "Stop();\n" );
  998. Stop();
  999. printf( "CleanupShell();\n" );
  1000. CleanupShell();
  1001. printf( "delete loadGUI;\n" );
  1002. delete loadGUI;
  1003. loadGUI = NULL;
  1004. printf( "delete renderWorld;\n" );
  1005. delete renderWorld;
  1006. renderWorld = NULL;
  1007. printf( "delete soundWorld;\n" );
  1008. delete soundWorld;
  1009. soundWorld = NULL;
  1010. printf( "delete menuSoundWorld;\n" );
  1011. delete menuSoundWorld;
  1012. menuSoundWorld = NULL;
  1013. // shut down the session
  1014. printf( "session->ShutdownSoundRelatedSystems();\n" );
  1015. session->ShutdownSoundRelatedSystems();
  1016. printf( "session->Shutdown();\n" );
  1017. session->Shutdown();
  1018. // shutdown, deallocate leaderboard definitions.
  1019. if( game != NULL ) {
  1020. printf( "game->Leaderboards_Shutdown();\n" );
  1021. game->Leaderboards_Shutdown();
  1022. }
  1023. // shut down the user interfaces
  1024. printf( "uiManager->Shutdown();\n" );
  1025. uiManager->Shutdown();
  1026. // shut down the sound system
  1027. printf( "soundSystem->Shutdown();\n" );
  1028. soundSystem->Shutdown();
  1029. // shut down the user command input code
  1030. printf( "usercmdGen->Shutdown();\n" );
  1031. usercmdGen->Shutdown();
  1032. // shut down the event loop
  1033. printf( "eventLoop->Shutdown();\n" );
  1034. eventLoop->Shutdown();
  1035. // shutdown the decl manager
  1036. printf( "declManager->Shutdown();\n" );
  1037. declManager->Shutdown();
  1038. // shut down the renderSystem
  1039. printf( "renderSystem->Shutdown();\n" );
  1040. renderSystem->Shutdown();
  1041. printf( "commonDialog.Shutdown();\n" );
  1042. commonDialog.Shutdown();
  1043. // unload the game dll
  1044. printf( "UnloadGameDLL();\n" );
  1045. UnloadGameDLL();
  1046. printf( "saveFile.Clear( true );\n" );
  1047. saveFile.Clear( true );
  1048. printf( "stringsFile.Clear( true );\n" );
  1049. stringsFile.Clear( true );
  1050. // only shut down the log file after all output is done
  1051. printf( "CloseLogFile();\n" );
  1052. CloseLogFile();
  1053. // shut down the file system
  1054. printf( "fileSystem->Shutdown( false );\n" );
  1055. fileSystem->Shutdown( false );
  1056. // shut down non-portable system services
  1057. printf( "Sys_Shutdown();\n" );
  1058. Sys_Shutdown();
  1059. // shut down the console
  1060. printf( "console->Shutdown();\n" );
  1061. console->Shutdown();
  1062. // shut down the key system
  1063. printf( "idKeyInput::Shutdown();\n" );
  1064. idKeyInput::Shutdown();
  1065. // shut down the cvar system
  1066. printf( "cvarSystem->Shutdown();\n" );
  1067. cvarSystem->Shutdown();
  1068. // shut down the console command system
  1069. printf( "cmdSystem->Shutdown();\n" );
  1070. cmdSystem->Shutdown();
  1071. // free any buffered warning messages
  1072. printf( "ClearWarnings( GAME_NAME \" shutdown\" );\n" );
  1073. ClearWarnings( GAME_NAME " shutdown" );
  1074. printf( "warningCaption.Clear();\n" );
  1075. warningCaption.Clear();
  1076. printf( "errorList.Clear();\n" );
  1077. errorList.Clear();
  1078. // shutdown idLib
  1079. printf( "idLib::ShutDown();\n" );
  1080. idLib::ShutDown();
  1081. }
  1082. /*
  1083. ========================
  1084. idCommonLocal::CreateMainMenu
  1085. ========================
  1086. */
  1087. void idCommonLocal::CreateMainMenu() {
  1088. if ( game != NULL ) {
  1089. // note which media we are going to need to load
  1090. declManager->BeginLevelLoad();
  1091. renderSystem->BeginLevelLoad();
  1092. soundSystem->BeginLevelLoad();
  1093. uiManager->BeginLevelLoad();
  1094. // create main inside an "empty" game level load - so assets get
  1095. // purged automagically when we transition to a "real" map
  1096. game->Shell_CreateMenu( false );
  1097. game->Shell_Show( true );
  1098. game->Shell_SyncWithSession();
  1099. // load
  1100. renderSystem->EndLevelLoad();
  1101. soundSystem->EndLevelLoad();
  1102. declManager->EndLevelLoad();
  1103. uiManager->EndLevelLoad( "" );
  1104. }
  1105. }
  1106. /*
  1107. ===============
  1108. idCommonLocal::Stop
  1109. called on errors and game exits
  1110. ===============
  1111. */
  1112. void idCommonLocal::Stop( bool resetSession ) {
  1113. ClearWipe();
  1114. // clear mapSpawned and demo playing flags
  1115. UnloadMap();
  1116. soundSystem->StopAllSounds();
  1117. insideUpdateScreen = false;
  1118. insideExecuteMapChange = false;
  1119. // drop all guis
  1120. ExitMenu();
  1121. if ( resetSession ) {
  1122. session->QuitMatchToTitle();
  1123. }
  1124. }
  1125. /*
  1126. ===============
  1127. idCommonLocal::BusyWait
  1128. ===============
  1129. */
  1130. void idCommonLocal::BusyWait() {
  1131. Sys_GenerateEvents();
  1132. const bool captureToImage = false;
  1133. UpdateScreen( captureToImage );
  1134. session->UpdateSignInManager();
  1135. session->Pump();
  1136. }
  1137. /*
  1138. ===============
  1139. idCommonLocal::WaitForSessionState
  1140. ===============
  1141. */
  1142. bool idCommonLocal::WaitForSessionState( idSession::sessionState_t desiredState ) {
  1143. if ( session->GetState() == desiredState ) {
  1144. return true;
  1145. }
  1146. while ( true ) {
  1147. BusyWait();
  1148. idSession::sessionState_t sessionState = session->GetState();
  1149. if ( sessionState == desiredState ) {
  1150. return true;
  1151. }
  1152. if ( sessionState != idSession::LOADING &&
  1153. sessionState != idSession::SEARCHING &&
  1154. sessionState != idSession::CONNECTING &&
  1155. sessionState != idSession::BUSY &&
  1156. sessionState != desiredState ) {
  1157. return false;
  1158. }
  1159. Sys_Sleep( 10 );
  1160. }
  1161. }
  1162. /*
  1163. ========================
  1164. idCommonLocal::LeaveGame
  1165. ========================
  1166. */
  1167. void idCommonLocal::LeaveGame() {
  1168. const bool captureToImage = false;
  1169. UpdateScreen( captureToImage );
  1170. ResetNetworkingState();
  1171. Stop( false );
  1172. CreateMainMenu();
  1173. StartMenu();
  1174. }
  1175. /*
  1176. ===============
  1177. idCommonLocal::ProcessEvent
  1178. ===============
  1179. */
  1180. bool idCommonLocal::ProcessEvent( const sysEvent_t *event ) {
  1181. // hitting escape anywhere brings up the menu
  1182. if ( game && game->IsInGame() ) {
  1183. if ( event->evType == SE_KEY && event->evValue2 == 1 && ( event->evValue == K_ESCAPE || event->evValue == K_JOY9 ) ) {
  1184. if ( !game->Shell_IsActive() ) {
  1185. // menus / etc
  1186. if ( MenuEvent( event ) ) {
  1187. return true;
  1188. }
  1189. console->Close();
  1190. StartMenu();
  1191. return true;
  1192. } else {
  1193. console->Close();
  1194. // menus / etc
  1195. if ( MenuEvent( event ) ) {
  1196. return true;
  1197. }
  1198. game->Shell_ClosePause();
  1199. }
  1200. }
  1201. }
  1202. // let the pull-down console take it if desired
  1203. if ( console->ProcessEvent( event, false ) ) {
  1204. return true;
  1205. }
  1206. if ( session->ProcessInputEvent( event ) ) {
  1207. return true;
  1208. }
  1209. if ( Dialog().IsDialogActive() ) {
  1210. Dialog().HandleDialogEvent( event );
  1211. return true;
  1212. }
  1213. // Let Doom classic run events.
  1214. if ( IsPlayingDoomClassic() ) {
  1215. // Translate the event to Doom classic format.
  1216. event_t classicEvent;
  1217. if ( event->evType == SE_KEY ) {
  1218. if( event->evValue2 == 1 ) {
  1219. classicEvent.type = ev_keydown;
  1220. } else if( event->evValue2 == 0 ) {
  1221. classicEvent.type = ev_keyup;
  1222. }
  1223. DoomLib::SetPlayer( 0 );
  1224. extern Globals * g;
  1225. if ( g != NULL ) {
  1226. classicEvent.data1 = DoomLib::RemapControl( event->GetKey() );
  1227. D_PostEvent( &classicEvent );
  1228. }
  1229. DoomLib::SetPlayer( -1 );
  1230. }
  1231. // Let the classics eat all events.
  1232. return true;
  1233. }
  1234. // menus / etc
  1235. if ( MenuEvent( event ) ) {
  1236. return true;
  1237. }
  1238. // if we aren't in a game, force the console to take it
  1239. if ( !mapSpawned ) {
  1240. console->ProcessEvent( event, true );
  1241. return true;
  1242. }
  1243. // in game, exec bindings for all key downs
  1244. if ( event->evType == SE_KEY && event->evValue2 == 1 ) {
  1245. idKeyInput::ExecKeyBinding( event->evValue );
  1246. return true;
  1247. }
  1248. return false;
  1249. }
  1250. /*
  1251. ========================
  1252. idCommonLocal::ResetPlayerInput
  1253. ========================
  1254. */
  1255. void idCommonLocal::ResetPlayerInput( int playerIndex ) {
  1256. userCmdMgr.ResetPlayer( playerIndex );
  1257. }
  1258. /*
  1259. ========================
  1260. idCommonLocal::SwitchToGame
  1261. ========================
  1262. */
  1263. void idCommonLocal::SwitchToGame( currentGame_t newGame ) {
  1264. idealCurrentGame = newGame;
  1265. }
  1266. /*
  1267. ========================
  1268. idCommonLocal::PerformGameSwitch
  1269. ========================
  1270. */
  1271. void idCommonLocal::PerformGameSwitch() {
  1272. // If the session state is past the menu, we should be in Doom 3.
  1273. // This will happen if, for example, we accept an invite while playing
  1274. // Doom or Doom 2.
  1275. if ( session->GetState() > idSession::IDLE ) {
  1276. idealCurrentGame = DOOM3_BFG;
  1277. }
  1278. if ( currentGame == idealCurrentGame ) {
  1279. return;
  1280. }
  1281. const int DOOM_CLASSIC_HZ = 35;
  1282. if ( idealCurrentGame == DOOM_CLASSIC || idealCurrentGame == DOOM2_CLASSIC ) {
  1283. // Pause Doom 3 sound.
  1284. if ( menuSoundWorld != NULL ) {
  1285. menuSoundWorld->Pause();
  1286. }
  1287. DoomLib::skipToNew = false;
  1288. DoomLib::skipToLoad = false;
  1289. // Reset match parameters for the classics.
  1290. DoomLib::matchParms = idMatchParameters();
  1291. // The classics use the usercmd manager too, clear it.
  1292. userCmdMgr.SetDefaults();
  1293. // Classics need a local user too.
  1294. session->UpdateSignInManager();
  1295. session->GetSignInManager().RegisterLocalUser( 0 );
  1296. com_engineHz_denominator = 100LL * DOOM_CLASSIC_HZ;
  1297. com_engineHz_latched = DOOM_CLASSIC_HZ;
  1298. DoomLib::SetCurrentExpansion( idealCurrentGame );
  1299. } else if ( idealCurrentGame == DOOM3_BFG ) {
  1300. DoomLib::Interface.Shutdown();
  1301. com_engineHz_denominator = 100LL * com_engineHz.GetFloat();
  1302. com_engineHz_latched = com_engineHz.GetFloat();
  1303. // Don't MoveToPressStart if we have an invite, we need to go
  1304. // directly to the lobby.
  1305. if ( session->GetState() <= idSession::IDLE ) {
  1306. session->MoveToPressStart();
  1307. }
  1308. // Unpause Doom 3 sound.
  1309. if ( menuSoundWorld != NULL ) {
  1310. menuSoundWorld->UnPause();
  1311. }
  1312. }
  1313. currentGame = idealCurrentGame;
  1314. }
  1315. /*
  1316. ==================
  1317. Common_WritePrecache_f
  1318. ==================
  1319. */
  1320. CONSOLE_COMMAND( writePrecache, "writes precache commands", NULL ) {
  1321. if ( args.Argc() != 2 ) {
  1322. common->Printf( "USAGE: writePrecache <execFile>\n" );
  1323. return;
  1324. }
  1325. idStr str = args.Argv(1);
  1326. str.DefaultFileExtension( ".cfg" );
  1327. idFile *f = fileSystem->OpenFileWrite( str );
  1328. declManager->WritePrecacheCommands( f );
  1329. renderModelManager->WritePrecacheCommands( f );
  1330. uiManager->WritePrecacheCommands( f );
  1331. fileSystem->CloseFile( f );
  1332. }
  1333. /*
  1334. ================
  1335. Common_Disconnect_f
  1336. ================
  1337. */
  1338. CONSOLE_COMMAND_SHIP( disconnect, "disconnects from a game", NULL ) {
  1339. session->QuitMatch();
  1340. }
  1341. /*
  1342. ===============
  1343. Common_Hitch_f
  1344. ===============
  1345. */
  1346. CONSOLE_COMMAND( hitch, "hitches the game", NULL ) {
  1347. if ( args.Argc() == 2 ) {
  1348. Sys_Sleep( atoi(args.Argv(1)) );
  1349. } else {
  1350. Sys_Sleep( 100 );
  1351. }
  1352. }
  1353. CONSOLE_COMMAND( showStringMemory, "shows memory used by strings", NULL ) {
  1354. idStr::ShowMemoryUsage_f( args );
  1355. }
  1356. CONSOLE_COMMAND( showDictMemory, "shows memory used by dictionaries", NULL ) {
  1357. idDict::ShowMemoryUsage_f( args );
  1358. }
  1359. CONSOLE_COMMAND( listDictKeys, "lists all keys used by dictionaries", NULL ) {
  1360. idDict::ListKeys_f( args );
  1361. }
  1362. CONSOLE_COMMAND( listDictValues, "lists all values used by dictionaries", NULL ) {
  1363. idDict::ListValues_f( args );
  1364. }
  1365. CONSOLE_COMMAND( testSIMD, "test SIMD code", NULL ) {
  1366. idSIMD::Test_f( args );
  1367. }