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.
661 lines
14 KiB
661 lines
14 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
// vcrtrace.cpp : Defines the entry point for the console application. |
|
// |
|
|
|
#include "stdafx.h" |
|
#include <time.h> |
|
#include "tier0/vcrmode.h" |
|
#include "tier1/utlvector.h" |
|
|
|
|
|
|
|
IVCRTrace *g_pTrace = 0; |
|
|
|
|
|
class CVCRHelpers : public IVCRHelpers |
|
{ |
|
public: |
|
virtual void ErrorMessage( const char *pMsg ) |
|
{ |
|
Msg("ERROR: %s\n", pMsg); |
|
} |
|
|
|
virtual void* GetMainWindow() |
|
{ |
|
return 0; |
|
} |
|
}; |
|
|
|
static CVCRHelpers g_VCRHelpers; |
|
|
|
|
|
void ErrFunction( char const *pMsg ) |
|
{ |
|
Msg( "%s", pMsg ); |
|
} |
|
|
|
|
|
typedef struct |
|
{ |
|
int m_Message; |
|
char const *m_pName; |
|
} WMessage; |
|
#define DEFINE_WMESSAGE(x) x, #x |
|
|
|
|
|
// Message table for windows messages. |
|
WMessage g_WMessages[] = |
|
{ |
|
DEFINE_WMESSAGE(WM_NOTIFY), |
|
DEFINE_WMESSAGE(WM_INPUTLANGCHANGEREQUEST), |
|
DEFINE_WMESSAGE(WM_INPUTLANGCHANGE), |
|
DEFINE_WMESSAGE(WM_TCARD), |
|
DEFINE_WMESSAGE(WM_HELP), |
|
DEFINE_WMESSAGE(WM_USERCHANGED), |
|
DEFINE_WMESSAGE(WM_NOTIFYFORMAT), |
|
DEFINE_WMESSAGE(NFR_ANSI), |
|
DEFINE_WMESSAGE(NFR_UNICODE), |
|
DEFINE_WMESSAGE(NF_QUERY), |
|
DEFINE_WMESSAGE(NF_REQUERY), |
|
DEFINE_WMESSAGE(WM_CONTEXTMENU), |
|
DEFINE_WMESSAGE(WM_STYLECHANGING), |
|
DEFINE_WMESSAGE(WM_STYLECHANGED), |
|
DEFINE_WMESSAGE(WM_DISPLAYCHANGE), |
|
DEFINE_WMESSAGE(WM_GETICON), |
|
DEFINE_WMESSAGE(WM_SETICON), |
|
DEFINE_WMESSAGE(WM_NCCREATE), |
|
DEFINE_WMESSAGE(WM_NCDESTROY), |
|
DEFINE_WMESSAGE(WM_NCCALCSIZE), |
|
DEFINE_WMESSAGE(WM_NCHITTEST), |
|
DEFINE_WMESSAGE(WM_NCPAINT), |
|
DEFINE_WMESSAGE(WM_NCACTIVATE), |
|
DEFINE_WMESSAGE(WM_GETDLGCODE), |
|
DEFINE_WMESSAGE(WM_SYNCPAINT), |
|
DEFINE_WMESSAGE(WM_NCMOUSEMOVE), |
|
DEFINE_WMESSAGE(WM_NCLBUTTONDOWN), |
|
DEFINE_WMESSAGE(WM_NCLBUTTONUP), |
|
DEFINE_WMESSAGE(WM_NCLBUTTONDBLCLK), |
|
DEFINE_WMESSAGE(WM_NCRBUTTONDOWN), |
|
DEFINE_WMESSAGE(WM_NCRBUTTONUP), |
|
DEFINE_WMESSAGE(WM_NCRBUTTONDBLCLK), |
|
DEFINE_WMESSAGE(WM_NCMBUTTONDOWN), |
|
DEFINE_WMESSAGE(WM_NCMBUTTONUP), |
|
DEFINE_WMESSAGE(WM_NCMBUTTONDBLCLK), |
|
DEFINE_WMESSAGE(WM_KEYFIRST), |
|
DEFINE_WMESSAGE(WM_KEYDOWN), |
|
DEFINE_WMESSAGE(WM_KEYUP), |
|
DEFINE_WMESSAGE(WM_CHAR), |
|
DEFINE_WMESSAGE(WM_DEADCHAR), |
|
DEFINE_WMESSAGE(WM_SYSKEYDOWN), |
|
DEFINE_WMESSAGE(WM_SYSKEYUP), |
|
DEFINE_WMESSAGE(WM_SYSCHAR), |
|
DEFINE_WMESSAGE(WM_SYSDEADCHAR), |
|
DEFINE_WMESSAGE(WM_KEYLAST), |
|
DEFINE_WMESSAGE(WM_IME_STARTCOMPOSITION), |
|
DEFINE_WMESSAGE(WM_IME_ENDCOMPOSITION), |
|
DEFINE_WMESSAGE(WM_IME_COMPOSITION), |
|
DEFINE_WMESSAGE(WM_IME_KEYLAST), |
|
DEFINE_WMESSAGE(WM_INITDIALOG), |
|
DEFINE_WMESSAGE(WM_COMMAND), |
|
DEFINE_WMESSAGE(WM_SYSCOMMAND), |
|
DEFINE_WMESSAGE(WM_TIMER), |
|
DEFINE_WMESSAGE(WM_HSCROLL), |
|
DEFINE_WMESSAGE(WM_VSCROLL), |
|
DEFINE_WMESSAGE(WM_INITMENU), |
|
DEFINE_WMESSAGE(WM_INITMENUPOPUP), |
|
DEFINE_WMESSAGE(WM_MENUSELECT), |
|
DEFINE_WMESSAGE(WM_MENUCHAR), |
|
DEFINE_WMESSAGE(WM_ENTERIDLE), |
|
DEFINE_WMESSAGE(WM_CTLCOLORMSGBOX), |
|
DEFINE_WMESSAGE(WM_CTLCOLOREDIT), |
|
DEFINE_WMESSAGE(WM_CTLCOLORLISTBOX), |
|
DEFINE_WMESSAGE(WM_CTLCOLORBTN), |
|
DEFINE_WMESSAGE(WM_CTLCOLORDLG), |
|
DEFINE_WMESSAGE(WM_CTLCOLORSCROLLBAR), |
|
DEFINE_WMESSAGE(WM_CTLCOLORSTATIC), |
|
DEFINE_WMESSAGE(WM_MOUSEMOVE), |
|
DEFINE_WMESSAGE(WM_LBUTTONDOWN), |
|
DEFINE_WMESSAGE(WM_LBUTTONUP), |
|
DEFINE_WMESSAGE(WM_LBUTTONDBLCLK), |
|
DEFINE_WMESSAGE(WM_RBUTTONDOWN), |
|
DEFINE_WMESSAGE(WM_RBUTTONUP), |
|
DEFINE_WMESSAGE(WM_RBUTTONDBLCLK), |
|
DEFINE_WMESSAGE(WM_MBUTTONDOWN), |
|
DEFINE_WMESSAGE(WM_MBUTTONUP), |
|
DEFINE_WMESSAGE(WM_MBUTTONDBLCLK), |
|
DEFINE_WMESSAGE(WM_MOUSELAST), |
|
DEFINE_WMESSAGE(WM_PARENTNOTIFY), |
|
DEFINE_WMESSAGE(WM_ENTERMENULOOP), |
|
DEFINE_WMESSAGE(WM_EXITMENULOOP ) |
|
}; |
|
|
|
// Message table for winsock messages. |
|
WMessage g_WinsockMessages[] = |
|
{ |
|
DEFINE_WMESSAGE(WSAEWOULDBLOCK), |
|
DEFINE_WMESSAGE(WSAEINPROGRESS), |
|
DEFINE_WMESSAGE(WSAEALREADY), |
|
DEFINE_WMESSAGE(WSAENOTSOCK), |
|
DEFINE_WMESSAGE(WSAEDESTADDRREQ), |
|
DEFINE_WMESSAGE(WSAEMSGSIZE), |
|
DEFINE_WMESSAGE(WSAEPROTOTYPE), |
|
DEFINE_WMESSAGE(WSAENOPROTOOPT), |
|
DEFINE_WMESSAGE(WSAEPROTONOSUPPORT), |
|
DEFINE_WMESSAGE(WSAESOCKTNOSUPPORT), |
|
DEFINE_WMESSAGE(WSAEOPNOTSUPP), |
|
DEFINE_WMESSAGE(WSAEPFNOSUPPORT), |
|
DEFINE_WMESSAGE(WSAEAFNOSUPPORT), |
|
DEFINE_WMESSAGE(WSAEADDRINUSE), |
|
DEFINE_WMESSAGE(WSAEADDRNOTAVAIL), |
|
DEFINE_WMESSAGE(WSAENETDOWN), |
|
DEFINE_WMESSAGE(WSAENETUNREACH), |
|
DEFINE_WMESSAGE(WSAENETRESET), |
|
DEFINE_WMESSAGE(WSAECONNABORTED), |
|
DEFINE_WMESSAGE(WSAECONNRESET), |
|
DEFINE_WMESSAGE(WSAENOBUFS), |
|
DEFINE_WMESSAGE(WSAEISCONN), |
|
DEFINE_WMESSAGE(WSAENOTCONN), |
|
DEFINE_WMESSAGE(WSAESHUTDOWN), |
|
DEFINE_WMESSAGE(WSAETOOMANYREFS), |
|
DEFINE_WMESSAGE(WSAETIMEDOUT), |
|
DEFINE_WMESSAGE(WSAECONNREFUSED), |
|
DEFINE_WMESSAGE(WSAELOOP), |
|
DEFINE_WMESSAGE(WSAENAMETOOLONG), |
|
DEFINE_WMESSAGE(WSAEHOSTDOWN), |
|
DEFINE_WMESSAGE(WSAEHOSTUNREACH), |
|
DEFINE_WMESSAGE(WSAENOTEMPTY), |
|
DEFINE_WMESSAGE(WSAEPROCLIM), |
|
DEFINE_WMESSAGE(WSAEUSERS), |
|
DEFINE_WMESSAGE(WSAEDQUOT), |
|
DEFINE_WMESSAGE(WSAESTALE), |
|
DEFINE_WMESSAGE(WSAEREMOTE), |
|
DEFINE_WMESSAGE(WSAEDISCON), |
|
DEFINE_WMESSAGE(WSASYSNOTREADY), |
|
DEFINE_WMESSAGE(WSAVERNOTSUPPORTED), |
|
DEFINE_WMESSAGE(WSANOTINITIALISED) |
|
}; |
|
|
|
|
|
static char const* GetWMessageName(WMessage *pMessages, int nMessages, int msg) |
|
{ |
|
static char str[128]; |
|
int i; |
|
|
|
for(i=0; i < nMessages; i++) |
|
{ |
|
if(pMessages[i].m_Message == msg) |
|
return pMessages[i].m_pName; |
|
} |
|
|
|
sprintf(str, "%d", msg); |
|
return str; |
|
} |
|
|
|
FILE *g_fpTrace = NULL; |
|
bool g_bEndOfFile = false; |
|
|
|
template<class T> |
|
static void VCRTrace_ReadVal(T &val) |
|
{ |
|
if ( fread( &val, 1, sizeof( val ), g_fpTrace ) != sizeof( val ) ) |
|
g_bEndOfFile = true; |
|
} |
|
|
|
static void VCRTrace_Read( void *pOut, int size ) |
|
{ |
|
if ( fread( pOut, 1, size, g_fpTrace ) != (size_t)size ) |
|
g_bEndOfFile = true; |
|
} |
|
|
|
void ReadAndPrintShortString( const char *pFormat ) |
|
{ |
|
unsigned short len; |
|
VCRTrace_ReadVal( len ); |
|
|
|
static CUtlVector<char> tempData; |
|
if ( tempData.Count() < len ) |
|
tempData.SetSize( len ); |
|
|
|
VCRTrace_Read( tempData.Base(), len ); |
|
if ( len > 0 && ( tempData[len-2] == '\n' || tempData[len-2] == '\r' ) ) |
|
tempData[len-2] = 0; |
|
|
|
Msg( pFormat, tempData.Base() ); |
|
} |
|
|
|
static void VCR_TraceEvents() |
|
{ |
|
int iEvent = 0; |
|
|
|
g_pTrace = g_pVCR->GetVCRTraceInterface(); |
|
|
|
while ( !g_bEndOfFile ) |
|
{ |
|
++iEvent; |
|
|
|
unsigned char eventCode; |
|
VCRTrace_Read( &eventCode, sizeof( eventCode ) ); |
|
|
|
unsigned short iThread = 0; |
|
if ( eventCode & 0x80 ) |
|
{ |
|
VCRTrace_Read( &iThread, sizeof( iThread ) ); |
|
eventCode &= ~0x80; |
|
} |
|
|
|
Msg( "%5d (thread %d): ", iEvent, iThread ); |
|
|
|
VCREvent event = (VCREvent)eventCode; |
|
switch(event) |
|
{ |
|
case VCREvent_Sys_FloatTime: |
|
{ |
|
double ret; |
|
VCRTrace_Read(&ret, sizeof(ret)); |
|
Msg("Sys_FloatTime: %f\n", ret); |
|
} |
|
break; |
|
|
|
case VCREvent_recvfrom: |
|
{ |
|
int ret; |
|
char buf[8192]; |
|
|
|
VCRTrace_Read(&ret, sizeof(ret)); |
|
|
|
Assert(ret < (int)sizeof(buf)); |
|
if(ret == SOCKET_ERROR) |
|
{ |
|
int err; |
|
VCRTrace_ReadVal(err); |
|
|
|
Msg("recvfrom: %d (error %s)\n", ret, GetWMessageName(g_WinsockMessages, sizeof(g_WinsockMessages)/sizeof(g_WinsockMessages[0]), err)); |
|
} |
|
else |
|
{ |
|
Msg("recvfrom: %d\n", ret); |
|
VCRTrace_Read(buf, ret); |
|
|
|
char bFrom; |
|
VCRTrace_ReadVal( bFrom ); |
|
if ( bFrom ) |
|
{ |
|
sockaddr_in from; |
|
VCRTrace_Read( &from, sizeof( from ) ); |
|
} |
|
} |
|
} |
|
break; |
|
|
|
case VCREvent_SyncToken: |
|
{ |
|
char len; |
|
char buf[256]; |
|
|
|
VCRTrace_Read(&len, 1); |
|
VCRTrace_Read(buf, len); |
|
buf[len] = 0; |
|
|
|
Msg("SyncToken: %s\n", buf); |
|
} |
|
break; |
|
|
|
case VCREvent_GetCursorPos: |
|
{ |
|
POINT pt; |
|
VCRTrace_ReadVal(pt); |
|
Msg("GetCursorPos: (%d, %d)\n", pt.x, pt.y); |
|
} |
|
break; |
|
|
|
case VCREvent_SetCursorPos: |
|
{ |
|
int x, y; |
|
VCRTrace_Read(&x, sizeof(x)); |
|
VCRTrace_Read(&y, sizeof(y)); |
|
Msg("SetCursorPos: (%d, %d)\n", x, y); |
|
} |
|
break; |
|
|
|
case VCREvent_ScreenToClient: |
|
{ |
|
POINT pt; |
|
VCRTrace_ReadVal(pt); |
|
Msg("ScreenToClient: (%d, %d)\n", pt.x, pt.y); |
|
} |
|
break; |
|
|
|
case VCREvent_Cmd_Exec: |
|
{ |
|
int len; |
|
char *f; |
|
|
|
VCRTrace_Read(&len, sizeof(len)); |
|
|
|
if(len != -1) |
|
{ |
|
f = (char*)malloc(len); |
|
VCRTrace_Read(f, len); |
|
} |
|
|
|
Msg("Cmd_Exec: %d\n", len); |
|
} |
|
break; |
|
|
|
case VCREvent_CmdLine: |
|
{ |
|
int len; |
|
char str[8192]; |
|
|
|
VCRTrace_Read(&len, sizeof(len)); |
|
Assert(len < sizeof(str)); |
|
VCRTrace_Read(str, len); |
|
|
|
Msg("CmdLine: %s\n", str); |
|
} |
|
break; |
|
|
|
case VCREvent_RegOpenKeyEx: |
|
{ |
|
long ret; |
|
VCRTrace_ReadVal(ret); |
|
Msg("RegOpenKeyEx: %d\n", ret); |
|
} |
|
break; |
|
|
|
case VCREvent_RegSetValueEx: |
|
{ |
|
long ret; |
|
VCRTrace_ReadVal(ret); |
|
Msg("RegSetValueEx: %d\n", ret); |
|
} |
|
break; |
|
|
|
case VCREvent_RegQueryValueEx: |
|
{ |
|
long ret; |
|
unsigned long type, cbData; |
|
char dummy; |
|
|
|
VCRTrace_ReadVal(ret); |
|
VCRTrace_ReadVal(type); |
|
VCRTrace_ReadVal(cbData); |
|
while(cbData) |
|
{ |
|
VCRTrace_ReadVal(dummy); |
|
cbData--; |
|
} |
|
|
|
Msg("RegQueryValueEx\n"); |
|
} |
|
break; |
|
|
|
case VCREvent_RegCreateKeyEx: |
|
{ |
|
long ret; |
|
VCRTrace_ReadVal(ret); |
|
Msg("RegCreateKeyEx: %d\n", ret); |
|
} |
|
break; |
|
|
|
case VCREvent_RegCloseKey: |
|
{ |
|
Msg("VCREvent_RegCloseKey\n"); |
|
} |
|
break; |
|
|
|
case VCREvent_PeekMessage: |
|
{ |
|
MSG msg; |
|
int valid; |
|
|
|
VCRTrace_Read(&valid, sizeof(valid)); |
|
if(valid) |
|
{ |
|
VCRTrace_Read(&msg, sizeof(MSG)); |
|
} |
|
|
|
Msg("PeekMessage - msg: %s, wParam: %x, lParam: %x\n", GetWMessageName(g_WMessages, sizeof(g_WMessages)/sizeof(g_WMessages[0]), msg.message), msg.wParam, msg.lParam); |
|
} |
|
break; |
|
|
|
case VCREvent_GameMsg: |
|
{ |
|
char valid; |
|
VCRTrace_Read( &valid, sizeof(valid) ); |
|
|
|
if ( valid ) |
|
{ |
|
UINT uMsg; |
|
WPARAM wParam; |
|
LPARAM lParam; |
|
VCRTrace_Read( &uMsg, sizeof(uMsg) ); |
|
VCRTrace_Read( &wParam, sizeof(wParam) ); |
|
VCRTrace_Read( &lParam, sizeof(lParam) ); |
|
Msg( "GameMsg - msg: %s, wParam: %x, lParam: %x\n", GetWMessageName(g_WMessages, sizeof(g_WMessages)/sizeof(g_WMessages[0]), uMsg), wParam, lParam ); |
|
} |
|
else |
|
{ |
|
Msg("GameMsg - <end>\n" ); |
|
} |
|
} |
|
break; |
|
|
|
case VCREvent_GetNumberOfConsoleInputEvents: |
|
{ |
|
char val; |
|
unsigned long nEvents; |
|
|
|
VCRTrace_ReadVal( val ); |
|
VCRTrace_ReadVal( nEvents ); |
|
|
|
Msg( "GetNumberOfConsoleInputEvents (returned %d, nEvents = %d)\n", val, nEvents ); |
|
} |
|
break; |
|
|
|
case VCREvent_ReadConsoleInput: |
|
{ |
|
char val; |
|
unsigned long nRead; |
|
INPUT_RECORD recs[1024]; |
|
|
|
VCRTrace_ReadVal( val ); |
|
if ( val ) |
|
{ |
|
VCRTrace_ReadVal( nRead ); |
|
VCRTrace_Read( recs, nRead * sizeof( INPUT_RECORD ) ); |
|
} |
|
else |
|
{ |
|
nRead = 0; |
|
} |
|
|
|
Msg( "ReadConsoleInput (returned %d, nRead = %d)\n", val, nRead ); |
|
} |
|
break; |
|
|
|
case VCREvent_GetKeyState: |
|
{ |
|
short ret; |
|
VCRTrace_ReadVal( ret ); |
|
Msg( "VCREvent_GetKeyState: %d\n", ret ); |
|
} |
|
break; |
|
|
|
case VCREvent_recv: |
|
{ |
|
int ret; |
|
|
|
// Get the result from our file. |
|
VCRTrace_ReadVal( ret ); |
|
if ( ret == SOCKET_ERROR ) |
|
{ |
|
int err; |
|
VCRTrace_ReadVal( err ); |
|
Msg( "VCREvent_recv - SOCKET_ERROR - %d\n", err ); |
|
} |
|
else |
|
{ |
|
CUtlVector<char> dummyData; |
|
dummyData.SetSize( ret ); |
|
VCRTrace_Read( dummyData.Base(), ret ); |
|
Msg( "VCREvent_recv - size %d", ret ); |
|
} |
|
} |
|
break; |
|
|
|
case VCREvent_send: |
|
{ |
|
int ret; |
|
|
|
// Get the result from our file. |
|
VCRTrace_ReadVal( ret ); |
|
if ( ret == SOCKET_ERROR ) |
|
{ |
|
int err; |
|
VCRTrace_ReadVal(err); |
|
Msg( "VCREvent_send - SOCKET_ERROR - %d\n", err ); |
|
} |
|
else |
|
{ |
|
Msg( "VCREvent_send - %d\n", ret ); |
|
} |
|
} |
|
break; |
|
|
|
case VCREvent_Generic: |
|
{ |
|
unsigned char nameLen; |
|
VCRTrace_ReadVal( nameLen ); |
|
char testName[512] = "(none)"; |
|
|
|
if ( nameLen != 255 ) |
|
{ |
|
VCRTrace_Read( testName, nameLen ); |
|
} |
|
|
|
int dataLen; |
|
VCRTrace_ReadVal( dataLen ); |
|
|
|
CUtlVector<char> tempData; |
|
tempData.SetSize( dataLen ); |
|
VCRTrace_Read( tempData.Base(), dataLen ); |
|
|
|
Msg( "VCREvent_Generic (name: %s, len: %d)\n", testName, dataLen ); |
|
} |
|
break; |
|
|
|
case VCREvent_CreateThread: |
|
{ |
|
Msg( "VCREvent_CreateThread\n" ); |
|
} |
|
break; |
|
|
|
case VCREvent_WaitForSingleObject: |
|
{ |
|
char val; |
|
VCRTrace_ReadVal( val ); |
|
|
|
Msg( "VCREvent_WaitForSingleObject " ); |
|
if ( val == 1 ) |
|
Msg( "(WAIT_OBJECT_0)\n" ); |
|
else if ( val == 2 ) |
|
Msg( "(WAIT_ABANDONED)\n" ); |
|
else |
|
Msg( "(WAIT_TIMEOUT)\n" ); |
|
} |
|
break; |
|
|
|
case VCREvent_EnterCriticalSection: |
|
{ |
|
Msg( "VCREvent_EnterCriticalSection\n" ); |
|
} |
|
break; |
|
|
|
case VCREvent_LocalTime: |
|
{ |
|
tm today; |
|
VCRTrace_ReadVal( today ); |
|
Msg( "VCREvent_LocalTime\n" ); |
|
} |
|
break; |
|
|
|
case VCREvent_Time: |
|
{ |
|
long today; |
|
VCRTrace_ReadVal( today ); |
|
Msg( "VCREvent_Time\n" ); |
|
} |
|
break; |
|
|
|
case VCREvent_GenericString: |
|
{ |
|
Msg( "VCREvent_GenericString: " ); |
|
|
|
ReadAndPrintShortString( "[%s] " ); |
|
ReadAndPrintShortString( "%s" ); |
|
Msg( "\n" ); |
|
} |
|
break; |
|
|
|
default: |
|
{ |
|
Msg( "***ERROR*** VCR_TraceEvent: invalid event" ); |
|
return; |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
SpewRetval_t MySpewOutput( SpewType_t spewType, tchar const *pMsg ) |
|
{ |
|
printf( "%s", pMsg ); |
|
OutputDebugString( pMsg ); |
|
|
|
if ( spewType == SPEW_ASSERT ) |
|
return SPEW_DEBUGGER; |
|
|
|
else if ( spewType == SPEW_ERROR ) |
|
return SPEW_ABORT; |
|
|
|
else |
|
return SPEW_CONTINUE; |
|
} |
|
|
|
|
|
int main(int argc, char* argv[]) |
|
{ |
|
if(argc <= 1) |
|
{ |
|
Msg("vcrtrace <vcr filename>\n"); |
|
return 1; |
|
} |
|
|
|
SpewOutputFunc( MySpewOutput ); |
|
|
|
g_fpTrace = fopen( argv[1], "rb" ); |
|
if ( !g_fpTrace ) |
|
{ |
|
Msg("Invalid or mission VCR file '%s'\n", argv[1]); |
|
return 1; |
|
} |
|
|
|
unsigned long version; |
|
VCRTrace_ReadVal( version ); |
|
if ( version != VCRFILE_VERSION ) |
|
{ |
|
Msg( "Invalid VCR file version (is %d, but we need %d).\n", version, VCRFILE_VERSION ); |
|
return 1; |
|
} |
|
|
|
VCR_TraceEvents(); |
|
return 0; |
|
} |
|
|
|
|