123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809 |
- // IcarusImplementation.cpp
- #include "stdafx.h"
- #include "IcarusImplementation.h"
- #include "BlockStream.h"
- #include "Sequence.h"
- #include "TaskManager.h"
- #include "Sequencer.h"
- #define STL_ITERATE( a, b ) for ( a = b.begin(); a != b.end(); a++ )
- #define STL_INSERT( a, b ) a.insert( a.end(), b );
- //////////////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // required implementation of CIcarusInterface
- IIcarusInterface* IIcarusInterface::GetIcarus(int flavor,bool constructIfNecessary)
- {
- if(!CIcarus::s_instances && constructIfNecessary)
- {
- CIcarus::s_flavorsAvailable = IGameInterface::s_IcarusFlavorsNeeded;
- if (!CIcarus::s_flavorsAvailable)
- {
- return NULL;
- }
- CIcarus::s_instances = new CIcarus*[CIcarus::s_flavorsAvailable];
- for (int index = 0; index < CIcarus::s_flavorsAvailable; index++)
- {
- CIcarus::s_instances[index] = new CIcarus(index);
- //OutputDebugString( "ICARUS flavor successfully created\n" );
- }
- }
-
- if(flavor >= CIcarus::s_flavorsAvailable || !CIcarus::s_instances )
- {
- return NULL;
- }
- return CIcarus::s_instances[flavor];
- }
- void IIcarusInterface::DestroyIcarus()
- {
- for(int index = 0; index < CIcarus::s_flavorsAvailable; index++)
- {
- delete CIcarus::s_instances[index];
- }
- delete[] CIcarus::s_instances;
- CIcarus::s_instances = NULL;
- CIcarus::s_flavorsAvailable = 0;
- }
- IIcarusInterface::~IIcarusInterface()
- {
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // CIcarus
- double CIcarus::ICARUS_VERSION = 1.40;
- int CIcarus::s_flavorsAvailable = 0;
- CIcarus** CIcarus::s_instances = NULL;
- CIcarus::CIcarus(int flavor) :
- m_flavor(flavor), m_nextSequencerID(0)
- {
- m_GUID = 0;
- #ifdef _DEBUG
- m_DEBUG_NumSequencerAlloc = 0;
- m_DEBUG_NumSequencerFreed = 0;
- m_DEBUG_NumSequencerResidual = 0;
- m_DEBUG_NumSequenceAlloc = 0;
- m_DEBUG_NumSequenceFreed = 0;
- m_DEBUG_NumSequenceResidual = 0;
- #endif
- m_ulBufferCurPos = 0;
- m_ulBytesRead = 0;
- m_byBuffer = NULL;
- }
- CIcarus::~CIcarus()
- {
- Delete();
- }
- #if defined (_DEBUG) && defined (_WIN32)
- #include "../qcommon/platform.h" // for OutputDebugString
- #endif
- void CIcarus::Delete( void )
- {
- Free();
- #ifdef _DEBUG
-
- char buffer[1024];
- OutputDebugString( "\nICARUS Instance Debug Info:\n---------------------------\n" );
- sprintf( (char *) buffer, "Sequencers Allocated:\t%d\n", m_DEBUG_NumSequencerAlloc );
- OutputDebugString( (const char *) &buffer );
- sprintf( (char *) buffer, "Sequencers Freed:\t\t%d\n", m_DEBUG_NumSequencerFreed );
- OutputDebugString( (const char *) &buffer );
- sprintf( (char *) buffer, "Sequencers Residual:\t%d\n\n", m_DEBUG_NumSequencerResidual );
- OutputDebugString( (const char *) &buffer );
- sprintf( (char *) buffer, "Sequences Allocated:\t%d\n", m_DEBUG_NumSequenceAlloc );
- OutputDebugString( (const char *) &buffer );
- sprintf( (char *) buffer, "Sequences Freed:\t\t%d\n", m_DEBUG_NumSequenceFreed );
- OutputDebugString( (const char *) &buffer );
- sprintf( (char *) buffer, "Sequences Residual:\t\t%d\n\n", m_DEBUG_NumSequenceResidual );
- OutputDebugString( (const char *) &buffer );
- OutputDebugString( "\n" );
- #endif
- }
- void CIcarus::Signal( const char *identifier )
- {
- m_signals[ identifier ] = 1;
- }
- bool CIcarus::CheckSignal( const char *identifier )
- {
- signal_m::iterator smi;
- smi = m_signals.find( identifier );
- if ( smi == m_signals.end() )
- return false;
- return true;
- }
- void CIcarus::ClearSignal( const char *identifier )
- {
- m_signals.erase( identifier );
- }
- void CIcarus::Free( void )
- {
- sequencer_l::iterator sri;
- //Delete any residual sequencers
- STL_ITERATE( sri, m_sequencers )
- {
- (*sri)->Free(this);
-
- #ifdef _DEBUG
- m_DEBUG_NumSequencerResidual++;
- #endif
- }
- m_sequencers.clear();
- m_signals.clear();
- sequence_l::iterator si;
- //Delete any residual sequences
- STL_ITERATE( si, m_sequences )
- {
- (*si)->Delete(this);
- delete (*si);
- #ifdef _DEBUG
- m_DEBUG_NumSequenceResidual++;
- #endif
- }
- m_sequences.clear();
- m_sequencerMap.clear();
- }
- int CIcarus::GetIcarusID( int gameID )
- {
- CSequencer *sequencer = CSequencer::Create();
- CTaskManager *taskManager = CTaskManager::Create();
-
- sequencer->Init( gameID, taskManager );
- taskManager->Init( sequencer );
- STL_INSERT( m_sequencers, sequencer );
- m_sequencerMap[sequencer->GetID()] = sequencer;
- #ifdef _DEBUG
- m_DEBUG_NumSequencerAlloc++;
- #endif
-
- return sequencer->GetID();
- }
- void CIcarus::DeleteIcarusID( int& icarusID )
- {
- CSequencer* sequencer = FindSequencer(icarusID);
- if(!sequencer)
- {
- icarusID = -1;
- return;
- }
- CTaskManager *taskManager = sequencer->GetTaskManager();
- if (taskManager->IsResident())
- {
- IGameInterface::GetGame()->DebugPrint( IGameInterface::WL_ERROR, "Refusing DeleteIcarusID(%d) because it is running!\n", icarusID);
- assert(0);
- return;
- }
- m_sequencerMap.erase(icarusID);
- // added 2/12/2 to properly delete blocks that were passed to the task manager
- sequencer->Recall(this);
- if ( taskManager )
- {
- taskManager->Free();
- delete taskManager;
- }
- m_sequencers.remove( sequencer );
- sequencer->Free(this);
- #ifdef _DEBUG
- m_DEBUG_NumSequencerFreed++;
- #endif
- icarusID = -1;
- }
- CSequence *CIcarus::GetSequence( void )
- {
- CSequence *sequence = CSequence::Create();
- //Assign the GUID
- sequence->SetID( m_GUID++ );
- STL_INSERT( m_sequences, sequence );
- #ifdef _DEBUG
- m_DEBUG_NumSequenceAlloc++;
- #endif
- return sequence;
- }
- CSequence *CIcarus::GetSequence( int id )
- {
- sequence_l::iterator si;
- STL_ITERATE( si, m_sequences )
- {
- if ( (*si)->GetID() == id )
- return (*si);
- }
- return NULL;
- }
- void CIcarus::DeleteSequence( CSequence *sequence )
- {
- m_sequences.remove( sequence );
- sequence->Delete(this);
- delete sequence;
- #ifdef _DEBUG
- m_DEBUG_NumSequenceFreed++;
- #endif
- }
- int CIcarus::AllocateSequences( int numSequences, int *idTable )
- {
- CSequence *sequence;
- for ( int i = 0; i < numSequences; i++ )
- {
- //If the GUID of this sequence is higher than the current, take this a the "current" GUID
- if ( idTable[i] > m_GUID )
- m_GUID = idTable[i];
- //Allocate the container sequence
- if ( ( sequence = GetSequence() ) == NULL )
- return false;
- //Override the given GUID with the real one
- sequence->SetID( idTable[i] );
- }
- return true;
- }
- void CIcarus::Precache(char* buffer, long length)
- {
- IGameInterface* game = IGameInterface::GetGame(m_flavor);
- CBlockStream stream;
- CBlockMember *blockMember;
- CBlock block;
- if ( stream.Open( buffer, length ) == 0 )
- return;
- const char *sVal1, *sVal2;
- //Now iterate through all blocks of the script, searching for keywords
- while ( stream.BlockAvailable() )
- {
- //Get a block
- if ( stream.ReadBlock( &block, this ) == 0 )
- return;
- //Determine what type of block this is
- switch( block.GetBlockID() )
- {
- case ID_CAMERA: // to cache ROFF files
- {
- float f = *(float *) block.GetMemberData( 0 );
- if (f == TYPE_PATH)
- {
- sVal1 = (const char *) block.GetMemberData( 1 );
- game->PrecacheRoff(sVal1);
- }
- }
- break;
- case ID_PLAY: // to cache ROFF files
-
- sVal1 = (const char *) block.GetMemberData( 0 );
- if (!stricmp(sVal1,"PLAY_ROFF"))
- {
- sVal1 = (const char *) block.GetMemberData( 1 );
- game->PrecacheRoff(sVal1);
- }
- break;
- //Run commands
- case ID_RUN:
- sVal1 = (const char *) block.GetMemberData( 0 );
- game->PrecacheScript( sVal1 );
- break;
-
- case ID_SOUND:
- sVal1 = (const char *) block.GetMemberData( 1 ); //0 is channel, 1 is filename
- game->PrecacheSound(sVal1);
- break;
- case ID_SET:
- blockMember = block.GetMember( 0 );
- //NOTENOTE: This will not catch special case get() inlines! (There's not really a good way to do that)
- //Make sure we're testing against strings
- if ( blockMember->GetID() == TK_STRING )
- {
- sVal1 = (const char *) block.GetMemberData( 0 );
- sVal2 = (const char *) block.GetMemberData( 1 );
-
- game->PrecacheFromSet( sVal1 , sVal2);
- }
- break;
- default:
- break;
- }
- //Clean out the block for the next pass
- block.Free(this);
- }
- //All done
- stream.Free();
- }
- CSequencer* CIcarus::FindSequencer(int sequencerID)
- {
- sequencer_m::iterator mi = m_sequencerMap.find( sequencerID );
- if ( mi == m_sequencerMap.end() )
- return NULL;
- return (*mi).second;
- }
- int CIcarus::Run(int icarusID, char* buffer, long length)
- {
- CSequencer* sequencer = FindSequencer(icarusID);
- if(sequencer)
- {
- return sequencer->Run(buffer, length, this);
- }
- return ICARUS_INVALID;
- }
- int CIcarus::SaveSequenceIDTable()
- {
- //Save out the number of sequences to follow
- int numSequences = m_sequences.size();
- BufferWrite( &numSequences, sizeof( numSequences ) );
- //Sequences are saved first, by ID and information
- sequence_l::iterator sqi;
- //First pass, save all sequences ID for reconstruction
- int *idTable = new int[ numSequences ];
- int itr = 0;
- if ( idTable == NULL )
- return false;
- STL_ITERATE( sqi, m_sequences )
- {
- idTable[itr++] = (*sqi)->GetID();
- }
- //game->WriteSaveData( 'SQTB', idTable, sizeof( int ) * numSequences );
- BufferWrite( idTable, sizeof( int ) * numSequences );
- delete[] idTable;
- return true;
- }
- int CIcarus::SaveSequences()
- {
- //Save out a listing of all the used sequences by ID
- SaveSequenceIDTable();
- //Save all the information in order
- sequence_l::iterator sqi;
- STL_ITERATE( sqi, m_sequences )
- {
- (*sqi)->Save();
- }
- return true;
- }
- int CIcarus::SaveSequencers()
- {
- //Save out the number of sequences to follow
- int numSequencers = m_sequencers.size();
- BufferWrite( &numSequencers, sizeof( numSequencers ) );
- //The sequencers are then saved
- int sequencessaved = 0;
- sequencer_l::iterator si;
- STL_ITERATE( si, m_sequencers )
- {
- (*si)->Save();
- sequencessaved++;
- }
- assert( sequencessaved == numSequencers );
- return true;
- }
- int CIcarus::SaveSignals()
- {
- int numSignals = m_signals.size();
- //game->WriteSaveData( 'ISIG', &numSignals, sizeof( numSignals ) );
- BufferWrite( &numSignals, sizeof( numSignals ) );
- signal_m::iterator si;
- STL_ITERATE( si, m_signals )
- {
- //game->WriteSaveData( 'ISIG', &numSignals, sizeof( numSignals ) );
- const char *name = ((*si).first).c_str();
-
- int length = strlen( name ) + 1;
- //Save out the string size
- BufferWrite( &length, sizeof( length ) );
- //Write out the string
- BufferWrite( (void *) name, length );
- }
- return true;
- }
- // Get the current Game flavor.
- int CIcarus::GetFlavor()
- {
- return m_flavor;
- }
- int CIcarus::Save()
- {
- // Allocate the temporary buffer.
- CreateBuffer();
- IGameInterface* game = IGameInterface::GetGame(m_flavor);
- //Save out a ICARUS save block header with the ICARUS version
- double version = ICARUS_VERSION;
- game->WriteSaveData( 'ICAR', &version, sizeof( version ) );
- //Save out the signals
- if ( SaveSignals() == false )
- {
- DestroyBuffer();
- return false;
- }
- //Save out the sequences
- if ( SaveSequences() == false )
- {
- DestroyBuffer();
- return false;
- }
- //Save out the sequencers
- if ( SaveSequencers() == false )
- {
- DestroyBuffer();
- return false;
- }
- // Write out the buffer with all our collected data.
- game->WriteSaveData( 'ISEQ', m_byBuffer, m_ulBufferCurPos );
- // De-allocate the temporary buffer.
- DestroyBuffer();
- return true;
- }
- int CIcarus::LoadSignals()
- {
- int numSignals;
- BufferRead( &numSignals, sizeof( numSignals ) );
- for ( int i = 0; i < numSignals; i++ )
- {
- char buffer[1024];
- int length;
- //Get the size of the string
- BufferRead( &length, sizeof( length ) );
- //Get the string
- BufferRead( &buffer, length );
- //Turn it on and add it to the system
- Signal( (const char *) &buffer );
- }
- return true;
- }
- int CIcarus::LoadSequence()
- {
- CSequence *sequence = GetSequence();
- //Load the sequence back in
- sequence->Load(this);
- //If this sequence had a higher GUID than the current, save it
- if ( sequence->GetID() > m_GUID )
- m_GUID = sequence->GetID();
- return true;
- }
- int CIcarus::LoadSequences()
- {
- CSequence *sequence;
- int numSequences;
- //Get the number of sequences to read in
- BufferRead( &numSequences, sizeof( numSequences ) );
- int *idTable = new int[ numSequences ];
- if ( idTable == NULL )
- return false;
- //Load the sequencer ID table
- BufferRead( idTable, sizeof( int ) * numSequences );
- //First pass, allocate all container sequences and give them their proper IDs
- if ( AllocateSequences( numSequences, idTable ) == false )
- return false;
- //Second pass, load all sequences
- for ( int i = 0; i < numSequences; i++ )
- {
- //Get the proper sequence for this load
- if ( ( sequence = GetSequence( idTable[i] ) ) == NULL )
- return false;
- //Load the sequence
- if ( ( sequence->Load(this) ) == false )
- return false;
- }
- //Free the idTable
- delete[] idTable;
- return true;
- }
- int CIcarus::LoadSequencers()
- {
- CSequencer *sequencer;
- int numSequencers;
- IGameInterface* game = IGameInterface::GetGame(m_flavor);
- //Get the number of sequencers to load
- BufferRead( &numSequencers, sizeof( numSequencers ) );
- //Load all sequencers
- for ( int i = 0; i < numSequencers; i++ )
- {
- //NOTENOTE: The ownerID will be replaced in the loading process
- int sequencerID = GetIcarusID(-1);
- if ( ( sequencer = FindSequencer(sequencerID) ) == NULL )
- return false;
- if ( sequencer->Load(this, game) == false )
- return false;
- }
- return true;
- }
- int CIcarus::Load()
- {
- CreateBuffer();
- IGameInterface* game = IGameInterface::GetGame(m_flavor);
- //Clear out any old information
- Free();
- //Check to make sure we're at the ICARUS save block
- double version;
- game->ReadSaveData( 'ICAR', &version, sizeof( version ) );
- //Versions must match!
- if ( version != ICARUS_VERSION )
- {
- DestroyBuffer();
- game->DebugPrint( IGameInterface::WL_ERROR, "save game data contains outdated ICARUS version information!\n");
- return false;
- }
- // Read into the buffer all our data.
- /*m_ulBytesAvailable = */game->ReadSaveData( 'ISEQ', m_byBuffer, 0 ); //fixme, use real buff size
- //Load all signals
- if ( LoadSignals() == false )
- {
- DestroyBuffer();
- game->DebugPrint( IGameInterface::WL_ERROR, "failed to load signals from save game!\n");
- return false;
- }
- //Load in all sequences
- if ( LoadSequences() == false )
- {
- DestroyBuffer();
- game->DebugPrint( IGameInterface::WL_ERROR, "failed to load sequences from save game!\n");
- return false;
- }
- //Load in all sequencers
- if ( LoadSequencers() == false )
- {
- DestroyBuffer();
- game->DebugPrint( IGameInterface::WL_ERROR, "failed to load sequencers from save game!\n");
- return false;
- }
- DestroyBuffer();
- return true;
- }
- int CIcarus::Update(int icarusID)
- {
- CSequencer* sequencer = FindSequencer(icarusID);
- if(sequencer)
- {
- return sequencer->GetTaskManager()->Update(this);
- }
- return -1;
- }
- int CIcarus::IsRunning(int icarusID)
- {
- CSequencer* sequencer = FindSequencer(icarusID);
- if(sequencer)
- {
- return sequencer->GetTaskManager()->IsRunning();
- }
- return false;
- }
- void CIcarus::Completed( int icarusID, int taskID )
- {
- CSequencer* sequencer = FindSequencer(icarusID);
- if(sequencer)
- {
- sequencer->GetTaskManager()->Completed(taskID);
- }
- }
- // Destroy the File Buffer.
- void CIcarus::DestroyBuffer()
- {
- if ( m_byBuffer )
- {
- IGameInterface::GetGame()->Free( m_byBuffer );
- m_byBuffer = NULL;
- }
- }
- // Create the File Buffer.
- void CIcarus::CreateBuffer()
- {
- DestroyBuffer();
- m_byBuffer = (unsigned char *)IGameInterface::GetGame()->Malloc( MAX_BUFFER_SIZE );
- m_ulBufferCurPos = 0;
- }
- // Write to a buffer.
- void CIcarus::BufferWrite( void *pSrcData, unsigned long ulNumBytesToWrite )
- {
- if ( !pSrcData )
- return;
- // Make sure we have enough space in the buffer to write to.
- if ( MAX_BUFFER_SIZE - m_ulBufferCurPos < ulNumBytesToWrite )
- { // Write out the buffer with all our collected data so far...
- IGameInterface::GetGame()->DebugPrint( IGameInterface::WL_ERROR, "BufferWrite: Out of buffer space, Flushing." );
- IGameInterface::GetGame()->WriteSaveData( 'ISEQ', m_byBuffer, m_ulBufferCurPos );
- m_ulBufferCurPos = 0; //reset buffer
- }
-
- assert( MAX_BUFFER_SIZE - m_ulBufferCurPos >= ulNumBytesToWrite );
- {
- memcpy( m_byBuffer + m_ulBufferCurPos, pSrcData, ulNumBytesToWrite );
- m_ulBufferCurPos += ulNumBytesToWrite;
- }
- }
- // Read from a buffer.
- void CIcarus::BufferRead( void *pDstBuff, unsigned long ulNumBytesToRead )
- {
- if ( !pDstBuff )
- return;
- // If we can read this data...
- if ( m_ulBytesRead + ulNumBytesToRead > MAX_BUFFER_SIZE )
- {// We've tried to read past the buffer...
- IGameInterface::GetGame()->DebugPrint( IGameInterface::WL_ERROR, "BufferRead: Buffer underflow, Looking for new block." );
- // Read in the next block.
- /*m_ulBytesAvailable = */IGameInterface::GetGame()->ReadSaveData( 'ISEQ', m_byBuffer, 0 ); //FIXME, to actually check underflows, use real buff size
- m_ulBytesRead = 0; //reset buffer
- }
- assert(m_ulBytesRead + ulNumBytesToRead <= MAX_BUFFER_SIZE);
- {
- memcpy( pDstBuff, m_byBuffer + m_ulBytesRead, ulNumBytesToRead );
- m_ulBytesRead += ulNumBytesToRead;
- }
- }
|