PageRenderTime 74ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/idTech4/idEngine.cs

http://github.com/iainmckay/idtech4.net
C# | 2218 lines | 1027 code | 344 blank | 847 comment | 218 complexity | ae4b6599c50999885cc272617f3df437 MD5 | raw file
Possible License(s): GPL-3.0

Large files files are truncated, but you can click here to view the full file

  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. using System;
  21. using System.Collections.Generic;
  22. using System.Diagnostics;
  23. using System.IO;
  24. using System.Linq;
  25. using System.Reflection;
  26. using System.Text;
  27. using System.Threading;
  28. using Microsoft.Xna.Framework;
  29. using Microsoft.Xna.Framework.Graphics;
  30. using Microsoft.Xna.Framework.Input;
  31. using idTech4.Input;
  32. using idTech4.IO;
  33. using idTech4.Math;
  34. using idTech4.Renderer;
  35. using idTech4.Services;
  36. using idTech4.Text;
  37. using idTech4.Threading;
  38. using idTech4.UI;
  39. using Keys = idTech4.Services.Keys;
  40. namespace idTech4
  41. {
  42. /// <summary>
  43. /// This is the main type for your game
  44. /// </summary>
  45. /// <remarks>
  46. /// New for tech4x:
  47. /// <para/>
  48. /// Unlike previous SMP work, the actual GPU command drawing is done in the main thread, which avoids the
  49. /// OpenGL problems with needing windows to be created by the same thread that creates the context, as well
  50. /// as the issues with passing context ownership back and forth on the 360.
  51. /// <para/>
  52. /// The game tic and the generation of the draw command list is now run in a separate thread, and overlapped
  53. /// with the interpretation of the previous draw command list.
  54. /// <para/>
  55. /// While the game tic should be nicely contained, the draw command generation winds through the user interface
  56. /// code, and is potentially hazardous. For now, the overlap will be restricted to the renderer back end,
  57. /// which should also be nicely contained.
  58. /// </remarks>
  59. public class idEngine : Game
  60. {
  61. #region Singleton
  62. public static idEngine Instance
  63. {
  64. get
  65. {
  66. return _instance;
  67. }
  68. }
  69. private static idEngine _instance;
  70. static idEngine()
  71. {
  72. _instance = new idEngine();
  73. }
  74. #endregion
  75. #region Properties
  76. #region Network
  77. /// <summary>
  78. /// Is this a multiplayer game?
  79. /// </summary>
  80. public bool IsMultiplayer
  81. {
  82. get
  83. {
  84. return false;
  85. }
  86. }
  87. #endregion
  88. #region Timing
  89. public int FrameNumber
  90. {
  91. get
  92. {
  93. return _frameNumber;
  94. }
  95. }
  96. /// <summary>
  97. /// Gets the total amount of time elapsed since the game started in milliseconds.
  98. /// </summary>
  99. public long ElapsedTime
  100. {
  101. get
  102. {
  103. return _gameTimer.ElapsedMilliseconds;
  104. }
  105. }
  106. #endregion
  107. #endregion
  108. #region Members
  109. private GraphicsDeviceManager _graphicsDeviceManager;
  110. private bool _firstTick = true;
  111. private bool _initialized;
  112. private int _frameNumber;
  113. private long _lastFrameTime;
  114. private string[] _rawCommandLineArguments;
  115. private CommandArguments[] _commandLineArguments = new CommandArguments[] { };
  116. private idMaterial _splashScreen;
  117. private idMaterial _whiteMaterial;
  118. // this is set if the player enables the console, which disables achievements
  119. private bool _consoleUsed;
  120. private idGameThread _gameThread; // the game and draw code can be run in parallel
  121. private int _gameFrame; // frame number of the local game
  122. private double _gameTimeResidual; // left over msec from the last game frame
  123. private bool _syncNextGameFrame;
  124. // for tracking errors
  125. private ErrorType _errorEntered;
  126. private long _lastErrorTime;
  127. private int _errorCount;
  128. private List<string> _errorList = new List<string>();
  129. private Stopwatch _gameTimer;
  130. private bool _shuttingDown;
  131. private bool _generateEventsEntered;
  132. // engine timing
  133. private float _engineHzLatched = 60.0f; // latched version of cvar, updated between map loads
  134. private long _engineHzNumerator = 100 * 1000;
  135. private long _engineHzDenominator = 100 * 60;
  136. private bool _isJapaneseSKU;
  137. private CurrentGame _currentGame;
  138. private CurrentGame _idealCurrentGame; // defer game switching so that bad things don't happen in the middle of the frame.
  139. private idMaterial _doomClassicMaterial;
  140. // com_speeds times
  141. private int _speeds_GameFrameCount; // total number of game frames that were run
  142. private int _speeds_GameFrame; // game logic time
  143. private int _speeds_MaxGameFrame; // maximum single frame game logic time
  144. private int _speeds_GameDraw; // game present time
  145. private long _speeds_Frontend; // renderer frontend time
  146. private long _speeds_Backend; // renderer backend time
  147. private long _speeds_Shadows; // renderer backend waiting for shadow volumes to be created
  148. private long _speeds_Gpu; // total gpu time, at least for PC
  149. private long _speeds_LastTime;
  150. private bool _showShellRequested;
  151. private string _currentMapName; // for checking reload on same level
  152. private bool _mapSpawned; // cleared on Stop()
  153. #endregion
  154. #region Constructor
  155. private idEngine()
  156. {
  157. this.IsFixedTimeStep = false;
  158. this.Content.RootDirectory = idLicensee.BaseGameDirectory;
  159. _gameTimer = Stopwatch.StartNew();
  160. _graphicsDeviceManager = new GraphicsDeviceManager(this);
  161. }
  162. #endregion
  163. #region Error Handling
  164. public void Error(string format, params object[] args)
  165. {
  166. ErrorType code = ErrorType.Drop;
  167. // always turn this off after an error
  168. idLog.RefreshOnPrint = false;
  169. // retrieve the services we need for this
  170. ICVarSystem cvarSystem = this.GetService<ICVarSystem>();
  171. ICommandSystem cmdSystem = this.GetService<ICommandSystem>();
  172. IRenderSystem renderSystem = this.GetService<IRenderSystem>();
  173. if(cvarSystem.GetInt("com_productionMode") == 3)
  174. {
  175. Sys_Quit();
  176. }
  177. // if we don't have the renderer running, make it a fatal error
  178. if(renderSystem.IsInitialized == false)
  179. {
  180. code = ErrorType.Fatal;
  181. }
  182. // if we got a recursive error, make it fatal
  183. if(_errorEntered > 0)
  184. {
  185. // if we are recursively erroring while exiting
  186. // from a fatal error, just kill the entire
  187. // process immediately, which will prevent a
  188. // full screen rendering window covering the
  189. // error dialog
  190. if(_errorEntered == ErrorType.Fatal)
  191. {
  192. Sys_Quit();
  193. }
  194. code = ErrorType.Fatal;
  195. }
  196. // if we are getting a solid stream of ERP_DROP, do an ERP_FATAL
  197. long currentTime = this.ElapsedTime;
  198. if((currentTime - _lastErrorTime) < 100)
  199. {
  200. if(++_errorCount > 3)
  201. {
  202. code = ErrorType.Fatal;
  203. }
  204. }
  205. else
  206. {
  207. _errorCount = 0;
  208. }
  209. _lastErrorTime = currentTime;
  210. _errorEntered = code;
  211. string errorMessage = string.Format(format, args);
  212. // copy the error message to the clip board
  213. // TODO: SetClipboardData(errorMessage);
  214. // add the message to the error list
  215. if(_errorList.Contains(errorMessage) == false)
  216. {
  217. _errorList.Add(errorMessage);
  218. }
  219. Stop();
  220. if(code == ErrorType.Disconnect)
  221. {
  222. _errorEntered = ErrorType.None;
  223. throw new Exception(errorMessage);
  224. }
  225. else if(code == ErrorType.Drop)
  226. {
  227. idLog.WriteLine("********************");
  228. idLog.WriteLine("ERROR: {0}", errorMessage);
  229. idLog.WriteLine("********************");
  230. _errorEntered = ErrorType.None;
  231. throw new Exception(errorMessage);
  232. }
  233. else
  234. {
  235. idLog.WriteLine("********************");
  236. idLog.WriteLine("ERROR: {0}", errorMessage);
  237. idLog.WriteLine("********************");
  238. }
  239. if(cvarSystem.GetBool("r_fullscreen") == true)
  240. {
  241. cmdSystem.BufferCommandText("vid_restart partial windowed\n", Execute.Now);
  242. }
  243. Sys_Error(errorMessage);
  244. }
  245. public void FatalError(string format, params object[] args)
  246. {
  247. ICVarSystem cvarSystem = this.Services.GetService<ICVarSystem>();
  248. ICommandSystem cmdSystem = this.Services.GetService<ICommandSystem>();
  249. if(cvarSystem.GetInt("com_productionMode") == 3)
  250. {
  251. Sys_Quit();
  252. }
  253. // if we got a recursive error, make it fatal
  254. if(_errorEntered != ErrorType.None)
  255. {
  256. // if we are recursively erroring while exiting
  257. // from a fatal error, just kill the entire
  258. // process immediately, which will prevent a
  259. // full screen rendering window covering the
  260. // error dialog
  261. idLog.Print("FATAL: recursed fatal error:\n{0}", string.Format(format, args));
  262. // write the console to a log file?
  263. Sys_Quit();
  264. }
  265. _errorEntered = ErrorType.Fatal;
  266. if(cvarSystem.GetBool("r_fullscreen") == true)
  267. {
  268. cmdSystem.BufferCommandText("vid_restart partial windowed", Execute.Now);
  269. }
  270. // TODO: Sys_SetFatalError( errorMessage );
  271. Sys_Error(format, args);
  272. }
  273. #endregion
  274. #region Events
  275. public bool ProcessEvent(SystemEvent ev)
  276. {
  277. idLog.Warning("TODO: ProcessEvent");
  278. IGame game = GetService<IGame>();
  279. IConsole console = GetService<IConsole>();
  280. IInputSystem inputSystem = GetService<IInputSystem>();
  281. // hitting escape anywhere brings up the menu
  282. // TODO: ingame
  283. /*if ( game && game->IsInGame() ) {
  284. if ( event->evType == SE_KEY && event->evValue2 == 1 && ( event->evValue == K_ESCAPE || event->evValue == K_JOY9 ) ) {
  285. if ( !game->Shell_IsActive() ) {
  286. // menus / etc
  287. if ( MenuEvent( event ) ) {
  288. return true;
  289. }
  290. console->Close();
  291. StartMenu();
  292. return true;
  293. } else {
  294. console->Close();
  295. // menus / etc
  296. if ( MenuEvent( event ) ) {
  297. return true;
  298. }
  299. game->Shell_ClosePause();
  300. }
  301. }
  302. }*/
  303. // let the pull-down console take it if desired
  304. if(console.ProcessEvent(ev, false) == true)
  305. {
  306. return true;
  307. }
  308. // TODO: shell
  309. /*if ( session->ProcessInputEvent( event ) ) {
  310. return true;
  311. }*/
  312. // TODO: dialog
  313. /*if ( Dialog().IsDialogActive() ) {
  314. Dialog().HandleDialogEvent( event );
  315. return true;
  316. }*/
  317. // Let Doom classic run events.
  318. // TODO: classic doom
  319. /*if ( IsPlayingDoomClassic() ) {
  320. // Translate the event to Doom classic format.
  321. event_t classicEvent;
  322. if ( event->evType == SE_KEY ) {
  323. if( event->evValue2 == 1 ) {
  324. classicEvent.type = ev_keydown;
  325. } else if( event->evValue2 == 0 ) {
  326. classicEvent.type = ev_keyup;
  327. }
  328. DoomLib::SetPlayer( 0 );
  329. extern Globals * g;
  330. if ( g != NULL ) {
  331. classicEvent.data1 = DoomLib::RemapControl( event->GetKey() );
  332. D_PostEvent( &classicEvent );
  333. }
  334. DoomLib::SetPlayer( -1 );
  335. }
  336. // Let the classics eat all events.
  337. return true;
  338. }*/
  339. // menus / etc
  340. if(ProcessMenuEvent(ev) == true)
  341. {
  342. return true;
  343. }
  344. // if we aren't in a game, force the console to take it
  345. if(_mapSpawned == false)
  346. {
  347. console.ProcessEvent(ev, true);
  348. return true;
  349. }
  350. // in game, exec bindings for all key downs
  351. if((ev.Type == SystemEventType.Key) && (ev.Value2 == 1))
  352. {
  353. inputSystem.ExecuteBinding((Keys) ev.Value);
  354. return true;
  355. }
  356. return false;
  357. }
  358. private bool ProcessMenuEvent(SystemEvent ev)
  359. {
  360. // TODO: signin manager
  361. /*if ( session->GetSignInManager().ProcessInputEvent( event ) ) {
  362. return true;
  363. }*/
  364. IGame game = GetService<IGame>();
  365. if((game != null) && (game.Shell_IsActive() == true))
  366. {
  367. return game.Shell_HandleGuiEvent(ev);
  368. }
  369. if(game != null)
  370. {
  371. idLog.Warning("TODO: return game->HandlePlayerGuiEvent( event );");
  372. }
  373. return false;
  374. }
  375. private void GuiFrameEvents()
  376. {
  377. IGame game = idEngine.Instance.GetService<IGame>();
  378. if(game != null)
  379. {
  380. game.Shell_SyncWithSession();
  381. }
  382. }
  383. #endregion
  384. #region Flow Control
  385. public new void Exit()
  386. {
  387. base.Exit();
  388. // don't try to shutdown if we are in a recursive error
  389. if(_errorEntered == ErrorType.None)
  390. {
  391. Shutdown();
  392. }
  393. Sys_Quit();
  394. }
  395. public void Run(string[] args)
  396. {
  397. _rawCommandLineArguments = args;
  398. base.Run();
  399. }
  400. private void Shutdown()
  401. {
  402. if(_shuttingDown == true)
  403. {
  404. return;
  405. }
  406. _shuttingDown = true;
  407. idLog.WriteLine("TODO: important! shutdown");
  408. /*// Kill any pending saves...
  409. printf( "session->GetSaveGameManager().CancelToTerminate();\n" );
  410. session->GetSaveGameManager().CancelToTerminate();
  411. // kill sound first
  412. printf( "soundSystem->StopAllSounds();\n" );
  413. soundSystem->StopAllSounds();
  414. // shutdown the script debugger
  415. // DebuggerServerShutdown();
  416. if ( aviCaptureMode ) {
  417. printf( "EndAVICapture();\n" );
  418. EndAVICapture();
  419. }
  420. printf( "Stop();\n" );
  421. Stop();
  422. printf( "CleanupShell();\n" );
  423. CleanupShell();
  424. printf( "delete loadGUI;\n" );
  425. delete loadGUI;
  426. loadGUI = NULL;
  427. printf( "delete renderWorld;\n" );
  428. delete renderWorld;
  429. renderWorld = NULL;
  430. printf( "delete soundWorld;\n" );
  431. delete soundWorld;
  432. soundWorld = NULL;
  433. printf( "delete menuSoundWorld;\n" );
  434. delete menuSoundWorld;
  435. menuSoundWorld = NULL;
  436. // shut down the session
  437. printf( "session->ShutdownSoundRelatedSystems();\n" );
  438. session->ShutdownSoundRelatedSystems();
  439. printf( "session->Shutdown();\n" );
  440. session->Shutdown();
  441. // shutdown, deallocate leaderboard definitions.
  442. if( game != NULL ) {
  443. printf( "game->Leaderboards_Shutdown();\n" );
  444. game->Leaderboards_Shutdown();
  445. }
  446. // shut down the user interfaces
  447. printf( "uiManager->Shutdown();\n" );
  448. uiManager->Shutdown();
  449. // shut down the sound system
  450. printf( "soundSystem->Shutdown();\n" );
  451. soundSystem->Shutdown();
  452. // shut down the user command input code
  453. printf( "usercmdGen->Shutdown();\n" );
  454. usercmdGen->Shutdown();
  455. // shut down the event loop
  456. printf( "eventLoop->Shutdown();\n" );
  457. eventLoop->Shutdown();
  458. // shutdown the decl manager
  459. printf( "declManager->Shutdown();\n" );
  460. declManager->Shutdown();
  461. // shut down the renderSystem
  462. printf( "renderSystem->Shutdown();\n" );
  463. renderSystem->Shutdown();
  464. printf( "commonDialog.Shutdown();\n" );
  465. commonDialog.Shutdown();
  466. // unload the game dll
  467. printf( "UnloadGameDLL();\n" );
  468. UnloadGameDLL();
  469. printf( "saveFile.Clear( true );\n" );
  470. saveFile.Clear( true );
  471. printf( "stringsFile.Clear( true );\n" );
  472. stringsFile.Clear( true );
  473. // only shut down the log file after all output is done
  474. printf( "CloseLogFile();\n" );
  475. CloseLogFile();
  476. // shut down the file system
  477. printf( "fileSystem->Shutdown( false );\n" );
  478. fileSystem->Shutdown( false );
  479. // shut down non-portable system services
  480. printf( "Sys_Shutdown();\n" );
  481. Sys_Shutdown();
  482. // shut down the console
  483. printf( "console->Shutdown();\n" );
  484. console->Shutdown();
  485. // shut down the key system
  486. printf( "idKeyInput::Shutdown();\n" );
  487. idKeyInput::Shutdown();
  488. // shut down the cvar system
  489. printf( "cvarSystem->Shutdown();\n" );
  490. cvarSystem->Shutdown();
  491. // shut down the console command system
  492. printf( "cmdSystem->Shutdown();\n" );
  493. cmdSystem->Shutdown();*/
  494. // free any buffered warning messages
  495. idLog.ClearWarnings(idLicensee.GameName + " shutdown");
  496. }
  497. /// <summary>
  498. /// Called on errors and game exits.
  499. /// </summary>
  500. /// <param name="resetSession"></param>
  501. private void Stop(bool resetSession = true)
  502. {
  503. idLog.WriteLine("TODO: Stop");
  504. /*ClearWipe();
  505. // clear mapSpawned and demo playing flags
  506. UnloadMap();
  507. soundSystem->StopAllSounds();
  508. insideUpdateScreen = false;
  509. insideExecuteMapChange = false;
  510. // drop all guis
  511. ExitMenu();
  512. if ( resetSession ) {
  513. session->QuitMatchToTitle();
  514. }*/
  515. }
  516. #endregion
  517. #region Initialization
  518. /// <summary>
  519. /// Allows the game to perform any initialization it needs to before starting to run.
  520. /// This is where it can query for any required services and load any non-graphic
  521. /// related content. Calling base.Initialize will enumerate through any components
  522. /// and initialize them as well.
  523. /// </summary>
  524. protected override void Initialize()
  525. {
  526. // done before Com/Sys_Init since we need this for error output
  527. // TODO:
  528. /*idLog.WriteLine("TODO: Sys_CreateConsole();");
  529. idLog.WriteLine("TODO: optimalPCTBuffer( 0.5f );");*/
  530. _currentGame = CurrentGame.Doom3BFG;
  531. _idealCurrentGame = CurrentGame.Doom3BFG;
  532. /*idLog.WriteLine("TODO: snapCurrent.localTime = -1;");
  533. idLog.WriteLine("TODO: snapPrevious.localTime = -1;");
  534. idLog.WriteLine("TODO: snapCurrent.serverTime = -1;");
  535. idLog.WriteLine("TODO: snapPrevious.serverTime = -1;");
  536. idLog.WriteLine("TODO: ClearWipe();");*/
  537. try
  538. {
  539. // clear warning buffer
  540. idLog.ClearWarnings(idLicensee.GameName + " initialization");
  541. // parse command line options
  542. ParseCommandLine(_rawCommandLineArguments);
  543. // init some systems
  544. ICVarSystem cvarSystem = new idCVarSystem();
  545. ICommandSystem cmdSystem = new idCommandSystem();
  546. IPlatformService platform = FindPlatform();
  547. IFileSystem fileSystem = new idFileSystem();
  548. ILocalization localization = new idLocalization();
  549. IInputSystem inputSystem = new idInputSystem();
  550. IConsole console = new idConsole();
  551. IDeclManager declManager = new idDeclManager();
  552. IRenderSystem renderSystem = new idRenderSystem(_graphicsDeviceManager);
  553. IResolutionScale resolutionScale = new idResolutionScale();
  554. IUserInterfaceManager userInterfaceManager = new idUserInterfaceManager();
  555. IEventLoop eventLoop = new idEventLoop();
  556. ISession session = FindSession();
  557. this.Services.AddService(typeof(ICVarSystem), cvarSystem);
  558. this.Services.AddService(typeof(ICommandSystem), cmdSystem);
  559. this.Services.AddService(typeof(IPlatformService), platform);
  560. this.Services.AddService(typeof(ILocalization), localization);
  561. this.Services.AddService(typeof(IFileSystem), fileSystem);
  562. this.Services.AddService(typeof(IInputSystem), inputSystem);
  563. this.Services.AddService(typeof(IConsole), console);
  564. this.Services.AddService(typeof(IDeclManager), declManager);
  565. this.Services.AddService(typeof(IRenderSystem), renderSystem);
  566. this.Services.AddService(typeof(IResolutionScale), resolutionScale);
  567. this.Services.AddService(typeof(IUserInterfaceManager), userInterfaceManager);
  568. this.Services.AddService(typeof(ISession), session);
  569. this.Services.AddService(typeof(IEventLoop), eventLoop);
  570. cvarSystem.Initialize();
  571. cmdSystem.Initialize();
  572. platform.Initialize();
  573. localization.Initialize();
  574. fileSystem.Initialize();
  575. // scan for commands
  576. cmdSystem.Scan();
  577. idLog.WriteLine("Command line: {0}", String.Join(" ", _rawCommandLineArguments));
  578. idLog.WriteLine("QA Timing INIT");
  579. idLog.WriteLine(idVersion.ToString(platform));
  580. // init journalling, etc
  581. eventLoop.Initialize();
  582. // initialize key input/binding, done early so bind command exists
  583. // init the console so we can take prints
  584. inputSystem.Initialize();
  585. console.Initialize();
  586. // get architecture info
  587. Sys_Init();
  588. // initialize networking
  589. idLog.WriteLine("TODO: Sys_InitNetworking();");
  590. // override cvars from command line
  591. StartupVariable(null);
  592. _consoleUsed = cvarSystem.GetBool("com_allowConsole");
  593. if(Sys_AlreadyRunning() == true)
  594. {
  595. Sys_Quit();
  596. }
  597. // initialize processor specific SIMD implementation
  598. idLog.WriteLine("TODO: InitSIMD();");
  599. string defaultLang = Sys_DefaultLanguage();
  600. _isJapaneseSKU = defaultLang.Equals(idLanguage.Japanese, StringComparison.OrdinalIgnoreCase);
  601. // Allow the system to set a default lanugage
  602. Sys_SetLanguageFromSystem();
  603. // pre-allocate our 20 MB save buffer here on time, instead of on-demand for each save....
  604. idLog.WriteLine("TOOD: savefile pre-allocation");
  605. /*saveFile.SetNameAndType( SAVEGAME_CHECKPOINT_FILENAME, SAVEGAMEFILE_BINARY );
  606. saveFile.PreAllocate( MIN_SAVEGAME_SIZE_BYTES );
  607. stringsFile.SetNameAndType( SAVEGAME_STRINGS_FILENAME, SAVEGAMEFILE_BINARY );
  608. stringsFile.PreAllocate( MAX_SAVEGAME_STRING_TABLE_SIZE );*/
  609. fileSystem.BeginLevelLoad("_startup"/* TODO: , saveFile.GetDataPtr(), saveFile.GetAllocated()*/);
  610. // initialize the declaration manager
  611. declManager.Initialize();
  612. // init the parallel job manager
  613. idLog.WriteLine("WARNING: parallelJobManager->Init();");
  614. // exec the startup scripts
  615. cmdSystem.BufferCommandText("exec default.cfg");
  616. // skip the config file if "safe" is on the command line
  617. if((IsSafeMode() == false) && (cvarSystem.GetBool("g_demoMode") == false))
  618. {
  619. cmdSystem.BufferCommandText(string.Format("exec {0}", idLicensee.ConfigFile));
  620. }
  621. cmdSystem.BufferCommandText("exec autoexec.cfg");
  622. // run cfg execution
  623. cmdSystem.ExecuteCommandBuffer();
  624. // re-override anything from the config files with command line args
  625. StartupVariable(null);
  626. // if any archived cvars are modified after this, we will trigger a writing of the config file
  627. cvarSystem.ClearModifiedFlags(CVarFlags.Archive);
  628. // support up to 2 digits after the decimal point
  629. _engineHzDenominator = 100 * cvarSystem.GetInt64("com_engineHz");
  630. _engineHzLatched = cvarSystem.GetFloat("com_engineHz");
  631. // init renderer
  632. renderSystem.Initialize();
  633. // start the sound system, but don't do any hardware operations yet
  634. idLog.WriteLine("TODO: soundSystem->Init();");
  635. _whiteMaterial = declManager.FindMaterial("_white");
  636. string sysLang = cvarSystem.GetString("sys_lang");
  637. if(sysLang.Equals(idLanguage.French, StringComparison.OrdinalIgnoreCase) == true)
  638. {
  639. // if the user specified french, we show french no matter what SKU
  640. _splashScreen = declManager.FindMaterial("guis/assets/splash/legal_french");
  641. }
  642. else if(defaultLang.Equals(idLanguage.French, StringComparison.OrdinalIgnoreCase) == true)
  643. {
  644. // if the lead sku is french (ie: europe), display figs
  645. _splashScreen = declManager.FindMaterial("guis/assets/splash/legal_figs");
  646. }
  647. else
  648. {
  649. // otherwise show it in english
  650. _splashScreen = declManager.FindMaterial("guis/assets/splash/legal_english");
  651. }
  652. }
  653. catch(Exception ex)
  654. {
  655. throw new Exception("Uh oh!", ex);
  656. Sys_Error("Error during initialization");
  657. }
  658. base.Initialize();
  659. }
  660. private void Initialize2()
  661. {
  662. try
  663. {
  664. ICVarSystem cvarSystem = this.GetService<ICVarSystem>();
  665. IDeclManager declManager = this.GetService<IDeclManager>();
  666. IFileSystem fileSystem = this.GetService<IFileSystem>();
  667. IUserInterfaceManager userInterfaceManager = this.GetService<IUserInterfaceManager>();
  668. ISession session = this.GetService<ISession>();
  669. int legalMinTime = 4000;
  670. legalMinTime = 0;
  671. bool showVideo = ((cvarSystem.GetBool("com_skipIntroVideos") == false) && (fileSystem.UsingResourceFiles == true));
  672. if(showVideo == true)
  673. {
  674. idLog.Warning("TODO: RenderBink( \"video\\loadvideo.bik\" );");
  675. RenderSplash();
  676. RenderSplash();
  677. }
  678. else
  679. {
  680. idLog.WriteLine("Skipping Intro Videos!");
  681. // display the legal splash screen
  682. RenderSplash();
  683. RenderSplash();
  684. }
  685. long legalStartTime = this.ElapsedTime;
  686. declManager.RegisterDeclFolder("skins", ".skin", DeclType.Skin);
  687. declManager.RegisterDeclFolder("sound", ".sndshd", DeclType.Sound);
  688. // initialize string database so we can use it for loading messages
  689. InitLanguageDict();
  690. idLog.Warning("TODO: REST OF INIT");
  691. // spawn the game thread, even if we are going to run without SMP
  692. // one meg stack, because it can parse decls from gui surfaces (unfortunately)
  693. // use a lower priority so job threads can run on the same core
  694. _gameThread = new idGameThread();
  695. _gameThread.StartWorkerThread( "Game/Draw", ThreadCore.C_1B, ThreadPriority.BelowNormal, 0x100000);
  696. // boost this thread's priority, so it will prevent job threads from running while
  697. // the render back end still has work to do
  698. idLog.Warning("TODO: Sys_SetRumble( 0, 0, 0 );");
  699. // initialize the user interfaces
  700. userInterfaceManager.Init();
  701. // startup the script debugger
  702. // DebuggerServerInit();
  703. // load the game dll
  704. LoadGameDLL();
  705. // On the PC touch them all so they get included in the resource build
  706. /*if ( !fileSystem->UsingResourceFiles() ) {
  707. declManager->FindMaterial( "guis/assets/splash/legal_english" );
  708. declManager->FindMaterial( "guis/assets/splash/legal_french" );
  709. declManager->FindMaterial( "guis/assets/splash/legal_figs" );
  710. // register the japanese font so it gets included
  711. renderSystem->RegisterFont( "DFPHeiseiGothicW7" );
  712. // Make sure all videos get touched because you can bring videos from one map to another, they need to be included in all maps
  713. for ( int i = 0; i < declManager->GetNumDecls( DECL_VIDEO ); i++ ) {
  714. declManager->DeclByIndex( DECL_VIDEO, i );
  715. }
  716. }
  717. fileSystem->UnloadResourceContainer( "_ordered" );
  718. // the same idRenderWorld will be used for all games
  719. // and demos, insuring that level specific models
  720. // will be freed
  721. renderWorld = renderSystem->AllocRenderWorld();
  722. soundWorld = soundSystem->AllocSoundWorld( renderWorld );
  723. menuSoundWorld = soundSystem->AllocSoundWorld( NULL );
  724. menuSoundWorld->PlaceListener( vec3_origin, mat3_identity, 0 );*/
  725. // init the session
  726. session.Initialize();
  727. /*session->InitializeSoundRelatedSystems();
  728. InitializeMPMapsModes();
  729. // leaderboards need to be initialized after InitializeMPMapsModes, which populates the MP Map list.
  730. if( game != NULL ) {
  731. game->Leaderboards_Init();
  732. }*/
  733. CreateMainMenu();
  734. CreateDialog();
  735. /*
  736. // load the console history file
  737. consoleHistory.LoadHistoryFile();*/
  738. AddStartupCommands();
  739. StartMenu(true);
  740. while((this.ElapsedTime - legalStartTime) < legalMinTime)
  741. {
  742. RenderSplash();
  743. Sys_GenerateEvents();
  744. Thread.Sleep(10);
  745. }
  746. // print all warnings queued during initialization
  747. /* PrintWarnings();
  748. // remove any prints from the notify lines
  749. console->ClearNotifyLines();
  750. CheckStartupStorageRequirements();
  751. if ( preload_CommonAssets.GetBool() && fileSystem->UsingResourceFiles() ) {
  752. idPreloadManifest manifest;
  753. manifest.LoadManifest( "_common.preload" );
  754. globalImages->Preload( manifest, false );
  755. soundSystem->Preload( manifest );
  756. }*/
  757. fileSystem.EndLevelLoad();
  758. // initialize support for Doom classic.
  759. //_doomClassicMaterial = declManager.FindMaterial("_doomClassic");
  760. /*idImage *image = globalImages->GetImage( "_doomClassic" );
  761. if ( image != NULL ) {
  762. idImageOpts opts;
  763. opts.format = FMT_RGBA8;
  764. opts.colorFormat = CFM_DEFAULT;
  765. opts.width = DOOMCLASSIC_RENDERWIDTH;
  766. opts.height = DOOMCLASSIC_RENDERHEIGHT;
  767. opts.numLevels = 1;
  768. image->AllocImage( opts, TF_LINEAR, TR_REPEAT );
  769. }*/
  770. // no longer need the splash screen
  771. if(_splashScreen != null)
  772. {
  773. for(int i = 0; i < _splashScreen.StageCount; i++)
  774. {
  775. idImage image = _splashScreen.GetStage(i).Texture.Image;
  776. if(image != null)
  777. {
  778. image.Purge();
  779. }
  780. }
  781. }
  782. idLog.WriteLine("--- Common Initialization Complete ---");
  783. idLog.WriteLine("QA Timing IIS: {0}ms", _gameTimer.ElapsedMilliseconds);
  784. // TODO:
  785. /*if(win32.win_notaskkeys.GetInteger())
  786. {
  787. DisableTaskKeys(TRUE, FALSE, /*( win32.win_notaskkeys.GetInteger() == 2 )*/
  788. /*FALSE);
  789. }*/
  790. // hide or show the early console as necessary
  791. /*if(win32.win_viewlog.GetInteger())
  792. {
  793. Sys_ShowConsole(1, true);
  794. }
  795. else
  796. {
  797. Sys_ShowConsole(0, false);
  798. }*/
  799. _initialized = true;
  800. }
  801. catch(Exception ex)
  802. {
  803. throw new Exception("Uh oh!", ex);
  804. Sys_Error("Error during initialization");
  805. }
  806. }
  807. private void CreateDialog()
  808. {
  809. IGame game = this.GetService<IGame>();
  810. IDialog dialog = game.CreateDialog();
  811. this.Services.AddService(typeof(IDialog), dialog);
  812. }
  813. private void CreateMainMenu()
  814. {
  815. IGame game = this.GetService<IGame>();
  816. if(game != null)
  817. {
  818. IDeclManager declManager = this.GetService<IDeclManager>();
  819. IRenderSystem renderSystem = this.GetService<IRenderSystem>();
  820. // TODO: soundSystem->BeginLevelLoad();
  821. IUserInterfaceManager userInterfaceManager = this.GetService<IUserInterfaceManager>();
  822. // note which media we are going to need to load
  823. declManager.BeginLevelLoad();
  824. renderSystem.BeginLevelLoad();
  825. // TODO: soundSystem->BeginLevelLoad();
  826. userInterfaceManager.BeginLevelLoad();
  827. // create main inside an "empty" game level load - so assets get
  828. // purged automagically when we transition to a "real" map
  829. game.Shell_CreateMenu(false);
  830. game.Shell_Show(true);
  831. game.Shell_SyncWithSession();
  832. // load
  833. renderSystem.EndLevelLoad();
  834. // TODO: soundSystem->EndLevelLoad();
  835. declManager.EndLevelLoad();
  836. userInterfaceManager.EndLevelLoad("");
  837. }
  838. }
  839. private void StartMenu(bool playIntro)
  840. {
  841. IGame game = this.GetService<IGame>();
  842. IConsole console = this.GetService<IConsole>();
  843. if((game != null) && (game.Shell_IsActive() == true))
  844. {
  845. return;
  846. }
  847. // TODO: readDemo
  848. /*if ( readDemo ) {
  849. // if we're playing a demo, esc kills it
  850. UnloadMap();
  851. }*/
  852. game.Shell_Show(true);
  853. game.Shell_SyncWithSession();
  854. console.Close();
  855. }
  856. /// <summary>
  857. /// Check for "safe" on the command line, which will
  858. /// skip loading of config file (DoomConfig.cfg)
  859. /// </summary>
  860. private bool IsSafeMode()
  861. {
  862. foreach(CommandArguments args in _commandLineArguments)
  863. {
  864. if((args.Get(0).Equals("safe", StringComparison.OrdinalIgnoreCase) == true)
  865. || (args.Get(0).Equals("cvar_restart", StringComparison.OrdinalIgnoreCase) == true))
  866. {
  867. args.Clear();
  868. return true;
  869. }
  870. }
  871. return false;
  872. }
  873. private void InitLanguageDict()
  874. {
  875. ICommandSystem cmdSystem = GetService<ICommandSystem>();
  876. ICVarSystem cvarSystem = GetService<ICVarSystem>();
  877. IFileSystem fileSystem = GetService<IFileSystem>();
  878. ILocalization loc = GetService<ILocalization>();
  879. // D3XP: Instead of just loading a single lang file for each language
  880. // we are going to load all files that begin with the language name
  881. // similar to the way pak files work. So you can place english001.lang
  882. // to add new strings to the english language dictionary
  883. idFileList files = fileSystem.ListFiles("strings", ".lang", true);
  884. string[] langFiles = files.Files;
  885. string langName = cvarSystem.GetString("sys_lang");
  886. // loop through the list and filter
  887. string[] currentLanguageList = langFiles.Where(c => c.StartsWith(langName)).ToArray();
  888. if(currentLanguageList.Length == 0)
  889. {
  890. // reset to english and try to load again
  891. cvarSystem.Set("sys_lang", idLanguage.English);
  892. langName = cvarSystem.GetString("sys_lang");
  893. currentLanguageList = langFiles.Where(c => c.StartsWith(langName)).ToArray();
  894. }
  895. loc.Clear();
  896. foreach(string lang in currentLanguageList)
  897. {
  898. byte[] buffer = fileSystem.ReadFile(Path.Combine("strings", lang));
  899. if(buffer != null)
  900. {
  901. loc.Load(Encoding.UTF8.GetString(buffer), lang);
  902. }
  903. }
  904. }
  905. private void LoadGameDLL()
  906. {
  907. IFileSystem fileSystem = this.GetService<IFileSystem>();
  908. ICVarSystem cvarSystem = this.GetService<ICVarSystem>();
  909. // from executable directory first - this is handy for developement
  910. string dllName = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
  911. dllName = Path.Combine(dllName, "idTech4.Game.dll");
  912. if(File.Exists(dllName) == false)
  913. {
  914. dllName = null;
  915. }
  916. if(dllName == null)
  917. {
  918. dllName = fileSystem.GetAbsolutePath(null, idLicensee.BaseGameDirectory, "idTech4.Game.dll");
  919. }
  920. // register some extra assembly paths
  921. AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs e) => {
  922. string name = e.Name;
  923. if(name.IndexOf(",") != -1)
  924. {
  925. name = e.Name.Substring(0, e.Name.IndexOf(","));
  926. }
  927. if(name.EndsWith(".dll") == false)
  928. {
  929. name = name + ".dll";
  930. }
  931. return Assembly.LoadFile(fileSystem.GetAbsolutePath(fileSystem.BasePath, idLicensee.BaseGameDirectory, name));
  932. };
  933. idLog.WriteLine("Loading game DLL: '{0}'", dllName);
  934. Assembly asm = Assembly.LoadFile(Path.GetFullPath(dllName));
  935. IGame game = (IGame) asm.CreateInstance("idTech4.Game.idGame");
  936. IGameEdit gameEdit = (IGameEdit) asm.CreateInstance("idTech4.Game.idGameEdit");
  937. this.Services.AddService(typeof(IGame), game);
  938. this.Services.AddService(typeof(IGameEdit), gameEdit);
  939. game.Init();
  940. }
  941. protected override void OnExiting(object sender, EventArgs args)
  942. {
  943. base.OnExiting(sender, args);
  944. Shutdown();
  945. }
  946. private IPlatformService FindPlatform()
  947. {
  948. // TODO: clean this up
  949. #if WINDOWS || LINUX
  950. string assemblyName = "idTech4.Platform.PC.dll";
  951. string typeName = "idTech4.Platform.PC.PCPlatform";
  952. #else
  953. return null;
  954. #endif
  955. assemblyName = Path.Combine(Environment.CurrentDirectory, assemblyName);
  956. return Assembly.LoadFile(assemblyName).CreateInstance(typeName) as IPlatformService;
  957. }
  958. private ISession FindSession()
  959. {
  960. // TODO: clean this up
  961. #if WINDOWS || LINUX
  962. string assemblyName = "idTech4.Platform.PC.dll";
  963. string typeName = "idTech4.Platform.PC.PCSession";
  964. #else
  965. return null;
  966. #endif
  967. assemblyName = Path.Combine(Environment.CurrentDirectory, assemblyName);
  968. return Assembly.LoadFile(assemblyName).CreateInstance(typeName) as ISession;
  969. }
  970. /// <summary>
  971. /// Adds command line parameters as script statements commands are separated by + signs
  972. /// </summary>
  973. /// <remarks>
  974. /// Returns true if any late commands were added, which will keep the demoloop from immediately starting.
  975. /// </remarks>
  976. private void AddStartupCommands()
  977. {
  978. ICommandSystem cmdSystem = this.GetService<ICommandSystem>();
  979. foreach(CommandArguments args in _commandLineArguments)
  980. {
  981. if(args.Length == 0)
  982. {
  983. return;
  984. }
  985. // directly as tokenized so nothing gets screwed
  986. cmdSystem.BufferCommandArgs(args, Execute.Append);
  987. }
  988. }
  989. private void ParseCommandLine(string[] args)
  990. {
  991. List<CommandArguments> argList = new List<CommandArguments>();
  992. CommandArguments current = null;
  993. foreach(string arg in args)
  994. {
  995. if(arg.StartsWith("+") == true)
  996. {
  997. current = new CommandArguments();
  998. current.AppendArg(arg.Substring(1));
  999. argList.Add(current);
  1000. }
  1001. else
  1002. {
  1003. if(current == null)
  1004. {
  1005. current = new CommandArguments();
  1006. argList.Add(current);
  1007. }
  1008. current.AppendArg(arg);
  1009. }
  1010. }
  1011. _commandLineArguments = argList.ToArray();
  1012. }
  1013. private void PerformGameSwitch()
  1014. {
  1015. // if the session state is past the menu, we should be in Doom 3.
  1016. // this will happen if, for example, we accept an invite while playing
  1017. // Doom or Doom 2.
  1018. ISession session = GetService<ISession>();
  1019. ICVarSystem cvarSystem = GetService<ICVarSystem>();
  1020. if(session.State > SessionState.Idle)
  1021. {
  1022. _idealCurrentGame = CurrentGame.Doom3BFG;
  1023. }
  1024. if(_currentGame == _idealCurrentGame)
  1025. {
  1026. return;
  1027. }
  1028. if((_idealCurrentGame == CurrentGame.DoomClassic) || (_idealCurrentGame == CurrentGame.Doom2Classic))
  1029. {
  1030. idLog.Warning("TODO: switch to doom classic");
  1031. // Pause Doom 3 sound.
  1032. /*if ( menuSoundWorld != NULL ) {
  1033. menuSoundWorld->Pause();
  1034. }
  1035. DoomLib::skipToNew = false;
  1036. DoomLib::skipToLoad = false;
  1037. // Reset match parameters for the classics.
  1038. DoomLib::matchParms = idMatchParameters();
  1039. // The classics use the usercmd manager too, clear it.
  1040. userCmdMgr.SetDefaults();
  1041. // Classics need a local user too.
  1042. session->UpdateSignInManager();
  1043. session->GetSignInManager().RegisterLocalUser( 0 );
  1044. com_engineHz_denominator = 100LL * DOOM_CLASSIC_HZ;
  1045. com_engineHz_latched = DOOM_CLASSIC_HZ;
  1046. DoomLib::SetCurrentExpansion( idealCurrentGame );*/
  1047. }
  1048. else if(_idealCurrentGame == CurrentGame.Doom3BFG)
  1049. {
  1050. idLog.Warning("TODO: DoomLib::Interface.Shutdown();");
  1051. _engineHzDenominator = (long) (100L * cvarSystem.GetFloat("com_engineHz"));
  1052. _engineHzLatched = cvarSystem.GetFloat("com_engineHz");
  1053. // don't MoveToPressStart if we have an invite, we need to go directly to the lobby
  1054. if(session.State <= SessionState.Idle)
  1055. {
  1056. session.MoveToPressStart();
  1057. }
  1058. // unpause Doom 3 sound
  1059. idLog.Warning("TODO: unpause sound");
  1060. /*if ( menuSoundWorld != NULL ) {
  1061. menuSoundWorld->UnPause();
  1062. }*/
  1063. }
  1064. _currentGame = _idealCurrentGame;
  1065. }
  1066. private void RenderSplash()
  1067. {
  1068. IRenderSystem renderSystem = GetService<IRenderSystem>();
  1069. float sysWidth = renderSystem.Width * renderSystem.PixelAspect;
  1070. float sysHeight = renderSystem.Height;
  1071. float sysAspect = sysWidth / sysHeight;
  1072. float splashAspect = 16.0f / 9.0f;
  1073. float adjustment = sysAspect / splashAspect;
  1074. float barHeight = (adjustment >= 1.0f) ? 0.0f : (1.0f - adjustment) * (float) Constants.ScreenHeight * 0.25f;
  1075. float barWidth = (adjustment <= 1.0f) ? 0.0f : (adjustment - 1.0f) * (float) Constants.ScreenWidth * 0.25f;
  1076. if(barHeight > 0.0f)
  1077. {
  1078. renderSystem.Color = idColor.Black;
  1079. renderSystem.DrawStretchPicture(0, 0, Constants.ScreenWidth, barHeight, 0, 0, 1, 1, _whiteMaterial);
  1080. renderSystem.DrawStretchPicture(0, Constants.ScreenHeight - barHeight, Constants.ScreenWidth, barHeight, 0, 0, 1, 1, _whiteMaterial);
  1081. }
  1082. if(barWidth > 0.0f)
  1083. {
  1084. renderSystem.Color = idColor.Black;
  1085. renderSystem.DrawStretchPicture(0, 0, barWidth, Constants.ScreenHeight, 0, 0, 1, 1, _whiteMaterial);
  1086. renderSystem.DrawStretchPicture(Constants.ScreenWidth - barWidth, 0, barWidth, Constants.ScreenHeight, 0, 0, 1, 1, _whiteMaterial);
  1087. }
  1088. renderSystem.Color = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
  1089. renderSystem.DrawStretchPicture(barWidth, barHeight, Constants.ScreenWidth - barWidth * 2.0f, Constants.ScreenHeight - barHeight * 2.0f, 0, 0, 1, 1, _splashScreen);
  1090. LinkedListNode<idRenderCommand> cmd = renderSystem.SwapCommandBuffers(out _speeds_Frontend, out _speeds_Backend, out _speeds_Shadows, out _speeds_Gpu);
  1091. renderSystem.RenderCommandBuffers(cmd);
  1092. }
  1093. /// <summary>
  1094. /// Searches for command line parameters that are set commands.
  1095. /// </summary>
  1096. /// <remarks>
  1097. /// If match is not NULL, only that cvar will be looked for.
  1098. /// That is necessary because cddir and basedir need to be set before the filesystem is started, but all other sets should
  1099. /// be after execing the config and default.
  1100. /// </remarks>
  1101. /// <param name="match"></param>
  1102. /// <param name="once"></param>
  1103. public void StartupVariable(string match)
  1104. {
  1105. List<CommandArguments> final = new List<CommandArguments>();
  1106. foreach(CommandArguments args in _commandLineArguments)
  1107. {
  1108. if(args.Get(0).ToLower() != "set")
  1109. {
  1110. continue;
  1111. }
  1112. string s = args.Get(1);
  1113. if((match == null) || (s.Equals(match, StringComparison.OrdinalIgnoreCase) == true))
  1114. {
  1115. this.GetService<ICVarSystem>().Set(s, args.Get(2));
  1116. }
  1117. }
  1118. }
  1119. #endregion
  1120. #region System
  1121. public T GetService<T>() where T : class
  1122. {
  1123. return this.Services.GetService<T>();
  1124. }
  1125. /// <summary>
  1126. /// Checks if a copy of D3 is running already.
  1127. /// </summary>
  1128. /// <returns></returns>
  1129. private bool Sys_AlreadyRunning()
  1130. {
  1131. #if !DEBUG
  1132. if(GetService<ICVarSystem>().GetBool("win_allowMultipleInstances") == false)
  1133. {
  1134. bool created;
  1135. _appMutex = new Mutex(false, "DOOM3", out created);
  1136. if(created == false)
  1137. {
  1138. return true;
  1139. }
  1140. }
  1141. #endif
  1142. return false;
  1143. }
  1144. private string Sys_DefaultLanguage()
  1145. {
  1146. // sku breakdowns are as follows
  1147. // EFIGS Digital
  1148. // EF S North America
  1149. // FIGS EU
  1150. // E UK
  1151. // JE Japan
  1152. // If japanese exists, default to japanese
  1153. // else if english exists, defaults to english
  1154. // otherwise, french
  1155. return idLanguage.English;
  1156. }
  1157. /// <summary>
  1158. /// Show the early console as an error dialog.
  1159. /// </summary>
  1160. /// <param name="format"></param>
  1161. /// <param name="args"></param>
  1162. private void Sys_Error(string format, params object[] args)
  1163. {
  1164. string errorMessage = string.Format(format, args);
  1165. idLog.WriteLine("=========================================");
  1166. idLog.WriteLine("ERROR: {0}", errorMessage);
  1167. idLog.WriteLine("=========================================");
  1168. idLog.WriteLine("TODO: systemConsole");
  1169. // TODO: idE.SystemConsole.Append(errorMessage + Environment.NewLine);
  1170. // TODO: idE.SystemConsole.Show(1, true);
  1171. _gameTimer.Stop();
  1172. // TODO: Sys_ShutdownInput();
  1173. ICVarSystem cvarSystem = this.GetService<ICVarSystem>();
  1174. if((cvarSystem != null) && (cvarSystem.GetInt("com_productionMode") == 0))
  1175. {
  1176. // wait for the user to quit
  1177. // TODO: important!
  1178. /*while(true)
  1179. {
  1180. // TODO: if(idE.SystemConsole.IsDisposed == true)
  1181. {
  1182. Exit();
  1183. break;
  1184. }
  1185. Application.DoEvents();
  1186. Thread.Sleep(0);
  1187. }*/
  1188. }
  1189. // TODO: Sys_DestroyConsole();
  1190. Environment.Exit(1);
  1191. }
  1192. private void Sys_GenerateEvents()
  1193. {
  1194. if(_generateEventsEntered == true)
  1195. {
  1196. return;
  1197. }
  1198. _generateEventsEntered = true;
  1199. // pump the message loop
  1200. //Sys_PumpEvents();
  1201. // grab or release the mouse cursor if necessary
  1202. idEngine.Instance.GetService<IInputSystem>().ProcessFrame();
  1203. // check for console commands
  1204. // TODO: console commands
  1205. /*s = Sys_ConsoleInput();
  1206. if ( s ) {
  1207. char *b;
  1208. int len;
  1209. len = strlen( s ) + 1;
  1210. b = (char *)Mem_Alloc( len, TAG_EVENTS );
  1211. strcpy( b, s );
  1212. Sys_QueEvent( SE_CONSOLE, 0, 0, len, b, 0 );
  1213. }*/
  1214. _generateEventsEntered = false;
  1215. }
  1216. private void Sys_Init()
  1217. {
  1218. ICVarSystem cvarSystem = GetService<ICVarSystem>();
  1219. IPlatformService platform = GetService<IPlatformService>();
  1220. // not bothering with fetching the windows username.
  1221. cvarSystem.Set("win_username", Environment.UserName);
  1222. //
  1223. // Windows version
  1224. //
  1225. OperatingSystem osInfo = Environment.OSVersion;
  1226. if((osInfo.Platform == PlatformID.Win32S)
  1227. || (osInfo.Platform == PlatformID.Win32Windows))
  1228. {
  1229. Error("{0} requires Windows XP or above", idLicensee.GameName);
  1230. }
  1231. else if(osInfo.Platform == PlatformID.Win32NT)
  1232. {
  1233. if(osInfo.Version.Major <= 4)
  1234. {
  1235. cvarSystem.Set("sys_arch", "WinNT (NT)");
  1236. }
  1237. else if((osInfo.Version.Major == 5) && (osInfo.Version.Minor == 0))
  1238. {
  1239. cvarSystem.Set("sys_arch", "Win2K (NT)");
  1240. }
  1241. else if((osInfo.Version.Major == 5) && (osInfo.Version.Minor == 1))
  1242. {
  1243. cvarSystem.Set("sys_arch", "WinXP (NT)");
  1244. }
  1245. else if((osInfo.Version.Major == 6) && (osInfo.Version.Minor == 0))
  1246. {
  1247. cvarSystem.Set("sys_arch", "Vista");
  1248. }
  1249. else if((osInfo.Version.Major == 6) && (osInfo.Version.Minor == 1))
  1250. {
  1251. cvarSystem.Set("sys_arch", "Windows 7");
  1252. }
  1253. else
  1254. {
  1255. cvarSystem.Set("sys_arch", "Unknown NT variant");
  1256. }
  1257. }
  1258. //
  1259. // CPU type
  1260. //
  1261. if(cvarSystem.GetString("sys_cpustring").Equals("detect", StringComparison.OrdinalIgnoreCase) == true)
  1262. {
  1263. if(Environment.OSVersion.Version.Major >= 6)
  1264. {
  1265. idLog.WriteLine("{0} MHz, {1} cores, {2} threads", platform.ClockSpeed, platform.CoreCount, platform.ThreadCount);
  1266. }
  1267. else
  1268. {
  1269. idLog.WriteLine("{0} MHz", platform.ClockSpeed);
  1270. }
  1271. CpuCapabilities caps = platform.CpuCapabilities;
  1272. string capabilities = string.Empty;
  1273. if((caps & CpuCapabilities.AMD) == CpuCapabilities.AMD)
  1274. {
  1275. capabilities += "AMD CPU";
  1276. }
  1277. else if((caps & CpuCapabilities.Intel) == CpuCapabilities.Intel)
  1278. {
  1279. capabilities += "Intel CPU";
  1280. }
  1281. else if((caps & CpuCapabilities.Unsupported) == CpuCapabilities.Unsupported)
  1282. {
  1283. capabilities += "unsupported CPU";
  1284. }
  1285. else
  1286. {
  1287. capabilities += "generic CPU";
  1288. }
  1289. // TODO: can't make use of any of these features but nice to identify them anyway.
  1290. /*string += " with ";
  1291. if ( win32.cpuid & CPUID_MMX ) {
  1292. string += "MMX & ";
  1293. }
  1294. if ( win32.cpuid & CPUID_3DNOW ) {
  1295. string += "3DNow! & ";
  1296. }
  1297. if ( win32.cpuid & CPUID_SSE ) {
  1298. string += "SSE & ";
  1299. }
  1300. if ( win32.cpuid & CPUID_SSE2 ) {
  1301. string += "SSE2 & ";
  1302. }
  1303. if ( win32.cpuid & CPUID_SSE3 ) {
  1304. string += "SSE3 & ";
  1305. }
  1306. if ( win32.cpuid & CPUID_HTT ) {
  1307. string += "HTT & ";
  1308. }
  1309. string.StripTrailing( " & " );
  1310. string.StripTrailing( " with " );*/
  1311. cvarSystem.Set("sys_cpustring", capabilities);
  1312. }
  1313. idLog.WriteLine(cvarSystem.GetString("sys_cpustring"));
  1314. idLog.WriteLine("{0} MB system memory", platform.TotalPhysicalMemory);
  1315. idLog.WriteLine("{0} MB video memory", platform.TotalVideoMemory);
  1316. }
  1317. private void Sys_SetLanguageFromSystem()
  1318. {
  1319. GetService<ICVarSystem>().Set("sys_lang", Sys_DefaultLanguage());
  1320. }
  1321. private void Sys_Quit()
  1322. {
  1323. _gameTimer.Stop();
  1324. // TODO: Sys_ShutdownInput();
  1325. // TODO: Sys_DestroyConsole();
  1326. Environment.Exit(0);
  1327. }
  1328. #endregion
  1329. /// <summary>
  1330. /// Allows the game to run logic such as updating the world,
  1331. /// checking for collisions, gathering input, and playing audio.
  1332. /// </summary>
  1333. /// <param name="gameTime">Provides a snapshot of timing values.</param>
  1334. protected override void Update(GameTime gameTime)
  1335. {
  1336. // FIXME: this is a hack to get the render window up so we can show the loading messages.
  1337. // it doesn't usually come up until all initialization has been completed and one tick has been run.
  1338. // this causes none of the loading messages to appear and it looks like the program isn't loading!
  1339. if(_firstTick == true)
  1340. {
  1341. _firstTick = false;
  1342. _lastFrameTime = this.ElapsedTime;
  1343. base.Update(gameTime);
  1344. return;
  1345. }
  1346. else if(_initialized == false)
  1347. {
  1348. Initialize2();
  1349. base.Update(gameTime);
  1350. return;
  1351. }
  1352. IRenderSystem renderSystem = this.GetService<IRenderSystem>();
  1353. ICVarSystem cvarSystem = this.GetService<ICVarSystem>();
  1354. IInputSystem inputSystem = this.GetService<IInputSystem>();
  1355. ISession session = this.GetService<ISession>();
  1356. IGame game = this.GetService<IGame>();
  1357. IDialog dialog = this.GetService<IDialog>();
  1358. IEventLoop eventLoop = this.GetService<IEventLoop>();
  1359. LinkedListNode<idRenderCommand> renderCommands = null;
  1360. /*try*/
  1361. {
  1362. // TODO: SCOPED_PROFILE_EVENT( "Common::Frame" );
  1363. // This is the only place this is incremented
  1364. _frameNumber++;
  1365. // allow changing SIMD usage on the fly
  1366. if(cvarSystem.IsModified("com_forceGenericSIMD") == true)
  1367. {
  1368. idLog.Warning("TODO: idSIMD::InitProcessor( \"doom\", com_forceGenericSIMD.GetBool() );");
  1369. cvarSystem.ClearModified("com_forceGenericSIMD");
  1370. }
  1371. // Do the actual switch between Doom 3 and the classics here so
  1372. // that things don't get confused in the middle of the frame.
  1373. PerformGameSwitch();
  1374. // pump all the events
  1375. Sys_GenerateEvents();
  1376. // write config file if anything changed
  1377. // TODO: WriteConfiguration();
  1378. eventLoop.RunEventLoop();
  1379. // activate the shell if it's been requested
  1380. if((_showShellRequested == true) && (game != null))
  1381. {
  1382. game.Shell_Show(true);
  1383. _showShellRequested = false;
  1384. }
  1385. // if the console or another gui is down, we don't need to hold the mouse cursor
  1386. /*bool chatting = false;
  1387. if ( console->Active() || Dialog().IsDialogActive() || session->IsSystemUIShowing() || ( game && game->InhibitControls() && !IsPlayingDoomClassic() ) ) {
  1388. Sys_GrabMouseCursor( false );
  1389. usercmdGen->InhibitUsercmd( INHIBIT_SESSION, true );
  1390. chatting = true;
  1391. } else {
  1392. Sys_GrabMouseCursor( true );
  1393. usercmdGen->InhibitUsercmd( INHIBIT_SESSION, false );
  1394. }
  1395. const bool pauseGame = ( !mapSpawned || ( !IsMultiplayer() && ( Dialog().IsDialogPausing() || session->IsSystemUIShowing() || ( game && game->Shell_IsActive() ) ) ) ) && !IsPlayingDoomClassic();
  1396. */
  1397. bool pauseGame = false;
  1398. /*
  1399. // save the screenshot and audio from the last draw if needed
  1400. if ( aviCaptureMode ) {
  1401. idStr name = va("demos/%s/%s_%05i.tga", aviDemoShortName.c_str(), aviDemoShortName.c_str(), aviDemoFrameCount++ );
  1402. renderSystem->TakeScreenshot( com_aviDemoWidth.GetInteger(), com_aviDemoHeight.GetInteger(), name, com_aviDemoSamples.GetInteger(), NULL );

Large files files are truncated, but you can click here to view the full file