1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: VCR mode records a client's game and allows you to
// play it back and reproduce it exactly. When playing it back, nothing
// is simulated on the server, but all server packets are recorded.
//
// Most of the VCR mode functionality is accomplished through hooks
// called at various points in the engine.
//
// $NoKeywords: $
//===========================================================================//
#ifndef VCRMODE_H
#define VCRMODE_H
#ifdef _WIN32
#include <process.h>
#endif
#ifdef _WIN32
#pragma once
#endif
#include "tier0/platform.h"
#include "tier0/vcr_shared.h"
#include "tier0/dbg.h"
#ifdef POSIX
DBG_INTERFACE const char *BuildCmdLine( int argc, char **argv, bool fAddSteam = true );
tchar *GetCommandLine();
#endif
#ifdef _X360
#define NO_VCR 1
#endif
// Enclose lines of code in this if you don't want anything in them written to or read from the VCR file.
#ifndef NO_VCR
#define NOVCR(x) \
{\
VCRSetEnabled(0);\
x;\
VCRSetEnabled(1);\
}
#else
#define NOVCR(x) \
{\
x;\
}
#endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct InputEvent_t;
//-----------------------------------------------------------------------------
// Definitions.
//-----------------------------------------------------------------------------
enum VCRMode_t
{
VCR_Invalid=-1,
VCR_Disabled=0,
VCR_Record,
VCR_Playback
};
//-----------------------------------------------------------------------------
// Functions.
//-----------------------------------------------------------------------------
abstract_class IVCRHelpers
{
public:
virtual void ErrorMessage( const tchar *pMsg ) = 0;
virtual void* GetMainWindow() = 0;
};
// Used by the vcrtrace program.
abstract_class IVCRTrace
{
public:
virtual VCREvent ReadEvent() = 0;
virtual void Read( void *pDest, int size ) = 0;
};
typedef struct VCR_s
{
// Start VCR record or play.
int (*Start)( tchar const *pFilename, bool bRecord, IVCRHelpers *pHelpers );
void (*End)();
// Used by the VCR trace app.
IVCRTrace* (*GetVCRTraceInterface)();
// Get the current mode the VCR is in.
VCRMode_t (*GetMode)();
// This can be used to block out areas of code that are unpredictable (like things triggered by WM_TIMER messages).
// Note: this enables/disables VCR mode usage on a PER-THREAD basis. The assumption is that you're marking out
// specific sections of code that you don't want to use VCR mode inside of, but you're not intending to
// stop all the other threads from using VCR mode.
void (*SetEnabled)(int bEnabled);
// This can be called any time to put in a debug check to make sure things are synchronized.
void (*SyncToken)(tchar const *pToken);
// Hook for Sys_FloatTime().
double (*Hook_Sys_FloatTime)(double time);
// Note: this makes no guarantees about msg.hwnd being the same on playback. If it needs to be, then we need to add
// an ID system for Windows and store the ID like in Goldsrc.
int (*Hook_PeekMessage)(
struct tagMSG *msg,
void *hWnd,
unsigned int wMsgFilterMin,
unsigned int wMsgFilterMax,
unsigned int wRemoveMsg
);
// Call this to record game messages.
void (*Hook_RecordGameMsg)( const InputEvent_t &event );
void (*Hook_RecordEndGameMsg)();
// Call this to playback game messages until it returns false.
bool (*Hook_PlaybackGameMsg)( InputEvent_t *pEvent );
// Hook for recvfrom() calls. This replaces the recvfrom() call.
int (*Hook_recvfrom)(int s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen);
void (*Hook_GetCursorPos)(struct tagPOINT *pt);
void (*Hook_ScreenToClient)(void *hWnd, struct tagPOINT *pt);
void (*Hook_Cmd_Exec)(tchar **f);
tchar* (*Hook_GetCommandLine)();
// Registry hooks.
long (*Hook_RegOpenKeyEx)( void *hKey, const tchar *lpSubKey, unsigned long ulOptions, unsigned long samDesired, void *pHKey );
long (*Hook_RegSetValueEx)(void *hKey, tchar const *lpValueName, unsigned long Reserved, unsigned long dwType, uint8 const *lpData, unsigned long cbData);
long (*Hook_RegQueryValueEx)(void *hKey, tchar const *lpValueName, unsigned long *lpReserved, unsigned long *lpType, uint8 *lpData, unsigned long *lpcbData);
long (*Hook_RegCreateKeyEx)(void *hKey, tchar const *lpSubKey, unsigned long Reserved, tchar *lpClass, unsigned long dwOptions, unsigned long samDesired, void *lpSecurityAttributes, void *phkResult, unsigned long *lpdwDisposition);
void (*Hook_RegCloseKey)(void *hKey);
// hInput is a HANDLE.
int (*Hook_GetNumberOfConsoleInputEvents)( void *hInput, unsigned long *pNumEvents );
// hInput is a HANDLE.
// pRecs is an INPUT_RECORD pointer.
int (*Hook_ReadConsoleInput)( void *hInput, void *pRecs, int nMaxRecs, unsigned long *pNumRead );
// This calls time() then gives you localtime()'s result.
void (*Hook_LocalTime)( struct tm *today );
short (*Hook_GetKeyState)( int nVirtKey );
// TCP calls.
int (*Hook_recv)( int s, char *buf, int len, int flags );
int (*Hook_send)( int s, const char *buf, int len, int flags );
// These can be used to add events without having to modify VCR mode.
// pEventName is used for verification to make sure it's playing back correctly.
// If pEventName is null, then verification is not performed.
void (*GenericRecord)( const tchar *pEventName, const void *pData, int len );
// Returns the number of bytes written in the generic event.
// If bForceLenSame is true, then it will error out unless the value in the VCR file is the same as maxLen.
int (*GenericPlayback)( const tchar *pEventName, void *pOutData, int maxLen, bool bForceLenSame );
// If you just want to record and playback a value and not worry about whether or not you're
// recording or playing back, use this. It also will do nothing if you're not recording or playing back.
//
// NOTE: also see GenericValueVerify, which allows you to have it VERIFY that pData's contents are the same upon playback
// (rather than just copying whatever is in the VCR file into pData).
void (*GenericValue)( const tchar *pEventName, void *pData, int maxLen );
// Get the current percent (0.0 - 1.0) that it's played back through the file (only valid in playback).
double (*GetPercentCompleted)();
// If you use this, then any VCR stuff the thread does will work with VCR mode.
// This mirrors the Windows API CreateThread function and returns a HANDLE the same way.
void* (*Hook_CreateThread)(
void *lpThreadAttributes,
unsigned long dwStackSize,
void *lpStartAddress,
void *lpParameter,
unsigned long dwCreationFlags,
unsigned long *lpThreadID );
unsigned long (*Hook_WaitForSingleObject)(
void *handle,
unsigned long dwMilliseconds );
void (*Hook_EnterCriticalSection)( void *pCS );
void (*Hook_Time)( long *pTime );
// String value. Playback just verifies that the incoming string is the same as it was when recording.
void (*GenericString)( const char *pEventName, const char *pString );
// Works like GenericValue, except upon playback it will verify that pData's contents are the same as it was during recording.
void (*GenericValueVerify)( const tchar *pEventName, const void *pData, int maxLen );
unsigned long (*Hook_WaitForMultipleObjects)( uint32 nHandles, const void **pHandles, int bWaitAll, uint32 timeout );
} VCR_t;
#ifndef NO_VCR
// In the launcher, this is created by vcrmode.c.
// In the engine, this is set when the launcher initializes its DLL.
PLATFORM_INTERFACE VCR_t *g_pVCR;
#endif
#ifndef NO_VCR
#define VCRStart g_pVCR->Start
#define VCREnd g_pVCR->End
#define VCRGetVCRTraceInterface g_pVCR->GetVCRTraceInterface
#define VCRGetMode g_pVCR->GetMode
#define VCRSetEnabled g_pVCR->SetEnabled
#define VCRSyncToken g_pVCR->SyncToken
#define VCRGenericString g_pVCR->GenericString
#define VCRGenericValueVerify g_pVCR->GenericValueVerify
#define VCRHook_Sys_FloatTime g_pVCR->Hook_Sys_FloatTime
#define VCRHook_PeekMessage g_pVCR->Hook_PeekMessage
#define VCRHook_RecordGameMsg g_pVCR->Hook_RecordGameMsg
#define VCRHook_RecordEndGameMsg g_pVCR->Hook_RecordEndGameMsg
#define VCRHook_PlaybackGameMsg g_pVCR->Hook_PlaybackGameMsg
#define VCRHook_recvfrom g_pVCR->Hook_recvfrom
#define VCRHook_GetCursorPos g_pVCR->Hook_GetCursorPos
#define VCRHook_ScreenToClient g_pVCR->Hook_ScreenToClient
#define VCRHook_Cmd_Exec g_pVCR->Hook_Cmd_Exec
#define VCRHook_GetCommandLine g_pVCR->Hook_GetCommandLine
#define VCRHook_RegOpenKeyEx g_pVCR->Hook_RegOpenKeyEx
#define VCRHook_RegSetValueEx g_pVCR->Hook_RegSetValueEx
#define VCRHook_RegQueryValueEx g_pVCR->Hook_RegQueryValueEx
#define VCRHook_RegCreateKeyEx g_pVCR->Hook_RegCreateKeyEx
#define VCRHook_RegCloseKey g_pVCR->Hook_RegCloseKey
#define VCRHook_GetNumberOfConsoleInputEvents g_pVCR->Hook_GetNumberOfConsoleInputEvents
#define VCRHook_ReadConsoleInput g_pVCR->Hook_ReadConsoleInput
#define VCRHook_LocalTime g_pVCR->Hook_LocalTime
#define VCRHook_GetKeyState g_pVCR->Hook_GetKeyState
#define VCRHook_recv g_pVCR->Hook_recv
#define VCRHook_send g_pVCR->Hook_send
#define VCRGenericRecord g_pVCR->GenericRecord
#define VCRGenericPlayback g_pVCR->GenericPlayback
#define VCRGenericValue g_pVCR->GenericValue
#define VCRGetPercentCompleted g_pVCR->GetPercentCompleted
#define VCRHook_CreateThread g_pVCR->Hook_CreateThread
#define VCRHook_WaitForSingleObject g_pVCR->Hook_WaitForSingleObject
#define VCRHook_EnterCriticalSection g_pVCR->Hook_EnterCriticalSection
#define VCRHook_Time g_pVCR->Hook_Time
#define VCRHook_WaitForMultipleObjects( a, b, c, d) g_pVCR->Hook_WaitForMultipleObjects( a, (const void **)b, c, d)
#else
#define VCRStart( a, b, c ) (1)
#define VCREnd ((void)(0))
#define VCRGetVCRTraceInterface (NULL)
#define VCRGetMode() (VCR_Disabled)
#define VCRSetEnabled( a ) ((void)(0))
#define VCRSyncToken( a ) ((void)(0))
#define VCRGenericRecord MUST_IFDEF_OUT_GenericRecord
#define VCRGenericPlayback MUST_IFDEF_OUT_GenericPlayback
#define VCRGenericValue MUST_IFDEF_OUT_GenericValue
#define VCRGenericString MUST_IFDEF_OUT_GenericString
#define VCRGenericValueVerify MUST_IFDEF_OUT_GenericValueVerify
#define VCRGetPercentCompleted() (0.0f)
#define VCRHook_Sys_FloatTime Sys_FloatTime
#define VCRHook_PeekMessage PeekMessage
#define VCRHook_RecordGameMsg RecordGameMsg
#define VCRHook_RecordEndGameMsg RecordEndGameMsg
#define VCRHook_PlaybackGameMsg PlaybackGameMsg
#define VCRHook_recvfrom recvfrom
#define VCRHook_GetCursorPos GetCursorPos
#define VCRHook_ScreenToClient ScreenToClient
#define VCRHook_Cmd_Exec( a ) ((void)(0))
#define VCRHook_GetCommandLine GetCommandLine
#define VCRHook_RegOpenKeyEx RegOpenKeyEx
#define VCRHook_RegSetValueEx RegSetValueEx
#define VCRHook_RegQueryValueEx RegQueryValueEx
#define VCRHook_RegCreateKeyEx RegCreateKeyEx
#define VCRHook_RegCloseKey RegCloseKey
#define VCRHook_GetNumberOfConsoleInputEvents GetNumberOfConsoleInputEvents
#define VCRHook_ReadConsoleInput ReadConsoleInput
#define VCRHook_LocalTime( a ) memset(a, 0, sizeof(*a));
#define VCRHook_GetKeyState GetKeyState
#define VCRHook_recv recv
#define VCRHook_send send
#if defined( _X360 )
#define VCRHook_CreateThread CreateThread
#else
#define VCRHook_CreateThread (void*)_beginthreadex
#endif
#define VCRHook_WaitForSingleObject WaitForSingleObject
#define VCRHook_EnterCriticalSection EnterCriticalSection
#define VCRHook_WaitForMultipleObjects( a, b, c, d) WaitForMultipleObjects( a, (const HANDLE *)b, c, d)
#define VCRHook_Time Time
#endif
#endif // VCRMODE_H
|