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;
|
|
}
|
|
|