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.

970 lines
19 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include <time.h>
  9. #include <assert.h>
  10. #include <stdio.h>
  11. #include <stdarg.h>
  12. #include <string.h>
  13. #include <errno.h>
  14. #include <stdlib.h>
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include "tier0/threadtools.h"
  18. #define PROTECTED_THINGS_DISABLE
  19. #include "tier0/vcrmode.h"
  20. #include "tier0/dbg.h"
  21. #include "extendedtrace.h"
  22. // FIXME: We totally have a bad tier dependency here
  23. #include "inputsystem/InputEnums.h"
  24. #define VCRFILE_VERSION 2
  25. #define VCR_RuntimeAssert(x) VCR_RuntimeAssertFn(x, #x)
  26. #define PvAlloc malloc
  27. bool g_bExpectingWindowProcCalls = false;
  28. IVCRHelpers *g_pHelpers = 0;
  29. FILE *g_pVCRFile = NULL;
  30. VCRMode_t g_VCRMode = VCR_Disabled;
  31. VCRMode_t g_OldVCRMode = (VCRMode_t)-1; // Stored temporarily between SetEnabled(0)/SetEnabled(1) blocks.
  32. int g_iCurEvent = 0;
  33. int g_CurFilePos = 0; // So it knows when we're done playing back.
  34. int g_FileLen = 0;
  35. VCREvent g_LastReadEvent = (VCREvent)-1; // Last VCR_ReadEvent() call.
  36. int g_bVCREnabled = 0;
  37. // ---------------------------------------------------------------------- //
  38. // Internal functions.
  39. // ---------------------------------------------------------------------- //
  40. static void VCR_Error( const char *pFormat, ... )
  41. {
  42. #if defined( _DEBUG )
  43. DebuggerBreak();
  44. #endif
  45. char str[256];
  46. va_list marker;
  47. va_start( marker, pFormat );
  48. _snprintf( str, sizeof( str ), pFormat, marker );
  49. va_end( marker );
  50. g_pHelpers->ErrorMessage( str );
  51. VCREnd();
  52. }
  53. static void VCR_RuntimeAssertFn(int bAssert, char const *pStr)
  54. {
  55. if(!bAssert)
  56. {
  57. VCR_Error( "*** VCR ASSERT FAILED: %s ***\n", pStr );
  58. }
  59. }
  60. static void VCR_Read(void *pDest, int size)
  61. {
  62. if(!g_pVCRFile)
  63. {
  64. memset(pDest, 0, size);
  65. return;
  66. }
  67. fread(pDest, 1, size, g_pVCRFile);
  68. g_CurFilePos += size;
  69. VCR_RuntimeAssert(g_CurFilePos <= g_FileLen);
  70. if(g_CurFilePos >= g_FileLen)
  71. {
  72. VCREnd();
  73. }
  74. }
  75. template<class T>
  76. static void VCR_ReadVal(T &val)
  77. {
  78. VCR_Read(&val, sizeof(val));
  79. }
  80. static void VCR_Write(void const *pSrc, int size)
  81. {
  82. fwrite(pSrc, 1, size, g_pVCRFile);
  83. fflush(g_pVCRFile);
  84. }
  85. template<class T>
  86. static void VCR_WriteVal(T &val)
  87. {
  88. VCR_Write(&val, sizeof(val));
  89. }
  90. // Hook from ExtendedTrace.cpp
  91. bool g_bTraceRead = false;
  92. void OutputDebugStringFormat( const char *pMsg, ... )
  93. {
  94. char msg[4096];
  95. va_list marker;
  96. va_start( marker, pMsg );
  97. _vsnprintf( msg, sizeof( msg )-1, pMsg, marker );
  98. va_end( marker );
  99. int len = strlen( msg );
  100. if ( g_bTraceRead )
  101. {
  102. char tempData[4096];
  103. int tempLen;
  104. VCR_ReadVal( tempLen );
  105. VCR_RuntimeAssert( tempLen <= sizeof( tempData ) );
  106. VCR_Read( tempData, tempLen );
  107. tempData[tempLen] = 0;
  108. fprintf( stderr, "FILE: " );
  109. fprintf( stderr, "%s", tempData );
  110. VCR_RuntimeAssert( memcmp( msg, tempData, len ) == 0 );
  111. }
  112. else
  113. {
  114. VCR_WriteVal( len );
  115. VCR_Write( msg, len );
  116. }
  117. }
  118. static VCREvent VCR_ReadEvent()
  119. {
  120. g_bTraceRead = true;
  121. //STACKTRACE();
  122. char event;
  123. VCR_Read(&event, 1);
  124. g_LastReadEvent = (VCREvent)event;
  125. return (VCREvent)event;
  126. }
  127. static void VCR_WriteEvent(VCREvent event)
  128. {
  129. g_bTraceRead = false;
  130. //STACKTRACE();
  131. // Write a stack trace.
  132. char cEvent = (char)event;
  133. VCR_Write(&cEvent, 1);
  134. }
  135. static void VCR_IncrementEvent()
  136. {
  137. ++g_iCurEvent;
  138. }
  139. static void VCR_Event(VCREvent type)
  140. {
  141. if(g_VCRMode == VCR_Disabled)
  142. return;
  143. VCR_IncrementEvent();
  144. if(g_VCRMode == VCR_Record)
  145. {
  146. VCR_WriteEvent(type);
  147. }
  148. else
  149. {
  150. VCREvent currentEvent = VCR_ReadEvent();
  151. VCR_RuntimeAssert( currentEvent == type );
  152. }
  153. }
  154. // ---------------------------------------------------------------------- //
  155. // VCR trace interface.
  156. // ---------------------------------------------------------------------- //
  157. class CVCRTrace : public IVCRTrace
  158. {
  159. public:
  160. virtual VCREvent ReadEvent()
  161. {
  162. return VCR_ReadEvent();
  163. }
  164. virtual void Read( void *pDest, int size )
  165. {
  166. VCR_Read( pDest, size );
  167. }
  168. };
  169. static CVCRTrace g_VCRTrace;
  170. // ---------------------------------------------------------------------- //
  171. // VCR interface.
  172. // ---------------------------------------------------------------------- //
  173. static int VCR_Start( char const *pFilename, bool bRecord, IVCRHelpers *pHelpers )
  174. {
  175. unsigned long version;
  176. g_pHelpers = pHelpers;
  177. VCREnd();
  178. EXTENDEDTRACEINITIALIZE( "/tmp/hl2" );
  179. g_OldVCRMode = (VCRMode_t)-1;
  180. if(bRecord)
  181. {
  182. g_pVCRFile = fopen( pFilename, "wb" );
  183. if( g_pVCRFile )
  184. {
  185. // Write the version.
  186. version = VCRFILE_VERSION;
  187. VCR_Write(&version, sizeof(version));
  188. g_VCRMode = VCR_Record;
  189. return true;
  190. }
  191. else
  192. {
  193. return false;
  194. }
  195. }
  196. else
  197. {
  198. g_pVCRFile = fopen( pFilename, "rb" );
  199. if( g_pVCRFile )
  200. {
  201. // Get the file length.
  202. fseek(g_pVCRFile, 0, SEEK_END);
  203. g_FileLen = ftell(g_pVCRFile);
  204. fseek(g_pVCRFile, 0, SEEK_SET);
  205. g_CurFilePos = 0;
  206. // Verify the file version.
  207. VCR_Read(&version, sizeof(version));
  208. if(version != VCRFILE_VERSION)
  209. {
  210. assert(!"VCR_Start: invalid file version");
  211. VCREnd();
  212. return FALSE;
  213. }
  214. g_VCRMode = VCR_Playback;
  215. return TRUE;
  216. }
  217. else
  218. {
  219. return FALSE;
  220. }
  221. }
  222. }
  223. static void VCR_End()
  224. {
  225. if(g_pVCRFile)
  226. {
  227. fclose(g_pVCRFile);
  228. g_pVCRFile = NULL;
  229. }
  230. g_VCRMode = VCR_Disabled;
  231. EXTENDEDTRACEUNINITIALIZE();
  232. }
  233. static IVCRTrace* VCR_GetVCRTraceInterface()
  234. {
  235. return &g_VCRTrace;
  236. }
  237. static VCRMode_t VCR_GetMode()
  238. {
  239. return g_VCRMode;
  240. }
  241. static void VCR_SetEnabled(int bEnabled)
  242. {
  243. if(bEnabled)
  244. {
  245. VCR_RuntimeAssert(g_OldVCRMode != (VCRMode_t)-1);
  246. g_VCRMode = g_OldVCRMode;
  247. g_OldVCRMode = (VCRMode_t)-1;
  248. }
  249. else
  250. {
  251. VCR_RuntimeAssert(g_OldVCRMode == (VCRMode_t)-1);
  252. g_OldVCRMode = g_VCRMode;
  253. g_VCRMode = VCR_Disabled;
  254. }
  255. }
  256. static void VCR_SyncToken(char const *pToken)
  257. {
  258. unsigned char len;
  259. VCR_Event(VCREvent_SyncToken);
  260. if(g_VCRMode == VCR_Record)
  261. {
  262. int intLen = strlen( pToken );
  263. assert( intLen <= 255 );
  264. len = (unsigned char)intLen;
  265. VCR_Write(&len, 1);
  266. VCR_Write(pToken, len);
  267. }
  268. else if(g_VCRMode == VCR_Playback)
  269. {
  270. char test[256];
  271. VCR_Read(&len, 1);
  272. VCR_Read(test, len);
  273. VCR_RuntimeAssert( len == (unsigned char)strlen(pToken) );
  274. VCR_RuntimeAssert( memcmp(pToken, test, len) == 0 );
  275. }
  276. }
  277. static double VCR_Hook_Sys_FloatTime(double time)
  278. {
  279. VCR_Event(VCREvent_Sys_FloatTime);
  280. if(g_VCRMode == VCR_Record)
  281. {
  282. VCR_Write(&time, sizeof(time));
  283. }
  284. else if(g_VCRMode == VCR_Playback)
  285. {
  286. VCR_Read(&time, sizeof(time));
  287. }
  288. return time;
  289. }
  290. static int VCR_Hook_PeekMessage(
  291. struct tagMSG *msg,
  292. void *hWnd,
  293. unsigned int wMsgFilterMin,
  294. unsigned int wMsgFilterMax,
  295. unsigned int wRemoveMsg
  296. )
  297. {
  298. Assert( "VCR_Hook_PeekMessage unsupported" );
  299. return 0;
  300. }
  301. void VCR_Hook_RecordGameMsg( const InputEvent_t& event )
  302. {
  303. if ( g_VCRMode == VCR_Record )
  304. {
  305. VCR_Event( VCREvent_GameMsg );
  306. char val = 1;
  307. VCR_WriteVal( val );
  308. VCR_WriteVal( event.m_nType );
  309. VCR_WriteVal( event.m_nData );
  310. VCR_WriteVal( event.m_nData2 );
  311. VCR_WriteVal( event.m_nData3 );
  312. }
  313. }
  314. void VCR_Hook_RecordEndGameMsg()
  315. {
  316. if ( g_VCRMode == VCR_Record )
  317. {
  318. VCR_Event( VCREvent_GameMsg );
  319. char val = 0;
  320. VCR_WriteVal( val ); // record that there are no more messages.
  321. }
  322. }
  323. bool VCR_Hook_PlaybackGameMsg( InputEvent_t* pEvent )
  324. {
  325. if ( g_VCRMode == VCR_Playback )
  326. {
  327. VCR_Event( VCREvent_GameMsg );
  328. char bMsg;
  329. VCR_ReadVal( bMsg );
  330. if ( bMsg )
  331. {
  332. VCR_ReadVal( pEvent->m_nType );
  333. VCR_ReadVal( pEvent->m_nData );
  334. VCR_ReadVal( pEvent->m_nData2 );
  335. VCR_ReadVal( pEvent->m_nData3 );
  336. return true;
  337. }
  338. }
  339. return false;
  340. }
  341. static void VCR_Hook_GetCursorPos(struct tagPOINT *pt)
  342. {
  343. Assert( "VCR_Hook_GetCursorPos unsupported" );
  344. }
  345. static void VCR_Hook_ScreenToClient(void *hWnd, struct tagPOINT *pt)
  346. {
  347. Assert( "VCR_Hook_GetCursorPos unsupported" );
  348. }
  349. static int VCR_Hook_recvfrom(int s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
  350. {
  351. VCR_Event(VCREvent_recvfrom);
  352. int ret;
  353. if ( g_VCRMode == VCR_Playback )
  354. {
  355. // Get the result from our file.
  356. VCR_Read(&ret, sizeof(ret));
  357. if(ret == -1)
  358. {
  359. int err;
  360. VCR_ReadVal(err);
  361. errno = err;
  362. }
  363. else
  364. {
  365. VCR_Read( buf, ret );
  366. char bFrom;
  367. VCR_ReadVal( bFrom );
  368. if ( bFrom )
  369. {
  370. VCR_Read( from, *fromlen );
  371. }
  372. }
  373. }
  374. else
  375. {
  376. ret = recvfrom(s, buf, len, flags, from, (socklen_t *)(fromlen));
  377. if ( g_VCRMode == VCR_Record )
  378. {
  379. // Record the result.
  380. VCR_Write(&ret, sizeof(ret));
  381. if(ret == -1)
  382. {
  383. VCR_WriteVal(errno);
  384. }
  385. else
  386. {
  387. VCR_Write( buf, ret );
  388. char bFrom = !!from;
  389. VCR_WriteVal( bFrom );
  390. if ( bFrom )
  391. VCR_Write( from, *fromlen );
  392. }
  393. }
  394. }
  395. return ret;
  396. }
  397. static void VCR_Hook_Cmd_Exec(char **f)
  398. {
  399. VCR_Event(VCREvent_Cmd_Exec);
  400. if(g_VCRMode == VCR_Playback)
  401. {
  402. int len;
  403. VCR_Read(&len, sizeof(len));
  404. if(len == -1)
  405. {
  406. *f = NULL;
  407. }
  408. else
  409. {
  410. *f = (char*)PvAlloc(len);
  411. VCR_Read(*f, len);
  412. }
  413. }
  414. else if(g_VCRMode == VCR_Record)
  415. {
  416. int len;
  417. char *str = *f;
  418. if(str)
  419. {
  420. len = strlen(str)+1;
  421. VCR_Write(&len, sizeof(len));
  422. VCR_Write(str, len);
  423. }
  424. else
  425. {
  426. len = -1;
  427. VCR_Write(&len, sizeof(len));
  428. }
  429. }
  430. }
  431. #define MAX_LINUX_CMDLINE 512
  432. static char linuxCmdline[ MAX_LINUX_CMDLINE +7 ]; // room for -steam
  433. const char * BuildCmdLine( int argc, char **argv, bool fAddSteam )
  434. {
  435. int len;
  436. int i;
  437. for (len = 0, i = 0; i < argc; i++)
  438. {
  439. len += strlen(argv[i]);
  440. }
  441. if ( len > MAX_LINUX_CMDLINE )
  442. {
  443. printf( "command line too long, %i max\n", MAX_LINUX_CMDLINE );
  444. exit(-1);
  445. return "";
  446. }
  447. linuxCmdline[0] = '\0';
  448. for ( i = 0; i < argc; i++ )
  449. {
  450. if ( i > 0 )
  451. {
  452. strcat( linuxCmdline, " " );
  453. }
  454. strcat( linuxCmdline, argv[ i ] );
  455. }
  456. if( fAddSteam )
  457. {
  458. strcat( linuxCmdline, " -steam" );
  459. }
  460. return linuxCmdline;
  461. }
  462. char *GetCommandLine()
  463. {
  464. return linuxCmdline;
  465. }
  466. static char* VCR_Hook_GetCommandLine()
  467. {
  468. VCR_Event(VCREvent_CmdLine);
  469. int len;
  470. char *ret;
  471. if(g_VCRMode == VCR_Playback)
  472. {
  473. VCR_Read(&len, sizeof(len));
  474. ret = new char[len];
  475. VCR_Read(ret, len);
  476. }
  477. else
  478. {
  479. ret = GetCommandLine();
  480. if(g_VCRMode == VCR_Record)
  481. {
  482. len = strlen(ret) + 1;
  483. VCR_WriteVal(len);
  484. VCR_Write(ret, len);
  485. }
  486. }
  487. return ret;
  488. }
  489. static long VCR_Hook_RegOpenKeyEx( void *hKey, const char *lpSubKey, unsigned long ulOptions, unsigned long samDesired, void *pHKey )
  490. {
  491. Assert( "VCR_Hook_RegOpenKeyEx unsupported" );
  492. return 0;
  493. }
  494. static long VCR_Hook_RegSetValueEx(void *hKey, char const *lpValueName, unsigned long Reserved, unsigned long dwType, unsigned char const *lpData, unsigned long cbData)
  495. {
  496. Assert( "VCR_Hook_RegSetValueEx unsupported" );
  497. return 0;
  498. }
  499. static long VCR_Hook_RegQueryValueEx(void *hKey, char const *lpValueName, unsigned long *lpReserved, unsigned long *lpType, unsigned char *lpData, unsigned long *lpcbData)
  500. {
  501. Assert( "VCR_Hook_RegQueryValueEx unsupported" );
  502. return 0;
  503. }
  504. static long VCR_Hook_RegCreateKeyEx(void *hKey, char const *lpSubKey, unsigned long Reserved, char *lpClass, unsigned long dwOptions,
  505. unsigned long samDesired, void *lpSecurityAttributes, void *phkResult, unsigned long *lpdwDisposition)
  506. {
  507. Assert( "VCR_Hook_RegCreateKeyEx unsupported" );
  508. return 0;
  509. }
  510. static void VCR_Hook_RegCloseKey(void *hKey)
  511. {
  512. Assert( "VCR_Hook_RegCloseKey unsupported" );
  513. }
  514. int VCR_Hook_GetNumberOfConsoleInputEvents( void *hInput, unsigned long *pNumEvents )
  515. {
  516. VCR_Event( VCREvent_GetNumberOfConsoleInputEvents );
  517. char ret;
  518. if ( g_VCRMode == VCR_Playback )
  519. {
  520. VCR_ReadVal( ret );
  521. VCR_ReadVal( *pNumEvents );
  522. }
  523. else
  524. {
  525. ret = 1;
  526. if ( g_VCRMode == VCR_Record )
  527. {
  528. VCR_WriteVal( ret );
  529. VCR_WriteVal( *pNumEvents );
  530. }
  531. }
  532. return ret;
  533. }
  534. int VCR_Hook_ReadConsoleInput( void *hInput, void *pRecs, int nMaxRecs, unsigned long *pNumRead )
  535. {
  536. Assert( "VCR_Hook_ReadConsoleInput unsupported" );
  537. return 0;
  538. }
  539. void VCR_Hook_LocalTime( struct tm *today )
  540. {
  541. // We just provide a wrapper on this function so we can protect access to time() everywhere.
  542. time_t ltime;
  543. time( &ltime );
  544. tm *pTime = localtime( &ltime );
  545. memcpy( today, pTime, sizeof( *today ) );
  546. }
  547. short VCR_Hook_GetKeyState( int nVirtKey )
  548. {
  549. Assert( "VCREvent_GetKeyState unsupported" );
  550. return 0;
  551. }
  552. void VCR_GenericRecord( const char *pEventName, const void *pData, int len )
  553. {
  554. VCR_Event( VCREvent_Generic );
  555. if ( g_VCRMode != VCR_Record )
  556. Error( "VCR_GenericRecord( %s ): not recording a VCR file", pEventName );
  557. // Write the event name (or 255 if none).
  558. int nameLen = 255;
  559. if ( pEventName )
  560. {
  561. nameLen = strlen( pEventName ) + 1;
  562. if ( nameLen >= 255 )
  563. {
  564. VCR_Error( "VCR_GenericRecord( %s ): nameLen too long (%d)", pEventName, nameLen );
  565. return;
  566. }
  567. }
  568. unsigned char ucNameLen = (unsigned char)nameLen;
  569. VCR_WriteVal( ucNameLen );
  570. VCR_Write( pEventName, ucNameLen );
  571. // Write the data.
  572. VCR_WriteVal( len );
  573. VCR_Write( pData, len );
  574. }
  575. int VCR_GenericPlayback( const char *pEventName, void *pOutData, int maxLen, bool bForceSameLen )
  576. {
  577. VCR_Event( VCREvent_Generic );
  578. if ( g_VCRMode != VCR_Playback )
  579. Error( "VCR_Playback( %s ): not playing back a VCR file", pEventName );
  580. unsigned char nameLen;
  581. VCR_ReadVal( nameLen );
  582. if ( nameLen != 255 )
  583. {
  584. char testName[512];
  585. VCR_Read( testName, nameLen );
  586. if ( strcmp( pEventName, testName ) != 0 )
  587. {
  588. VCR_Error( "VCR_GenericPlayback( %s ) - event name does not match '%s'", pEventName, testName );
  589. return 0;
  590. }
  591. }
  592. int dataLen;
  593. VCR_ReadVal( dataLen );
  594. if ( dataLen > maxLen )
  595. {
  596. VCR_Error( "VCR_GenericPlayback( %s ) - generic data too long (greater than maxLen: %d)", pEventName, maxLen );
  597. return 0;
  598. }
  599. else if ( bForceSameLen && dataLen != maxLen )
  600. {
  601. VCR_Error( "VCR_GenericPlayback( %s ) - data size in file (%d) different than desired (%d)", pEventName, dataLen, maxLen );
  602. return 0;
  603. }
  604. VCR_Read( pOutData, dataLen );
  605. return dataLen;
  606. }
  607. void VCR_GenericValue( const char *pEventName, void *pData, int maxLen )
  608. {
  609. if ( g_VCRMode == VCR_Record )
  610. VCR_GenericRecord( pEventName, pData, maxLen );
  611. else if ( g_VCRMode == VCR_Playback )
  612. VCR_GenericPlayback( pEventName, pData, maxLen, true );
  613. }
  614. static int VCR_Hook_recv(int s, char *buf, int len, int flags)
  615. {
  616. VCR_Event(VCREvent_recv);
  617. int ret;
  618. if ( g_VCRMode == VCR_Playback )
  619. {
  620. // Get the result from our file.
  621. VCR_Read(&ret, sizeof(ret));
  622. if(ret == -1)
  623. {
  624. int err;
  625. VCR_ReadVal(err);
  626. errno = err;
  627. }
  628. else
  629. {
  630. VCR_Read( buf, ret );
  631. }
  632. }
  633. else
  634. {
  635. ret = recv( s, buf, len, flags );
  636. if ( g_VCRMode == VCR_Record )
  637. {
  638. // Record the result.
  639. VCR_Write(&ret, sizeof(ret));
  640. if(ret == -1)
  641. {
  642. VCR_WriteVal(errno);
  643. }
  644. else
  645. {
  646. VCR_Write( buf, ret );
  647. }
  648. }
  649. }
  650. return ret;
  651. }
  652. static int VCR_Hook_send(int s, const char *buf, int len, int flags)
  653. {
  654. VCR_Event(VCREvent_send);
  655. int ret;
  656. if ( g_VCRMode == VCR_Playback )
  657. {
  658. // Get the result from our file.
  659. VCR_Read(&ret, sizeof(ret));
  660. if(ret == -1)
  661. {
  662. int err;
  663. VCR_ReadVal(err);
  664. errno = err;
  665. }
  666. }
  667. else
  668. {
  669. ret = send( s, buf, len, flags );
  670. if ( g_VCRMode == VCR_Record )
  671. {
  672. // Record the result.
  673. VCR_Write(&ret, sizeof(ret));
  674. if(ret == -1)
  675. {
  676. VCR_WriteVal(errno);
  677. }
  678. }
  679. }
  680. return ret;
  681. }
  682. double VCR_GetPercentCompleted()
  683. {
  684. if ( g_VCRMode == VCR_Playback )
  685. {
  686. return (double)g_CurFilePos / g_FileLen;
  687. }
  688. else
  689. {
  690. return 0;
  691. }
  692. }
  693. void* VCR_CreateThread(
  694. void *lpThreadAttributes,
  695. unsigned long dwStackSize,
  696. void *lpStartAddress,
  697. void *lpParameter,
  698. unsigned long dwCreationFlags,
  699. unsigned long *lpThreadID )
  700. {
  701. return CreateSimpleThread( (ThreadFunc_t)lpStartAddress, lpParameter, lpThreadID, 0 );
  702. }
  703. unsigned long VCR_WaitForSingleObject(
  704. void *handle,
  705. unsigned long dwMilliseconds )
  706. {
  707. return -1;
  708. }
  709. unsigned long VCR_WaitForMultipleObjects( uint32 nHandles, const void **pHandles, int bWaitAll, uint32 timeout )
  710. {
  711. return -1;
  712. }
  713. void VCR_EnterCriticalSection( void *pInputCS )
  714. {
  715. }
  716. void VCR_Hook_Time( long *today )
  717. {
  718. // We just provide a wrapper on this function so we can protect access to time() everywhere.
  719. // NOTE: For 64-bit systems we should eventually get a function that takes a time_t, but we should have
  720. // until about 2038 to do that before we overflow a long.
  721. time_t curTime;
  722. time( &curTime );
  723. VCR_Event( VCREvent_Time );
  724. if ( g_VCRMode == VCR_Playback )
  725. {
  726. VCR_Read( &curTime, sizeof( curTime ) );
  727. }
  728. else if ( g_VCRMode == VCR_Record )
  729. {
  730. VCR_Write( &curTime, sizeof( curTime ) );
  731. }
  732. *today = (long)curTime;
  733. }
  734. void VCR_GenericString( const char *pEventName, const char *pString )
  735. {
  736. }
  737. void VCR_GenericValueVerify( const tchar *pEventName, const void *pData, int maxLen )
  738. {
  739. }
  740. // ---------------------------------------------------------------------- //
  741. // The global VCR interface.
  742. // ---------------------------------------------------------------------- //
  743. VCR_t g_VCR =
  744. {
  745. VCR_Start,
  746. VCR_End,
  747. VCR_GetVCRTraceInterface,
  748. VCR_GetMode,
  749. VCR_SetEnabled,
  750. VCR_SyncToken,
  751. VCR_Hook_Sys_FloatTime,
  752. VCR_Hook_PeekMessage,
  753. VCR_Hook_RecordGameMsg,
  754. VCR_Hook_RecordEndGameMsg,
  755. VCR_Hook_PlaybackGameMsg,
  756. VCR_Hook_recvfrom,
  757. VCR_Hook_GetCursorPos,
  758. VCR_Hook_ScreenToClient,
  759. VCR_Hook_Cmd_Exec,
  760. VCR_Hook_GetCommandLine,
  761. VCR_Hook_RegOpenKeyEx,
  762. VCR_Hook_RegSetValueEx,
  763. VCR_Hook_RegQueryValueEx,
  764. VCR_Hook_RegCreateKeyEx,
  765. VCR_Hook_RegCloseKey,
  766. VCR_Hook_GetNumberOfConsoleInputEvents,
  767. VCR_Hook_ReadConsoleInput,
  768. VCR_Hook_LocalTime,
  769. VCR_Hook_GetKeyState,
  770. VCR_Hook_recv,
  771. VCR_Hook_send,
  772. VCR_GenericRecord,
  773. VCR_GenericPlayback,
  774. VCR_GenericValue,
  775. VCR_GetPercentCompleted,
  776. VCR_CreateThread,
  777. VCR_WaitForSingleObject,
  778. VCR_EnterCriticalSection,
  779. VCR_Hook_Time,
  780. VCR_GenericString,
  781. VCR_GenericValueVerify,
  782. VCR_WaitForMultipleObjects,
  783. };
  784. VCR_t *g_pVCR = &g_VCR;