summaryrefslogtreecommitdiff
path: root/utils/demoinfo/demoinfo.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/demoinfo/demoinfo.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/demoinfo/demoinfo.cpp')
-rw-r--r--utils/demoinfo/demoinfo.cpp527
1 files changed, 527 insertions, 0 deletions
diff --git a/utils/demoinfo/demoinfo.cpp b/utils/demoinfo/demoinfo.cpp
new file mode 100644
index 0000000..85d740e
--- /dev/null
+++ b/utils/demoinfo/demoinfo.cpp
@@ -0,0 +1,527 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: A simple application demonstrating the HL2 demo file format ( subject to change!!! )
+//
+// $NoKeywords: $
+//=============================================================================//
+#include <windows.h>
+#include "tier0/dbg.h"
+#include "filesystem.h"
+#include "FileSystem_Tools.h"
+#include "cmdlib.h"
+#include "tooldemofile.h"
+
+static bool uselogfile = false;
+static bool spewed = false;
+
+#define LOGFILE_NAME "log.txt"
+
+#define COM_COPY_CHUNK_SIZE 8192
+
+//-----------------------------------------------------------------------------
+// Purpose: Prints to stdout and to the developer console and optionally to a log file
+// Input : depth -
+// *fmt -
+// ... -
+//-----------------------------------------------------------------------------
+void vprint( int depth, const char *fmt, ... )
+{
+ char string[ 8192 ];
+ va_list va;
+ va_start( va, fmt );
+ vsprintf( string, fmt, va );
+ va_end( va );
+
+ FILE *fp = NULL;
+
+ if ( uselogfile )
+ {
+ fp = fopen( LOGFILE_NAME, "ab" );
+ }
+
+ while ( depth-- > 0 )
+ {
+ printf( " " );
+ OutputDebugString( " " );
+ if ( fp )
+ {
+ fprintf( fp, " " );
+ }
+ }
+
+ ::printf( "%s", string );
+ OutputDebugString( string );
+
+ if ( fp )
+ {
+ char *p = string;
+ while ( *p )
+ {
+ if ( *p == '\n' )
+ {
+ fputc( '\r', fp );
+ }
+ fputc( *p, fp );
+ p++;
+ }
+ fclose( fp );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Warning/Msg call back through this API
+// Input : type -
+// *pMsg -
+// Output : SpewRetval_t
+//-----------------------------------------------------------------------------
+SpewRetval_t SpewFunc( SpewType_t type, char const *pMsg )
+{
+ spewed = true;
+
+ switch ( type )
+ {
+
+ default:
+ case SPEW_MESSAGE:
+ case SPEW_ASSERT:
+ case SPEW_LOG:
+ vprint( 0, "%s", pMsg );
+ break;
+ case SPEW_WARNING:
+
+ if ( verbose )
+ {
+ vprint( 0, "%s", pMsg );
+ }
+ break;
+ case SPEW_ERROR:
+ vprint( 0, "%s\n", pMsg );
+ break;
+ }
+
+ return SPEW_CONTINUE;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Shows usage information
+//-----------------------------------------------------------------------------
+void printusage( void )
+{
+ vprint( 0, "usage: demoinfo <.dem file>\n\
+ \t-v = verbose output\n\
+ \t-l = log to file log.txt\n\
+ \ne.g.: demoinfo -v u:/hl2/hl2/foo.dem\n" );
+
+ // Exit app
+ exit( 1 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Removes previous log file
+//-----------------------------------------------------------------------------
+void CheckLogFile( void )
+{
+ if ( uselogfile )
+ {
+ _unlink( LOGFILE_NAME );
+ vprint( 0, " Outputting to log.txt\n" );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Prints banner
+//-----------------------------------------------------------------------------
+void PrintHeader()
+{
+ vprint( 0, "Valve Software - demoinfo.exe (%s)\n", __DATE__ );
+ vprint( 0, "--- Demo File Info Sample ---\n" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Parses all "smoothing" info from .dem file
+// Input : &demoFile -
+// smooth -
+//-----------------------------------------------------------------------------
+void ParseSmoothingInfo( CToolDemoFile &demoFile, CUtlVector< demosmoothing_t >& smooth )
+{
+ democmdinfo_t info;
+ int dummy;
+
+ bool demofinished = false;
+ while ( !demofinished )
+ {
+ int tick = 0;
+ byte cmd;
+
+ bool swallowmessages = true;
+ do
+ {
+ demoFile.ReadCmdHeader( cmd, tick );
+
+ // COMMAND HANDLERS
+ switch ( cmd )
+ {
+ case dem_synctick:
+ break;
+ case dem_stop:
+ {
+ swallowmessages = false;
+ demofinished = true;
+ }
+ break;
+ case dem_consolecmd:
+ {
+ demoFile.ReadConsoleCommand();
+ }
+ break;
+ case dem_datatables:
+ {
+ demoFile.ReadNetworkDataTables( NULL );
+ }
+ break;
+ case dem_usercmd:
+ {
+ demoFile.ReadUserCmd( NULL, dummy );
+
+ }
+ break;
+ default:
+ {
+ swallowmessages = false;
+ }
+ break;
+ }
+ }
+ while ( swallowmessages );
+
+ if ( demofinished )
+ {
+ // StopPlayback();
+ return;
+ }
+
+ int curpos = demoFile.GetCurPos();
+
+ demoFile.ReadCmdInfo( info );
+ demoFile.ReadSequenceInfo( dummy, dummy );
+ demoFile.ReadRawData( NULL, 0 );
+
+ demosmoothing_t smoothing_entry;
+
+ smoothing_entry.file_offset = curpos;
+ smoothing_entry.frametick = tick;
+ smoothing_entry.info = info;
+ smoothing_entry.samplepoint = false;
+ smoothing_entry.vecmoved = info.GetViewOrigin();
+ smoothing_entry.angmoved = info.GetViewAngles();
+ smoothing_entry.targetpoint = false;
+ smoothing_entry.vectarget = info.GetViewOrigin();
+
+ // Add to end of list
+
+ smooth.AddToTail( smoothing_entry );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Resets all smoothing data back to original values
+// Input : smoothing -
+//-----------------------------------------------------------------------------
+void ClearSmoothingInfo( CSmoothingContext& smoothing )
+{
+ int c = smoothing.smooth.Count();
+ int i;
+
+ for ( i = 0; i < c; i++ )
+ {
+ demosmoothing_t *p = &smoothing.smooth[ i ];
+ p->info.Reset();
+ p->vecmoved = p->info.GetViewOrigin();
+ p->angmoved = p->info.GetViewAngles();
+ p->samplepoint = false;
+ p->vectarget = p->info.GetViewOrigin();
+ p->targetpoint = false;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Helper for copying sub-chunk of file
+// Input : dst -
+// src -
+// nSize -
+//-----------------------------------------------------------------------------
+void COM_CopyFileChunk( FileHandle_t dst, FileHandle_t src, int nSize )
+{
+ int copysize = nSize;
+ char copybuf[COM_COPY_CHUNK_SIZE];
+
+ while (copysize > COM_COPY_CHUNK_SIZE)
+ {
+ g_pFileSystem->Read ( copybuf, COM_COPY_CHUNK_SIZE, src );
+ g_pFileSystem->Write( copybuf, COM_COPY_CHUNK_SIZE, dst );
+ copysize -= COM_COPY_CHUNK_SIZE;
+ }
+
+ g_pFileSystem->Read ( copybuf, copysize, src );
+ g_pFileSystem->Write( copybuf, copysize, dst );
+
+ g_pFileSystem->Flush ( src );
+ g_pFileSystem->Flush ( dst );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Writes out a new .dem file based on the existing dem file with new camera positions saved into the dem file
+// Note: The new file is named filename_smooth.dem
+// Input : *filename -
+// smoothing -
+//-----------------------------------------------------------------------------
+void SaveSmoothingInfo( char const *filename, CSmoothingContext& smoothing )
+{
+ // Nothing to do
+ int c = smoothing.smooth.Count();
+ if ( !c )
+ return;
+
+ IBaseFileSystem *fs = g_pFileSystem;
+
+ FileHandle_t infile, outfile;
+
+ infile = fs->Open( filename, "rb", "GAME" );
+ if ( infile == FILESYSTEM_INVALID_HANDLE )
+ return;
+
+ int filesize = fs->Size( infile );
+
+ char outfilename[ 512 ];
+ Q_StripExtension( filename, outfilename, sizeof( outfilename ) );
+ Q_strncat( outfilename, "_smooth", sizeof(outfilename), COPY_ALL_CHARACTERS );
+ Q_DefaultExtension( outfilename, ".dem", sizeof( outfilename ) );
+ outfile = fs->Open( outfilename, "wb", "GAME" );
+ if ( outfile == FILESYSTEM_INVALID_HANDLE )
+ {
+ fs->Close( infile );
+ return;
+ }
+
+ int i;
+
+ // The basic algorithm is to seek to each sample and "overwrite" it during copy with the new data...
+ int lastwritepos = 0;
+ for ( i = 0; i < c; i++ )
+ {
+ demosmoothing_t *p = &smoothing.smooth[ i ];
+
+ int copyamount = p->file_offset - lastwritepos;
+
+ COM_CopyFileChunk( outfile, infile, copyamount );
+
+ fs->Seek( infile, p->file_offset, FILESYSTEM_SEEK_HEAD );
+
+ // wacky hacky overwriting
+ fs->Write( &p->info, sizeof( democmdinfo_t ), outfile );
+
+ lastwritepos = fs->Tell( outfile );
+ fs->Seek( infile, p->file_offset + sizeof( democmdinfo_t ), FILESYSTEM_SEEK_HEAD );
+ }
+
+ // Copy the final bit of data, if any...
+ int final = filesize - lastwritepos;
+
+ COM_CopyFileChunk( outfile, infile, final );
+
+ fs->Close( outfile );
+ fs->Close( infile );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Helper for spewing verbose sample information
+// Input : flags -
+// Output : char const
+//-----------------------------------------------------------------------------
+char const *DescribeFlags( int flags )
+{
+ static char outbuf[ 256 ];
+
+ outbuf[ 0 ] = 0;
+
+ if ( flags & FDEMO_USE_ORIGIN2 )
+ {
+ Q_strncat( outbuf, "USE_ORIGIN2, ", sizeof( outbuf ), COPY_ALL_CHARACTERS );
+ }
+ if ( flags & FDEMO_USE_ANGLES2 )
+ {
+ Q_strncat( outbuf, "USE_ANGLES2, ", sizeof( outbuf ), COPY_ALL_CHARACTERS );
+ }
+ if ( flags & FDEMO_NOINTERP )
+ {
+ Q_strncat( outbuf, "NOINTERP, ", sizeof( outbuf ), COPY_ALL_CHARACTERS );
+ }
+
+ int len = Q_strlen( outbuf );
+ if ( len > 2 )
+ {
+ outbuf[ len - 2 ] = 0;
+ }
+ else
+ {
+ Q_strncpy( outbuf, "N/A", sizeof( outbuf ) );
+ }
+ return outbuf;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Loads up all camera samples from a .dem file into the passed in context.
+// Input : *filename -
+// smoothing -
+//-----------------------------------------------------------------------------
+void LoadSmoothingInfo( const char *filename, CSmoothingContext& smoothing )
+{
+ char name[ MAX_OSPATH ];
+ Q_strncpy (name, filename, sizeof(name) );
+ Q_DefaultExtension( name, ".dem", sizeof( name ) );
+
+ CToolDemoFile demoFile;
+
+ if ( !demoFile.Open( filename, true ) )
+ {
+ Warning( "ERROR: couldn't open %s.\n", name );
+ return;
+ }
+
+ demoheader_t * header = demoFile.ReadDemoHeader();
+
+ if ( !header )
+ {
+ demoFile.Close();
+ return;
+ }
+
+ Msg( "\n\n" );
+ Msg( "--------------------------------------------------------------\n" );
+ Msg( "demofilestamp: '%s'\n", header->demofilestamp );
+ Msg( "demoprotocol: %i\n", header->demoprotocol );
+ Msg( "networkprotocol: %i\n", header->networkprotocol );
+ Msg( "servername: '%s'\n", header->servername );
+ Msg( "clientname: '%s'\n", header->clientname );
+ Msg( "mapname: '%s'\n", header->mapname );
+ Msg( "gamedirectory: '%s'\n", header->gamedirectory );
+ Msg( "playback_time: %f seconds\n", header->playback_time );
+ Msg( "playback_ticks: %i ticks\n", header->playback_ticks );
+ Msg( "playback_frames: %i frames\n", header->playback_frames );
+ Msg( "signonlength: %s\n", Q_pretifymem( header->signonlength ) );
+
+ smoothing.active = true;
+ Q_strncpy( smoothing.filename, name, sizeof(smoothing.filename) );
+
+ smoothing.smooth.RemoveAll();
+
+ ClearSmoothingInfo( smoothing );
+
+ ParseSmoothingInfo( demoFile, smoothing.smooth );
+
+ Msg( "--------------------------------------------------------------\n" );
+ Msg( "smoothing data: %i samples\n", smoothing.smooth.Count() );
+
+ if ( verbose )
+ {
+ int c = smoothing.smooth.Count();
+ for ( int i = 0; i < c; ++i )
+ {
+ demosmoothing_t& sample = smoothing.smooth[ i ];
+
+ Msg( "Sample %i:\n", i );
+ Msg( " file pos: %i\n", sample.file_offset );
+ Msg( " tick: %i\n", sample.frametick );
+ Msg( " flags: %s\n", DescribeFlags( sample.info.flags ) );
+
+ Msg( " Original Data:\n" );
+ Msg( " origin: %.4f %.4f %.4f\n", sample.info.viewOrigin.x, sample.info.viewOrigin.y, sample.info.viewOrigin.z );
+ Msg( " viewangles: %.4f %.4f %.4f\n", sample.info.viewAngles.x, sample.info.viewAngles.y, sample.info.viewAngles.z );
+ Msg( " localviewangles: %.4f %.4f %.4f\n", sample.info.localViewAngles.x, sample.info.localViewAngles.y, sample.info.localViewAngles.z );
+
+ Msg( " Resampled Data:\n" );
+ Msg( " origin: %.4f %.4f %.4f\n", sample.info.viewOrigin2.x, sample.info.viewOrigin2.y, sample.info.viewOrigin2.z );
+ Msg( " viewangles: %.4f %.4f %.4f\n", sample.info.viewAngles2.x, sample.info.viewAngles2.y, sample.info.viewAngles2.z );
+ Msg( " localviewangles: %.4f %.4f %.4f\n", sample.info.localViewAngles2.x, sample.info.localViewAngles2.y, sample.info.localViewAngles2.z );
+
+ Msg( "\n" );
+
+ }
+ }
+
+ demoFile.Close();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : argc -
+// argv[] -
+// Output : int
+//-----------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+ SpewOutputFunc( SpewFunc );
+ SpewActivate( "demoinfo", 2 );
+
+ int i = 1;
+ for ( i ; i<argc ; i++)
+ {
+ if ( argv[ i ][ 0 ] == '-' )
+ {
+ switch( argv[ i ][ 1 ] )
+ {
+ case 'l':
+ uselogfile = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'g':
+ ++i;
+ break;
+ default:
+ printusage();
+ break;
+ }
+ }
+ }
+
+ if ( argc < 2 || ( i != argc ) )
+ {
+ PrintHeader();
+ printusage();
+ }
+
+ CheckLogFile();
+
+ PrintHeader();
+
+ vprint( 0, " Info for %s..\n", argv[ i - 1 ] );
+
+ char workingdir[ 256 ];
+ workingdir[0] = 0;
+ Q_getwd( workingdir, sizeof( workingdir ) );
+
+ if ( !FileSystem_Init( NULL, 0, FS_INIT_FULL ) )
+ return 1;
+
+ // Add this so relative filenames work.
+ g_pFullFileSystem->AddSearchPath( workingdir, "game", PATH_ADD_TO_HEAD );
+
+ // Load the demo
+ CSmoothingContext context;
+
+ LoadSmoothingInfo( argv[ i - 1 ], context );
+
+ // Note to tool makers:
+ // Do your work here!!!
+ //Performsmoothing( context );
+
+ // Save out updated .dem file
+ // UNCOMMENT THIS TO ENABLE OUTPUTTING NEW .DEM FILES!!!
+ // SaveSmoothingInfo( argv[ i - 1 ], context );
+
+ FileSystem_Term();
+
+ return 0;
+}