EventLoop.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. idCVar idEventLoop::com_journal( "com_journal", "0", CVAR_INIT|CVAR_SYSTEM, "1 = record journal, 2 = play back journal", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  23. idEventLoop eventLoopLocal;
  24. idEventLoop *eventLoop = &eventLoopLocal;
  25. /*
  26. =================
  27. idEventLoop::idEventLoop
  28. =================
  29. */
  30. idEventLoop::idEventLoop() {
  31. com_journalFile = NULL;
  32. com_journalDataFile = NULL;
  33. initialTimeOffset = 0;
  34. }
  35. /*
  36. =================
  37. idEventLoop::~idEventLoop
  38. =================
  39. */
  40. idEventLoop::~idEventLoop() {
  41. }
  42. /*
  43. =================
  44. idEventLoop::GetRealEvent
  45. =================
  46. */
  47. sysEvent_t idEventLoop::GetRealEvent() {
  48. int r;
  49. sysEvent_t ev;
  50. // either get an event from the system or the journal file
  51. if ( com_journal.GetInteger() == 2 ) {
  52. r = com_journalFile->Read( &ev, sizeof(ev) );
  53. if ( r != sizeof(ev) ) {
  54. common->FatalError( "Error reading from journal file" );
  55. }
  56. if ( ev.evPtrLength ) {
  57. ev.evPtr = Mem_ClearedAlloc( ev.evPtrLength, TAG_EVENTS );
  58. r = com_journalFile->Read( ev.evPtr, ev.evPtrLength );
  59. if ( r != ev.evPtrLength ) {
  60. common->FatalError( "Error reading from journal file" );
  61. }
  62. }
  63. } else {
  64. ev = Sys_GetEvent();
  65. // write the journal value out if needed
  66. if ( com_journal.GetInteger() == 1 ) {
  67. r = com_journalFile->Write( &ev, sizeof(ev) );
  68. if ( r != sizeof(ev) ) {
  69. common->FatalError( "Error writing to journal file" );
  70. }
  71. if ( ev.evPtrLength ) {
  72. r = com_journalFile->Write( ev.evPtr, ev.evPtrLength );
  73. if ( r != ev.evPtrLength ) {
  74. common->FatalError( "Error writing to journal file" );
  75. }
  76. }
  77. }
  78. }
  79. return ev;
  80. }
  81. /*
  82. =================
  83. idEventLoop::PushEvent
  84. =================
  85. */
  86. void idEventLoop::PushEvent( sysEvent_t *event ) {
  87. sysEvent_t *ev;
  88. static bool printedWarning;
  89. ev = &com_pushedEvents[ com_pushedEventsHead & (MAX_PUSHED_EVENTS-1) ];
  90. if ( com_pushedEventsHead - com_pushedEventsTail >= MAX_PUSHED_EVENTS ) {
  91. // don't print the warning constantly, or it can give time for more...
  92. if ( !printedWarning ) {
  93. printedWarning = true;
  94. common->Printf( "WARNING: Com_PushEvent overflow\n" );
  95. }
  96. if ( ev->evPtr ) {
  97. Mem_Free( ev->evPtr );
  98. }
  99. com_pushedEventsTail++;
  100. } else {
  101. printedWarning = false;
  102. }
  103. *ev = *event;
  104. com_pushedEventsHead++;
  105. }
  106. /*
  107. =================
  108. idEventLoop::GetEvent
  109. =================
  110. */
  111. sysEvent_t idEventLoop::GetEvent() {
  112. if ( com_pushedEventsHead > com_pushedEventsTail ) {
  113. com_pushedEventsTail++;
  114. return com_pushedEvents[ (com_pushedEventsTail-1) & (MAX_PUSHED_EVENTS-1) ];
  115. }
  116. return GetRealEvent();
  117. }
  118. /*
  119. =================
  120. idEventLoop::ProcessEvent
  121. =================
  122. */
  123. void idEventLoop::ProcessEvent( sysEvent_t ev ) {
  124. // track key up / down states
  125. if ( ev.evType == SE_KEY ) {
  126. idKeyInput::PreliminaryKeyEvent( ev.evValue, ( ev.evValue2 != 0 ) );
  127. }
  128. if ( ev.evType == SE_CONSOLE ) {
  129. // from a text console outside the game window
  130. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, (char *)ev.evPtr );
  131. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "\n" );
  132. } else {
  133. common->ProcessEvent( &ev );
  134. }
  135. // free any block data
  136. if ( ev.evPtr ) {
  137. Mem_Free( ev.evPtr );
  138. }
  139. }
  140. /*
  141. ===============
  142. idEventLoop::RunEventLoop
  143. ===============
  144. */
  145. int idEventLoop::RunEventLoop( bool commandExecution ) {
  146. sysEvent_t ev;
  147. while ( 1 ) {
  148. if ( commandExecution ) {
  149. // execute any bound commands before processing another event
  150. cmdSystem->ExecuteCommandBuffer();
  151. }
  152. ev = GetEvent();
  153. // if no more events are available
  154. if ( ev.evType == SE_NONE ) {
  155. return 0;
  156. }
  157. ProcessEvent( ev );
  158. }
  159. return 0; // never reached
  160. }
  161. /*
  162. =============
  163. idEventLoop::Init
  164. =============
  165. */
  166. void idEventLoop::Init() {
  167. initialTimeOffset = Sys_Milliseconds();
  168. common->StartupVariable( "journal" );
  169. if ( com_journal.GetInteger() == 1 ) {
  170. common->Printf( "Journaling events\n" );
  171. com_journalFile = fileSystem->OpenFileWrite( "journal.dat" );
  172. com_journalDataFile = fileSystem->OpenFileWrite( "journaldata.dat" );
  173. } else if ( com_journal.GetInteger() == 2 ) {
  174. common->Printf( "Replaying journaled events\n" );
  175. com_journalFile = fileSystem->OpenFileRead( "journal.dat" );
  176. com_journalDataFile = fileSystem->OpenFileRead( "journaldata.dat" );
  177. }
  178. if ( !com_journalFile || !com_journalDataFile ) {
  179. com_journal.SetInteger( 0 );
  180. com_journalFile = 0;
  181. com_journalDataFile = 0;
  182. common->Printf( "Couldn't open journal files\n" );
  183. }
  184. }
  185. /*
  186. =============
  187. idEventLoop::Shutdown
  188. =============
  189. */
  190. void idEventLoop::Shutdown() {
  191. if ( com_journalFile ) {
  192. fileSystem->CloseFile( com_journalFile );
  193. com_journalFile = NULL;
  194. }
  195. if ( com_journalDataFile ) {
  196. fileSystem->CloseFile( com_journalDataFile );
  197. com_journalDataFile = NULL;
  198. }
  199. }
  200. /*
  201. ================
  202. idEventLoop::Milliseconds
  203. Can be used for profiling, but will be journaled accurately
  204. ================
  205. */
  206. int idEventLoop::Milliseconds() {
  207. #if 1 // FIXME!
  208. return Sys_Milliseconds() - initialTimeOffset;
  209. #else
  210. sysEvent_t ev;
  211. // get events and push them until we get a null event with the current time
  212. do {
  213. ev = Com_GetRealEvent();
  214. if ( ev.evType != SE_NONE ) {
  215. Com_PushEvent( &ev );
  216. }
  217. } while ( ev.evType != SE_NONE );
  218. return ev.evTime;
  219. #endif
  220. }
  221. /*
  222. ================
  223. idEventLoop::JournalLevel
  224. ================
  225. */
  226. int idEventLoop::JournalLevel() const {
  227. return com_journal.GetInteger();
  228. }