2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 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 Source Code. If not, please request a copy in writing from id Software at the address below.
24 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.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
32 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> );
34 idEventLoop eventLoopLocal;
35 idEventLoop *eventLoop = &eventLoopLocal;
40 idEventLoop::idEventLoop
43 idEventLoop::idEventLoop( void ) {
44 com_journalFile = NULL;
45 com_journalDataFile = NULL;
46 initialTimeOffset = 0;
51 idEventLoop::~idEventLoop
54 idEventLoop::~idEventLoop( void ) {
59 idEventLoop::GetRealEvent
62 sysEvent_t idEventLoop::GetRealEvent( void ) {
66 // either get an event from the system or the journal file
67 if ( com_journal.GetInteger() == 2 ) {
68 r = com_journalFile->Read( &ev, sizeof(ev) );
69 if ( r != sizeof(ev) ) {
70 common->FatalError( "Error reading from journal file" );
72 if ( ev.evPtrLength ) {
73 ev.evPtr = Mem_ClearedAlloc( ev.evPtrLength );
74 r = com_journalFile->Read( ev.evPtr, ev.evPtrLength );
75 if ( r != ev.evPtrLength ) {
76 common->FatalError( "Error reading from journal file" );
82 // write the journal value out if needed
83 if ( com_journal.GetInteger() == 1 ) {
84 r = com_journalFile->Write( &ev, sizeof(ev) );
85 if ( r != sizeof(ev) ) {
86 common->FatalError( "Error writing to journal file" );
88 if ( ev.evPtrLength ) {
89 r = com_journalFile->Write( ev.evPtr, ev.evPtrLength );
90 if ( r != ev.evPtrLength ) {
91 common->FatalError( "Error writing to journal file" );
102 idEventLoop::PushEvent
105 void idEventLoop::PushEvent( sysEvent_t *event ) {
107 static bool printedWarning;
109 ev = &com_pushedEvents[ com_pushedEventsHead & (MAX_PUSHED_EVENTS-1) ];
111 if ( com_pushedEventsHead - com_pushedEventsTail >= MAX_PUSHED_EVENTS ) {
113 // don't print the warning constantly, or it can give time for more...
114 if ( !printedWarning ) {
115 printedWarning = true;
116 common->Printf( "WARNING: Com_PushEvent overflow\n" );
120 Mem_Free( ev->evPtr );
122 com_pushedEventsTail++;
124 printedWarning = false;
128 com_pushedEventsHead++;
133 idEventLoop::GetEvent
136 sysEvent_t idEventLoop::GetEvent( void ) {
137 if ( com_pushedEventsHead > com_pushedEventsTail ) {
138 com_pushedEventsTail++;
139 return com_pushedEvents[ (com_pushedEventsTail-1) & (MAX_PUSHED_EVENTS-1) ];
141 return GetRealEvent();
146 idEventLoop::ProcessEvent
149 void idEventLoop::ProcessEvent( sysEvent_t ev ) {
150 // track key up / down states
151 if ( ev.evType == SE_KEY ) {
152 idKeyInput::PreliminaryKeyEvent( ev.evValue, ( ev.evValue2 != 0 ) );
155 if ( ev.evType == SE_CONSOLE ) {
156 // from a text console outside the game window
157 cmdSystem->BufferCommandText( CMD_EXEC_APPEND, (char *)ev.evPtr );
158 cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "\n" );
160 session->ProcessEvent( &ev );
163 // free any block data
165 Mem_Free( ev.evPtr );
171 idEventLoop::RunEventLoop
174 int idEventLoop::RunEventLoop( bool commandExecution ) {
179 if ( commandExecution ) {
180 // execute any bound commands before processing another event
181 cmdSystem->ExecuteCommandBuffer();
186 // if no more events are available
187 if ( ev.evType == SE_NONE ) {
193 return 0; // never reached
201 void idEventLoop::Init( void ) {
203 initialTimeOffset = Sys_Milliseconds();
205 common->StartupVariable( "journal", false );
207 if ( com_journal.GetInteger() == 1 ) {
208 common->Printf( "Journaling events\n" );
209 com_journalFile = fileSystem->OpenFileWrite( "journal.dat" );
210 com_journalDataFile = fileSystem->OpenFileWrite( "journaldata.dat" );
211 } else if ( com_journal.GetInteger() == 2 ) {
212 common->Printf( "Replaying journaled events\n" );
213 com_journalFile = fileSystem->OpenFileRead( "journal.dat" );
214 com_journalDataFile = fileSystem->OpenFileRead( "journaldata.dat" );
217 if ( !com_journalFile || !com_journalDataFile ) {
218 com_journal.SetInteger( 0 );
220 com_journalDataFile = 0;
221 common->Printf( "Couldn't open journal files\n" );
227 idEventLoop::Shutdown
230 void idEventLoop::Shutdown( void ) {
231 if ( com_journalFile ) {
232 fileSystem->CloseFile( com_journalFile );
233 com_journalFile = NULL;
235 if ( com_journalDataFile ) {
236 fileSystem->CloseFile( com_journalDataFile );
237 com_journalDataFile = NULL;
243 idEventLoop::Milliseconds
245 Can be used for profiling, but will be journaled accurately
248 int idEventLoop::Milliseconds( void ) {
250 return Sys_Milliseconds() - initialTimeOffset;
254 // get events and push them until we get a null event with the current time
257 ev = Com_GetRealEvent();
258 if ( ev.evType != SE_NONE ) {
259 Com_PushEvent( &ev );
261 } while ( ev.evType != SE_NONE );
269 idEventLoop::JournalLevel
272 int idEventLoop::JournalLevel( void ) const {
273 return com_journal.GetInteger();