//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include #include "tooldemofile.h" #include "filesystem.h" #include "demofile/demoformat.h" extern IBaseFileSystem *g_pFileSystem; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CToolDemoFile::CToolDemoFile() { m_hDemoFile = FILESYSTEM_INVALID_HANDLE; } CToolDemoFile::~CToolDemoFile() { if ( IsOpen() ) { Close(); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CToolDemoFile::ReadSequenceInfo(int &nSeqNrIn, int &nSeqNrOut) { Assert( m_hDemoFile != FILESYSTEM_INVALID_HANDLE ); g_pFileSystem->Read( &nSeqNrIn, sizeof(int), m_hDemoFile ); g_pFileSystem->Read( &nSeqNrOut, sizeof(int), m_hDemoFile ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CToolDemoFile::ReadCmdInfo( democmdinfo_t& info ) { Assert( m_hDemoFile != FILESYSTEM_INVALID_HANDLE ); g_pFileSystem->Read( &info, sizeof( democmdinfo_t ), m_hDemoFile ); } //----------------------------------------------------------------------------- // Purpose: // Input : cmd - // dt - // frame - //----------------------------------------------------------------------------- void CToolDemoFile::ReadCmdHeader( unsigned char& cmd, int& tick ) { Assert( m_hDemoFile != FILESYSTEM_INVALID_HANDLE ); // Read the command int r = g_pFileSystem->Read ( &cmd, sizeof(byte), m_hDemoFile ); if ( r <=0 ) { Warning("Missing end tag in demo file.\n"); cmd = dem_stop; return; } Assert( cmd >= 1 && cmd <= dem_lastcmd ); // Read the timestamp g_pFileSystem->Read ( &tick, sizeof(int), m_hDemoFile ); tick = LittleDWord( tick ); } const char *CToolDemoFile::ReadConsoleCommand() { static char cmdstring[1024]; ReadRawData( cmdstring, sizeof(cmdstring) ); return cmdstring; } unsigned int CToolDemoFile::GetCurPos() { if ( m_hDemoFile == FILESYSTEM_INVALID_HANDLE ) return 0; return g_pFileSystem->Tell( m_hDemoFile ); } //----------------------------------------------------------------------------- // Purpose: // Input : expected_length - // &demofile - //----------------------------------------------------------------------------- int CToolDemoFile::ReadNetworkDataTables( CUtlBuffer *buf ) { Assert( m_hDemoFile != FILESYSTEM_INVALID_HANDLE ); char data[ 1024 ]; int length; g_pFileSystem->Read( &length, sizeof( int ), m_hDemoFile ); while( length > 0 ) { int chunk = min( length, 1024 ); g_pFileSystem->Read( data, chunk, m_hDemoFile ); length -= chunk; if ( buf ) { buf->Put( data, chunk ); } } return length; } //----------------------------------------------------------------------------- // Purpose: // Input : discard - //----------------------------------------------------------------------------- int CToolDemoFile::ReadUserCmd( char *buffer, int &size ) { Assert( m_hDemoFile != FILESYSTEM_INVALID_HANDLE ); int outgoing_sequence; g_pFileSystem->Read( &outgoing_sequence, sizeof( int ), m_hDemoFile ); size = ReadRawData( buffer, size ); return outgoing_sequence; } //----------------------------------------------------------------------------- // Purpose: Rewind from the current spot by the time stamp, byte code and frame counter offsets //----------------------------------------------------------------------------- void CToolDemoFile::SeekTo( int position ) { Assert( m_hDemoFile != FILESYSTEM_INVALID_HANDLE ); g_pFileSystem->Seek( m_hDemoFile, position, FILESYSTEM_SEEK_HEAD ); } //----------------------------------------------------------------------------- // Purpose: // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- int CToolDemoFile::ReadRawData( char *buffer, int length ) { Assert( m_hDemoFile != FILESYSTEM_INVALID_HANDLE ); int size; // read length of data block g_pFileSystem->Read( &size, sizeof( int ), m_hDemoFile ); if ( buffer && (length < size) ) { DevMsg("CToolDemoFile::ReadRawData: buffe overflow (%i).\n", size ); return -1; } if ( buffer ) { if ( length < size ) { // given buffer is too small DevMsg("CToolDemoFile::ReadRawData: buffe overflow (%i).\n", size ); g_pFileSystem->Seek( m_hDemoFile, size, FILESYSTEM_SEEK_CURRENT ); size = -1; } else { // read data into buffer int r = g_pFileSystem->Read( buffer, size, m_hDemoFile ); if ( r != size ) { Warning( "Error reading demo message data.\n"); return -1; } } } else { // just skip it g_pFileSystem->Seek( m_hDemoFile, size, FILESYSTEM_SEEK_CURRENT ); } return size; } demoheader_t *CToolDemoFile::ReadDemoHeader() { if ( m_hDemoFile == FILESYSTEM_INVALID_HANDLE ) return NULL; // file not open // goto file start g_pFileSystem->Seek(m_hDemoFile, 0, FILESYSTEM_SEEK_HEAD); Q_memset( &m_DemoHeader, 0, sizeof(m_DemoHeader) ); int r = g_pFileSystem->Read( &m_DemoHeader, sizeof(demoheader_t), m_hDemoFile ); if ( r != sizeof(demoheader_t) ) return NULL; // reading failed if ( Q_strcmp ( m_DemoHeader.demofilestamp, DEMO_HEADER_ID ) ) { Warning( "%s has invalid demo header ID.\n", m_szFileName ); return NULL; } /* // The current network protocol version. Changing this makes clients and servers incompatible #define PROTOCOL_VERSION 7 if ( m_DemoHeader.networkprotocol != PROTOCOL_VERSION ) { Warning ("ERROR: demo network protocol %i outdated, engine version is %i \n", m_DemoHeader.networkprotocol, PROTOCOL_VERSION ); return NULL; } */ if ( m_DemoHeader.demoprotocol != DEMO_PROTOCOL ) { Warning ("ERROR: demo file protocol %i outdated, engine version is %i \n", m_DemoHeader.demoprotocol, DEMO_PROTOCOL ); return NULL; } return &m_DemoHeader; } bool CToolDemoFile::Open(const char *name, bool bReadOnly) { if ( m_hDemoFile != FILESYSTEM_INVALID_HANDLE ) { Warning ("CToolDemoFile::Open: file already open.\n"); return false; } m_szFileName[0] = 0; // clear name Q_memset( &m_DemoHeader, 0, sizeof(m_DemoHeader) ); // and demo header if ( bReadOnly ) { // open existing file for reading only m_hDemoFile = g_pFileSystem->Open (name, "rb", "GAME" ); } else { // create new file for writing only m_hDemoFile = g_pFileSystem->Open (name, "wb", "GAME" ); } if ( m_hDemoFile == FILESYSTEM_INVALID_HANDLE ) { Warning ("CToolDemoFile::Open: couldn't open file %s for %s.\n", name, bReadOnly?"reading":"writing" ); return false; } Q_strncpy( m_szFileName, name, sizeof(m_szFileName) ); return true; } bool CToolDemoFile::IsOpen() { return m_hDemoFile != FILESYSTEM_INVALID_HANDLE; } void CToolDemoFile::Close() { if ( m_hDemoFile != FILESYSTEM_INVALID_HANDLE ) { g_pFileSystem->Close(m_hDemoFile); m_hDemoFile = FILESYSTEM_INVALID_HANDLE; } } int CToolDemoFile::GetSize() { return g_pFileSystem->Size( m_hDemoFile ); }