Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

295 lines
7.2 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include <utlbuffer.h>
#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 );
}